Fix linting in packages/logger
This commit is contained in:
parent
003032c3ef
commit
8853c71a0d
@ -1,5 +0,0 @@
|
|||||||
import {ILogger} from './logger/ILogger'
|
|
||||||
|
|
||||||
export interface ILoggerFactory {
|
|
||||||
getLogger(name: string): ILogger
|
|
||||||
}
|
|
||||||
@ -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))
|
||||||
}
|
}
|
||||||
|
|||||||
@ -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
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -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[]
|
||||||
}
|
}
|
||||||
@ -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([])
|
||||||
66
packages/logger/src/SimpleLoggerFactory.ts
Normal file
66
packages/logger/src/SimpleLoggerFactory.ts
Normal 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
|
||||||
|
}
|
||||||
|
}
|
||||||
5
packages/logger/src/formatters/Formatter.ts
Normal file
5
packages/logger/src/formatters/Formatter.ts
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
import { Message } from '../Message'
|
||||||
|
|
||||||
|
export interface Formatter {
|
||||||
|
format(message: Message): Message
|
||||||
|
}
|
||||||
@ -1,5 +0,0 @@
|
|||||||
import { IMessage } from '../IMessage'
|
|
||||||
|
|
||||||
export interface IFormatter {
|
|
||||||
format(message: IMessage): IMessage
|
|
||||||
}
|
|
||||||
@ -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,
|
||||||
|
|||||||
@ -1,2 +1,2 @@
|
|||||||
export * from './IFormatter'
|
export * from './Formatter'
|
||||||
export * from './MessageFormatter'
|
export * from './MessageFormatter'
|
||||||
|
|||||||
@ -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}
|
||||||
|
|||||||
@ -1,9 +0,0 @@
|
|||||||
type ILogFunction = (message: string, ...meta: any[]) => void
|
|
||||||
|
|
||||||
export interface ILogger {
|
|
||||||
error: ILogFunction
|
|
||||||
warn: ILogFunction
|
|
||||||
info: ILogFunction
|
|
||||||
debug: ILogFunction
|
|
||||||
verbose: ILogFunction
|
|
||||||
}
|
|
||||||
@ -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)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
50
packages/logger/src/logger/SimpleLogger.ts
Normal file
50
packages/logger/src/logger/SimpleLogger.ts
Normal 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)
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -1,2 +1,2 @@
|
|||||||
export * from './ILogger'
|
|
||||||
export * from './Logger'
|
export * from './Logger'
|
||||||
|
export * from './SimpleLogger'
|
||||||
|
|||||||
@ -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
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,7 +0,0 @@
|
|||||||
import { IMessage } from '../IMessage'
|
|
||||||
import { LogLevel } from '../LogLevel'
|
|
||||||
|
|
||||||
export interface ITransport {
|
|
||||||
readonly level: LogLevel
|
|
||||||
write(message: IMessage): void
|
|
||||||
}
|
|
||||||
7
packages/logger/src/transports/Transport.ts
Normal file
7
packages/logger/src/transports/Transport.ts
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
import { Message } from '../Message'
|
||||||
|
import { LogLevel } from '../LogLevel'
|
||||||
|
|
||||||
|
export interface Transport {
|
||||||
|
readonly level: LogLevel
|
||||||
|
write(message: Message): void
|
||||||
|
}
|
||||||
@ -1,2 +1,2 @@
|
|||||||
export * from './ConsoleTransport'
|
export * from './ConsoleTransport'
|
||||||
export * from './ITransport'
|
export * from './Transport'
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user