Fix linting in packages/logger

This commit is contained in:
Jerko Steiner 2019-09-15 16:43:38 +07:00
parent 003032c3ef
commit 8853c71a0d
19 changed files with 165 additions and 163 deletions

View File

@ -1,5 +0,0 @@
import {ILogger} from './logger/ILogger'
export interface ILoggerFactory {
getLogger(name: string): ILogger
}

View File

@ -8,5 +8,6 @@ export enum LogLevel {
} }
export function isLogLevel(value: string): value is keyof typeof LogLevel { export function isLogLevel(value: string): value is keyof typeof LogLevel {
return LogLevel.hasOwnProperty(value) && isNaN(Number(value)) return Object.prototype.hasOwnProperty
.call(LogLevel, value) && isNaN(Number(value))
} }

View File

@ -1,66 +1,5 @@
import { MessageFormatter } from './formatters' import {Logger} from './logger/Logger'
import { getDefaultParams } from './getDefaultParams'
import { ILoggerFactory } from './ILoggerFactory'
import { ILogger, Logger } from './logger'
import { isLogLevel, LogLevel } from './LogLevel'
import { ConsoleTransport } from './transports'
// logging can be configured via environment variables, for example: export interface LoggerFactory {
// `LOG='*:info,api:debug,-sql' node ...` sets all logs to info, api to debug, getLogger(name: string): Logger
// and disable all sql logs.
export interface IEnabledLoggers {
readonly [key: string]: LogLevel
}
export interface ILoggerOptions {
readonly enabledLoggers: IEnabledLoggers
}
export class LoggerFactory implements ILoggerFactory {
protected readonly defaultLogLevel: LogLevel
protected readonly loggers: {[key: string]: ILogger} = {}
getCorrelationId: () => string = () => ''
static init({
logs = getDefaultParams(),
} = {}) {
const enabledLoggers = logs.split(',').reduce((logConfig, log) => {
const [key, value] = log.split(':')
const level = value && value.toUpperCase()
logConfig[key] = isLogLevel(level) ? LogLevel[level] : LogLevel.INFO
return logConfig
}, {} as {[key: string]: LogLevel})
return new this({enabledLoggers})
}
constructor(readonly options: ILoggerOptions) {
this.defaultLogLevel = options.enabledLoggers['*'] || LogLevel.OFF
}
getLoggerLevel(name: string): LogLevel {
const {enabledLoggers} = this.options
const disabled = !!enabledLoggers['-' + name]
if (disabled) {
return LogLevel.OFF
}
return enabledLoggers[name] || this.defaultLogLevel
}
getLogger = (name: string): ILogger => {
if (this.loggers[name]) {
return this.loggers[name]
}
const level = this.getLoggerLevel(name)
const logger = this.loggers[name] = new Logger({
name,
formatters: [new MessageFormatter()],
transports: [new ConsoleTransport(level)],
})
return logger
}
} }

View File

@ -1,9 +1,9 @@
import { LogLevel } from './LogLevel' import { LogLevel } from './LogLevel'
export interface IMessage { export interface Message {
loggerName: string loggerName: string
level: LogLevel level: LogLevel
timestamp: Date timestamp: Date
message: string message: string
params: any[] params: unknown[]
} }

View File

@ -1,11 +1,12 @@
import stdMocks from 'std-mocks' import stdMocks from 'std-mocks'
import loggerFactory, { LoggerFactory } from './' import loggerFactory from './'
import { SimpleLoggerFactory } from './SimpleLoggerFactory'
describe('LoggerFactory', () => { describe('SimpleLoggerFactory', () => {
let getLogger: typeof LoggerFactory.prototype.getLogger let getLogger: typeof SimpleLoggerFactory.prototype.getLogger
beforeEach(() => { beforeEach(() => {
getLogger = LoggerFactory.init({ getLogger = SimpleLoggerFactory.init({
logs: 'test1:verbose,-test3,t4,logtest5', logs: 'test1:verbose,-test3,t4,logtest5',
}) })
.getLogger .getLogger
@ -73,10 +74,10 @@ describe('LoggerFactory', () => {
describe('create', () => { describe('create', () => {
it('creates a logger with defaults', () => { it('creates a logger with defaults', () => {
LoggerFactory.init() SimpleLoggerFactory.init()
}) })
it('logs all', () => { it('logs all', () => {
const l = LoggerFactory.init({ logs: '*' }).getLogger('test') const l = SimpleLoggerFactory.init({ logs: '*' }).getLogger('test')
l.info('test info') l.info('test info')
l.debug('test debug') l.debug('test debug')
expect((global.console.debug as any).mock.calls).toEqual([]) expect((global.console.debug as any).mock.calls).toEqual([])

View File

@ -0,0 +1,66 @@
import { MessageFormatter } from './formatters'
import { getDefaultParams } from './getDefaultParams'
import { LoggerFactory } from './LoggerFactory'
import { SimpleLogger, Logger } from './logger'
import { isLogLevel, LogLevel } from './LogLevel'
import { ConsoleTransport } from './transports'
// logging can be configured via environment variables, for example:
// `LOG='*:info,api:debug,-sql' node ...` sets all logs to info, api to debug,
// and disable all sql logs.
export interface EnabledLoggers {
readonly [key: string]: LogLevel
}
export interface LoggerOptions {
readonly enabledLoggers: EnabledLoggers
}
export class SimpleLoggerFactory implements LoggerFactory {
protected readonly defaultLogLevel: LogLevel
protected readonly loggers: {[key: string]: Logger} = {}
getCorrelationId: () => string = () => ''
static init({
logs = getDefaultParams(),
} = {}) {
const enabledLoggers = logs.split(',').reduce((logConfig, log) => {
const [key, value] = log.split(':')
const level = value && value.toUpperCase()
logConfig[key] = isLogLevel(level) ? LogLevel[level] : LogLevel.INFO
return logConfig
}, {} as {[key: string]: LogLevel})
return new this({enabledLoggers})
}
constructor(readonly options: LoggerOptions) {
this.defaultLogLevel = options.enabledLoggers['*'] || LogLevel.OFF
}
getLoggerLevel(name: string): LogLevel {
const {enabledLoggers} = this.options
const disabled = !!enabledLoggers['-' + name]
if (disabled) {
return LogLevel.OFF
}
return enabledLoggers[name] || this.defaultLogLevel
}
getLogger = (name: string): Logger => {
if (this.loggers[name]) {
return this.loggers[name]
}
const level = this.getLoggerLevel(name)
const logger = this.loggers[name] = new SimpleLogger({
name,
formatters: [new MessageFormatter()],
transports: [new ConsoleTransport(level)],
})
return logger
}
}

View File

@ -0,0 +1,5 @@
import { Message } from '../Message'
export interface Formatter {
format(message: Message): Message
}

View File

@ -1,5 +0,0 @@
import { IMessage } from '../IMessage'
export interface IFormatter {
format(message: IMessage): IMessage
}

View File

@ -1,5 +1,5 @@
import { IFormatter } from './IFormatter' import { Formatter } from './Formatter'
import { IMessage } from '../IMessage' import { Message } from '../Message'
import { LogLevel } from '../LogLevel' import { LogLevel } from '../LogLevel'
import { format } from 'util' import { format } from 'util'
@ -13,8 +13,8 @@ function padleft(str: string, len: number) {
return str return str
} }
export class MessageFormatter implements IFormatter { export class MessageFormatter implements Formatter {
format(message: IMessage) { format(message: Message) {
message.message = format( message.message = format(
'%s %s %s', '%s %s %s',
message.loggerName, message.loggerName,

View File

@ -1,2 +1,2 @@
export * from './IFormatter' export * from './Formatter'
export * from './MessageFormatter' export * from './MessageFormatter'

View File

@ -1,11 +1,11 @@
export * from './ILoggerFactory' export * from './LoggerFactory'
export * from './IMessage' export * from './Message'
export * from './LogLevel' export * from './LogLevel'
export * from './Logger' export * from './Logger'
export * from './LoggerFactory' export * from './LoggerFactory'
import {LoggerFactory} from './LoggerFactory' import {SimpleLoggerFactory} from './SimpleLoggerFactory'
export default LoggerFactory.init() export default SimpleLoggerFactory.init()
import * as transports from './transports' import * as transports from './transports'
export {transports} export {transports}

View File

@ -1,9 +0,0 @@
type ILogFunction = (message: string, ...meta: any[]) => void
export interface ILogger {
error: ILogFunction
warn: ILogFunction
info: ILogFunction
debug: ILogFunction
verbose: ILogFunction
}

View File

@ -1,51 +1,9 @@
import { IFormatter } from '../formatters' type ILogFunction = (message: string, ...meta: unknown[]) => void
import { IMessage } from '../IMessage'
import { LogLevel } from '../LogLevel'
import { ITransport } from '../transports'
import { ILogger } from './ILogger'
interface ILoggerParams { export interface Logger {
name: string error: ILogFunction
readonly formatters: readonly IFormatter[], warn: ILogFunction
readonly transports: readonly ITransport[], info: ILogFunction
} debug: ILogFunction
verbose: ILogFunction
export class Logger implements ILogger {
constructor(protected readonly config: ILoggerParams) {}
protected log(level: LogLevel, message: string, params: any[]) {
const initialMessage: IMessage = {
loggerName: this.config.name,
timestamp: new Date(),
message,
params,
level,
}
const formattedMessage = this.config.formatters.reduce((m, f) => {
return f.format(m)
}, initialMessage)
this.config.transports.forEach(t => {
if (formattedMessage.level <= t.level) {
t.write(formattedMessage)
}
})
}
error(message: string, ...args: any[]) {
this.log(LogLevel.ERROR, message, args)
}
warn(message: string, ...args: any[]) {
this.log(LogLevel.WARN, message, args)
}
info(message: string, ...args: any[]) {
this.log(LogLevel.INFO, message, args)
}
debug(message: string, ...args: any[]) {
this.log(LogLevel.DEBUG, message, args)
}
verbose(message: string, ...args: any[]) {
this.log(LogLevel.VERBOSE, message, args)
}
} }

View File

@ -0,0 +1,50 @@
import { Formatter } from '../formatters'
import { Message } from '../Message'
import { LogLevel } from '../LogLevel'
import { Transport } from '../transports'
import { Logger } from './Logger'
interface LoggerParams {
name: string
readonly formatters: readonly Formatter[]
readonly transports: readonly Transport[]
}
export class SimpleLogger implements Logger {
constructor(protected readonly config: LoggerParams) {}
protected log(level: LogLevel, message: string, params: unknown[]) {
const initialMessage: Message = {
loggerName: this.config.name,
timestamp: new Date(),
message,
params,
level,
}
const formattedMessage = this.config.formatters.reduce((m, f) => {
return f.format(m)
}, initialMessage)
this.config.transports.forEach(t => {
if (formattedMessage.level <= t.level) {
t.write(formattedMessage)
}
})
}
error(message: string, ...args: unknown[]) {
this.log(LogLevel.ERROR, message, args)
}
warn(message: string, ...args: unknown[]) {
this.log(LogLevel.WARN, message, args)
}
info(message: string, ...args: unknown[]) {
this.log(LogLevel.INFO, message, args)
}
debug(message: string, ...args: unknown[]) {
this.log(LogLevel.DEBUG, message, args)
}
verbose(message: string, ...args: unknown[]) {
this.log(LogLevel.VERBOSE, message, args)
}
}

View File

@ -1,2 +1,2 @@
export * from './ILogger'
export * from './Logger' export * from './Logger'
export * from './SimpleLogger'

View File

@ -1,11 +1,11 @@
import { ITransport } from './ITransport' import { Transport } from './Transport'
import { IMessage } from '../IMessage' import { Message } from '../Message'
import { LogLevel } from '../LogLevel' import { LogLevel } from '../LogLevel'
export class ConsoleTransport implements ITransport { export class ConsoleTransport implements Transport {
constructor(readonly level: LogLevel) {} constructor(readonly level: LogLevel) {}
write(entry: IMessage) { write(entry: Message) {
if (entry.level <= this.level) { if (entry.level <= this.level) {
switch (entry.level) { switch (entry.level) {
case LogLevel.ERROR: case LogLevel.ERROR:
@ -24,6 +24,7 @@ export class ConsoleTransport implements ITransport {
case LogLevel.DEBUG: case LogLevel.DEBUG:
// tslint:disable-next-line // tslint:disable-next-line
console.debug(entry.message) console.debug(entry.message)
break
case LogLevel.OFF: case LogLevel.OFF:
// do nothing // do nothing
} }

View File

@ -1,7 +0,0 @@
import { IMessage } from '../IMessage'
import { LogLevel } from '../LogLevel'
export interface ITransport {
readonly level: LogLevel
write(message: IMessage): void
}

View File

@ -0,0 +1,7 @@
import { Message } from '../Message'
import { LogLevel } from '../LogLevel'
export interface Transport {
readonly level: LogLevel
write(message: Message): void
}

View File

@ -1,2 +1,2 @@
export * from './ConsoleTransport' export * from './ConsoleTransport'
export * from './ITransport' export * from './Transport'