-
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Fixes #63
- Loading branch information
Showing
5 changed files
with
204 additions
and
4 deletions.
There are no files selected for viewing
This file contains 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,132 @@ | ||
/** | ||
* Level of logging | ||
*/ | ||
export enum LogLevel { | ||
DEBUG = 0, | ||
INFO = 1, | ||
WARN = 2, | ||
ERROR = 3, | ||
FATAL = 4 | ||
} | ||
|
||
|
||
/** | ||
* A log record. This is the data that is passed to the transports. | ||
*/ | ||
export interface LogRecord { | ||
level: LogLevel | ||
context: string | ||
message: string | ||
timestamp: number | ||
data?: unknown | ||
} | ||
|
||
|
||
/** | ||
* A transport is a class that is responsible for actually logging the data. | ||
*/ | ||
export interface LogTransport { | ||
log(record: LogRecord): void | ||
} | ||
|
||
|
||
/** | ||
* The LogsController is responsible for managing the transports and passing | ||
* log records to them. It is a singleton. | ||
*/ | ||
export class LogsController { | ||
private transports: LogTransport[] = [] | ||
|
||
/** | ||
* Add a transport to the controller. | ||
* @param transport The transport to add | ||
*/ | ||
public register(transport: LogTransport) { | ||
this.transports.push(transport) | ||
} | ||
|
||
public log(record: LogRecord) { | ||
this.transports.forEach(transport => transport.log(record)) | ||
} | ||
} | ||
|
||
|
||
/** | ||
* The Logger class is responsible for creating a log record and passing it to | ||
* the LogsController. | ||
*/ | ||
export class Logger { | ||
/** | ||
* Initialize a new logger. | ||
* @param context The context of the logger. This is used to identify the source of the log. | ||
*/ | ||
constructor ( | ||
private context: string | ||
) {} | ||
|
||
/** | ||
* Logs a message. | ||
* @param level Log level | ||
* @param message Message to log | ||
*/ | ||
public log(level: LogLevel, message: string, data?: unknown) { | ||
Logs.log({ | ||
level, | ||
context: this.context, | ||
message, | ||
timestamp: Date.now(), | ||
data | ||
}) | ||
} | ||
|
||
/** | ||
* Debug level log. | ||
* @param message Message to log | ||
* @param data Data to log | ||
*/ | ||
public debug(message: string, data?: unknown) { | ||
this.log(LogLevel.DEBUG, message, data) | ||
} | ||
|
||
/** | ||
* Info level log. | ||
* @param message Message to log | ||
* @param data Data to log | ||
*/ | ||
public info(message: string, data?: unknown) { | ||
this.log(LogLevel.INFO, message, data) | ||
} | ||
|
||
/** | ||
* Warn level log. | ||
* @param message Message to log | ||
* @param data Data to log | ||
*/ | ||
public warn(message: string, data?: unknown) { | ||
this.log(LogLevel.WARN, message, data) | ||
} | ||
|
||
/** | ||
* Error level log. | ||
* @param message Message to log | ||
* @param data Data to log | ||
*/ | ||
public error(message: string, data?: unknown) { | ||
this.log(LogLevel.ERROR, message, data) | ||
} | ||
|
||
/** | ||
* Fatal level log. | ||
* @param message Message to log | ||
* @param data Data to log | ||
*/ | ||
public fatal(message: string, data?: unknown) { | ||
this.log(LogLevel.FATAL, message, data) | ||
} | ||
} | ||
|
||
|
||
/** | ||
* The singleton instance of the LogsController. | ||
*/ | ||
export const Logs = new LogsController() |
This file contains 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,2 +1,3 @@ | ||
export * from './Result' | ||
export * from './Event' | ||
export * from './Event' | ||
export * from './Logs' |
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
This file contains 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
This file contains 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,67 @@ | ||
import { LogRecord, Logs, LogTransport, Logger, LogLevel } from '@lib/core' | ||
|
||
|
||
class MockTransport implements LogTransport { | ||
public lastRecord: LogRecord | undefined | ||
log(record: LogRecord): void { | ||
this.lastRecord = record | ||
} | ||
} | ||
|
||
|
||
describe('LogsController', () => { | ||
describe('.register()', () => { | ||
it('should register a transport', () => { | ||
const transport = new MockTransport() | ||
const logger = new Logger('test') | ||
|
||
Logs.register(transport) | ||
logger.log(LogLevel.DEBUG, 'message', { test: 'test' }) | ||
|
||
expect(transport.lastRecord).toBeDefined() | ||
expect(transport.lastRecord?.context).toBe('test') | ||
expect(transport.lastRecord?.message).toBe('message') | ||
expect(transport.lastRecord?.level).toBe(LogLevel.DEBUG) | ||
expect(transport.lastRecord?.timestamp).toBeDefined() | ||
expect(transport.lastRecord?.data).toEqual({ test: 'test' }) | ||
}) | ||
}) | ||
}) | ||
|
||
describe('Logger', () => { | ||
const transport = new MockTransport() | ||
const logger = new Logger('test') | ||
Logs.register(transport) | ||
|
||
describe('.log()', () => { | ||
it('log a message', () => { | ||
logger.log(LogLevel.DEBUG, 'message') | ||
expect(transport.lastRecord?.level).toBe(LogLevel.DEBUG) | ||
}) | ||
|
||
it('debug level', () => { | ||
logger.debug('message') | ||
expect(transport.lastRecord?.level).toBe(LogLevel.DEBUG) | ||
}) | ||
|
||
it('info level', () => { | ||
logger.info('message') | ||
expect(transport.lastRecord?.level).toBe(LogLevel.INFO) | ||
}) | ||
|
||
it('warn level', () => { | ||
logger.warn('message') | ||
expect(transport.lastRecord?.level).toBe(LogLevel.WARN) | ||
}) | ||
|
||
it('error level', () => { | ||
logger.error('message') | ||
expect(transport.lastRecord?.level).toBe(LogLevel.ERROR) | ||
}) | ||
|
||
it('fatal level', () => { | ||
logger.fatal('message') | ||
expect(transport.lastRecord?.level).toBe(LogLevel.FATAL) | ||
}) | ||
}) | ||
}) |