Created
April 12, 2022 14:56
-
-
Save heiswayi/89a26841055cf0bb8a126aa186e5eb79 to your computer and use it in GitHub Desktop.
Logger Service for Angular
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import { Logger, LogLevel, LogOutput } from './logger.service'; | |
const logMethods = ['log', 'info', 'warn', 'error']; | |
describe('Logger', () => { | |
let savedConsole: any[]; | |
let savedLevel: LogLevel; | |
let savedOutputs: LogOutput[]; | |
beforeAll(() => { | |
savedConsole = []; | |
logMethods.forEach((m) => { | |
savedConsole[m] = console[m]; | |
console[m] = () => {}; | |
}); | |
savedLevel = Logger.level; | |
savedOutputs = Logger.outputs; | |
}); | |
beforeEach(() => { | |
Logger.level = LogLevel.Debug; | |
}); | |
afterAll(() => { | |
logMethods.forEach((m) => { | |
console[m] = savedConsole[m]; | |
}); | |
Logger.level = savedLevel; | |
Logger.outputs = savedOutputs; | |
}); | |
it('should create an instance', () => { | |
expect(new Logger()).toBeTruthy(); | |
}); | |
it('should add a new LogOutput and receives log entries', () => { | |
// Arrange | |
const outputSpy = jasmine.createSpy('outputSpy'); | |
const log = new Logger('test'); | |
// Act | |
Logger.outputs.push(outputSpy); | |
log.debug('d'); | |
log.info('i'); | |
log.warn('w'); | |
log.error('e', { error: true }); | |
// Assert | |
expect(outputSpy).toHaveBeenCalled(); | |
expect(outputSpy.calls.count()).toBe(4); | |
expect(outputSpy).toHaveBeenCalledWith('test', LogLevel.Debug, 'd'); | |
expect(outputSpy).toHaveBeenCalledWith('test', LogLevel.Info, 'i'); | |
expect(outputSpy).toHaveBeenCalledWith('test', LogLevel.Warning, 'w'); | |
expect(outputSpy).toHaveBeenCalledWith('test', LogLevel.Error, 'e', { error: true }); | |
}); | |
it('should add a new LogOutput and receives only production log entries', () => { | |
// Arrange | |
const outputSpy = jasmine.createSpy('outputSpy'); | |
const log = new Logger('test'); | |
// Act | |
Logger.outputs.push(outputSpy); | |
Logger.enableProductionMode(); | |
log.debug('d'); | |
log.info('i'); | |
log.warn('w'); | |
log.error('e', { error: true }); | |
// Assert | |
expect(outputSpy).toHaveBeenCalled(); | |
expect(outputSpy.calls.count()).toBe(2); | |
expect(outputSpy).toHaveBeenCalledWith('test', LogLevel.Warning, 'w'); | |
expect(outputSpy).toHaveBeenCalledWith('test', LogLevel.Error, 'e', { error: true }); | |
}); | |
}); |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* Simple logger system with the possibility of registering custom outputs. | |
* | |
* 4 different log levels are provided, with corresponding methods: | |
* - debug : for debug information | |
* - info : for informative status of the application (success, ...) | |
* - warning : for non-critical errors that do not prevent normal application behavior | |
* - error : for critical errors that prevent normal application behavior | |
* | |
* Example usage: | |
* ``` | |
* import { Logger } from 'app/core/logger.service'; | |
* | |
* const log = new Logger('myFile'); | |
* ... | |
* log.debug('something happened'); | |
* ``` | |
* | |
* To disable debug and info logs in production, add this snippet to your root component: | |
* ``` | |
* export class AppComponent implements OnInit { | |
* ngOnInit() { | |
* if (environment.production) { | |
* Logger.enableProductionMode(); | |
* } | |
* ... | |
* } | |
* } | |
* | |
* If you want to process logs through other outputs than console, you can add LogOutput functions to Logger.outputs. | |
*/ | |
/** | |
* The possible log levels. | |
* LogLevel.Off is never emitted and only used with Logger.level property to disable logs. | |
*/ | |
export enum LogLevel { | |
Off = 0, | |
Error, | |
Warning, | |
Info, | |
Debug, | |
} | |
/** | |
* Log output handler function. | |
*/ | |
export type LogOutput = (source: string | undefined, level: LogLevel, ...objects: any[]) => void; | |
export class Logger { | |
/** | |
* Current logging level. | |
* Set it to LogLevel.Off to disable logs completely. | |
*/ | |
static level = LogLevel.Debug; | |
/** | |
* Additional log outputs. | |
*/ | |
static outputs: LogOutput[] = []; | |
/** | |
* Enables production mode. | |
* Sets logging level to LogLevel.Warning. | |
*/ | |
static enableProductionMode() { | |
Logger.level = LogLevel.Warning; | |
} | |
constructor(private source?: string) {} | |
/** | |
* Logs messages or objects with the debug level. | |
* Works the same as console.log(). | |
*/ | |
debug(...objects: any[]) { | |
this.log(console.log, LogLevel.Debug, objects); | |
} | |
/** | |
* Logs messages or objects with the info level. | |
* Works the same as console.log(). | |
*/ | |
info(...objects: any[]) { | |
this.log(console.info, LogLevel.Info, objects); | |
} | |
/** | |
* Logs messages or objects with the warning level. | |
* Works the same as console.log(). | |
*/ | |
warn(...objects: any[]) { | |
this.log(console.warn, LogLevel.Warning, objects); | |
} | |
/** | |
* Logs messages or objects with the error level. | |
* Works the same as console.log(). | |
*/ | |
error(...objects: any[]) { | |
this.log(console.error, LogLevel.Error, objects); | |
} | |
private log(func: (...args: any[]) => void, level: LogLevel, objects: any[]) { | |
if (level <= Logger.level) { | |
const log = this.source ? ['[' + this.source + ']'].concat(objects) : objects; | |
func.apply(console, log); | |
Logger.outputs.forEach((output) => output.apply(output, [this.source, level, ...objects])); | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment