Skip to content

Commit

Permalink
feat: logger (#64)
Browse files Browse the repository at this point in the history
Fixes #63
  • Loading branch information
akdasa authored Feb 18, 2023
1 parent 8cbd60c commit f39c5c8
Show file tree
Hide file tree
Showing 5 changed files with 204 additions and 4 deletions.
132 changes: 132 additions & 0 deletions lib/core/Logs.ts
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()
3 changes: 2 additions & 1 deletion lib/core/index.ts
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'
4 changes: 2 additions & 2 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@akdasa-studios/framework",
"version": "0.2.8",
"version": "0.2.9",
"description": "Framework to build every app",
"main": "dist/index.js",
"typings": "dist/index.d.ts",
Expand Down
67 changes: 67 additions & 0 deletions tests/core/Logs.spec.ts
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)
})
})
})

0 comments on commit f39c5c8

Please sign in to comment.