From dfcb71a59b29f1249cd1f8f58476620ef0f276a4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vinicius=20Louren=C3=A7o?= <12551007+H4ad@users.noreply.github.com> Date: Sun, 21 May 2023 19:24:49 -0300 Subject: [PATCH] fix: logging (#652) * fix(logger): fix regression #651 * fix(types): better types for logger --- __tests__/integration.js | 121 +++++++++++++++++++++++++++++++++++++-- src/configure.d.ts | 14 ++--- src/logger.d.ts | 15 +++-- src/logger.js | 93 +++++++++++++++++------------- 4 files changed, 186 insertions(+), 57 deletions(-) diff --git a/__tests__/integration.js b/__tests__/integration.js index ad95bc26..f1c09a99 100644 --- a/__tests__/integration.js +++ b/__tests__/integration.js @@ -522,19 +522,130 @@ describe.each(EACH_MATRIX)('%s:%s: integration tests', (eventSourceName, framewo // expect(customLogger.debug.mock.calls.length).toBe(0) }) + test('custom levels', () => { + const loggerError = serverlessExpressLogger({ level: 'error' }) + + loggerError.error('error') + loggerError.info('nocall') + loggerError.warn('nocall') + loggerError.debug('nocall') + loggerError.verbose('nocall') + expect(global.console.warn).not.toHaveBeenCalled() + expect(global.console.debug).not.toHaveBeenCalled() + expect(global.console.info).not.toHaveBeenCalled() + expect(global.console.error).toHaveBeenLastCalledWith({ + message: 'error' + }) + + const loggerWarn = serverlessExpressLogger({ level: 'warn' }) + + loggerWarn.error('error2') + loggerWarn.warn('warn2') + loggerWarn.info('nocall') + loggerWarn.debug('nocall') + loggerWarn.verbose('nocall') + expect(global.console.debug).not.toHaveBeenCalled() + expect(global.console.info).not.toHaveBeenCalled() + expect(global.console.error).toHaveBeenLastCalledWith({ + message: 'error2' + }) + expect(global.console.warn).toHaveBeenLastCalledWith({ + message: 'warn2' + }) + + const loggerInfo = serverlessExpressLogger({ level: 'info' }) + + loggerInfo.error('error3') + loggerInfo.warn('warn3') + loggerInfo.info('info3') + loggerInfo.debug('nocall') + loggerInfo.verbose('nocall') + expect(global.console.debug).not.toHaveBeenCalled() + expect(global.console.error).toHaveBeenLastCalledWith({ + message: 'error3' + }) + expect(global.console.warn).toHaveBeenLastCalledWith({ + message: 'warn3' + }) + expect(global.console.info).toHaveBeenLastCalledWith({ + message: 'info3' + }) + + const loggerVerbose = serverlessExpressLogger({ level: 'verbose' }) + + loggerVerbose.error('error4') + loggerVerbose.warn('warn4') + loggerVerbose.info('info4') + loggerVerbose.verbose('verbose4') + loggerVerbose.debug('nocall') + expect(global.console.error).toHaveBeenLastCalledWith({ + message: 'error4' + }) + expect(global.console.warn).toHaveBeenLastCalledWith({ + message: 'warn4' + }) + expect(global.console.info).toHaveBeenLastCalledWith({ + message: 'info4' + }) + expect(global.console.debug).toHaveBeenLastCalledWith({ + message: 'verbose4' + }) + + const loggerDebug = serverlessExpressLogger({ level: 'debug' }) + + loggerDebug.error('error5') + loggerDebug.warn('warn5') + loggerDebug.info('info5') + loggerDebug.verbose('verbose5') + loggerDebug.debug('debug5') + expect(global.console.error).toHaveBeenLastCalledWith({ + message: 'error5' + }) + expect(global.console.warn).toHaveBeenLastCalledWith({ + message: 'warn5' + }) + expect(global.console.info).toHaveBeenLastCalledWith({ + message: 'info5' + }) + expect(global.console.debug).toHaveBeenLastCalledWith({ + message: 'debug5' + }) + }) + test('lazy print of logger', async () => { - const logger = serverlessExpressLogger() + const logger = serverlessExpressLogger({ level: 'debug' }) + logger.debug('simple message') logger.debug('debug', () => '=true', ' works') logger.debug(() => 'debug') + logger.debug('array', ['message']) - expect(global.console.debug).not.toHaveBeenNthCalledWith( + expect(global.console.debug).toHaveBeenNthCalledWith( 1, - 'debug=true works' + { + message: 'simple message' + } ) - expect(global.console.debug).not.toHaveBeenNthCalledWith( + expect(global.console.debug).toHaveBeenNthCalledWith( 2, - 'debug' + { + message: 'debug', + 0: '=true', + 1: ' works' + } + ) + expect(global.console.debug).toHaveBeenNthCalledWith( + 3, + { + message: 'debug' + } + ) + expect(global.console.debug).toHaveBeenNthCalledWith( + 4, + { + message: 'array', + 0: ['message'] + } ) }) }) diff --git a/src/configure.d.ts b/src/configure.d.ts index f4c84d93..d270500f 100644 --- a/src/configure.d.ts +++ b/src/configure.d.ts @@ -1,9 +1,9 @@ -import { RequestListener } from "http"; -import { Handler } from "aws-lambda"; -import Logger from "./logger"; -import Framework from "./frameworks"; +import { RequestListener } from 'http'; +import { Handler } from 'aws-lambda'; +import { Logger } from './logger'; +import Framework from './frameworks'; -type EventSources = "AWS_SNS" | "AWS_DYNAMODB" | "AWS_EVENTBRIDGE" | "AWS_SQS" | "AWS_KINESIS_DATA_STREAM"; +type EventSources = 'AWS_SNS' | 'AWS_DYNAMODB' | 'AWS_EVENTBRIDGE' | 'AWS_SQS' | 'AWS_KINESIS_DATA_STREAM'; interface EventSource { getRequest?: any; // TODO: @@ -49,9 +49,7 @@ export interface ConfigureResult { proxy: (proxyParams: ProxyParams) => Promise; } -declare function configure( - configureParams: ConfigureParams -): Handler & ConfigureResult; +declare function configure(configureParams: ConfigureParams): Handler & ConfigureResult; // declare function proxy(proxyParams: ProxyParams): Promise diff --git a/src/logger.d.ts b/src/logger.d.ts index 88b40a7a..3d0f513a 100644 --- a/src/logger.d.ts +++ b/src/logger.d.ts @@ -1,7 +1,12 @@ -interface Logger { - info: (message: string, additional: Object) => void - debug: (message: string, additional: Object) => void - error: (message: string, additional: Object) => void +export interface Logger { + info: (message: string, ...additional: Object[]) => void; + debug: (message: string, ...additional: Object[]) => void; + error: (message: string, ...additional: Object[]) => void; + warn: (message: string, ...additional: Object[]) => void; + verbose: (message: string, ...additional: Object[]) => void; +} +interface Options { + level?: 'error' | 'warn' | 'info' | 'verbose' | 'debug' | string; } -export default Logger \ No newline at end of file +export default function logger(options?: Options): Logger; diff --git a/src/logger.js b/src/logger.js index 10ff4775..671ace42 100644 --- a/src/logger.js +++ b/src/logger.js @@ -1,49 +1,64 @@ -const lazyPrint = (value) => { - if (typeof value === 'function') { return value() } +const lazyPrint = value => { + if (typeof value === 'function') { + return value() + } return value } -function logger ({ - level = 'error' -} = {}) { - return { - error (message, ...additional) { - if (!level.includes('debug', 'verbose', 'info', 'warn', 'error')) return - console.error({ - message: lazyPrint(message), - ...additional.map(lazyPrint) - }) - }, - warn (message, ...additional) { - if (!level.includes('debug', 'verbose', 'info', 'warn')) return - console.warn({ - message: lazyPrint(message), - ...additional.map(lazyPrint) - }) - }, - info (message, additional) { - if (!level.includes('debug', 'verbose', 'info')) return - console.info({ - message: lazyPrint(message), - ...additional.map(lazyPrint) - }) - }, - verbose (message, additional) { - if (!level.includes('debug', 'verbose')) return - console.debug({ - message: lazyPrint(message), - ...additional.map(lazyPrint) - }) - }, - debug (message, additional) { - if (level !== 'debug') return - console.debug({ +const logLevels = { + debug: [ + ['debug', 'debug'], + ['verbose', 'debug'], + ['info', 'info'], + ['error', 'error'], + ['warn', 'warn'] + ], + verbose: [ + ['verbose', 'debug'], + ['info', 'info'], + ['error', 'error'], + ['warn', 'warn'] + ], + info: [ + ['info', 'info'], + ['error', 'error'], + ['warn', 'warn'] + ], + warn: [ + ['warn', 'warn'], + ['error', 'error'] + ], + error: [['error', 'error']], + none: [] +} + +const print = + fn => + (message, ...additional) => + console[fn]({ message: lazyPrint(message), - ...additional.map(lazyPrint) + ...(Array.isArray(additional) ? additional.map(lazyPrint) : []) }) - } + +const NO_OP = () => {} + +function logger ({ level = 'error' } = {}) { + const levels = logLevels[level] + + const logger = { + error: NO_OP, + debug: NO_OP, + info: NO_OP, + verbose: NO_OP, + warn: NO_OP } + + if (!levels) return logger + + for (const [level2, consoleMethod] of levels) logger[level2] = print(consoleMethod) + + return logger } module.exports = logger