From 3ebc2ab34ce8057dbc03a2ebb141d0bc6adf1ea7 Mon Sep 17 00:00:00 2001 From: Cristian Barlutiu Date: Mon, 11 Mar 2024 15:41:50 +0100 Subject: [PATCH 01/17] enabled custom colors per level --- lib/messageFormatFactory.js | 4 ++-- test/index.test.js | 35 +++++++++++++++++++++++++++++++++++ 2 files changed, 37 insertions(+), 2 deletions(-) diff --git a/lib/messageFormatFactory.js b/lib/messageFormatFactory.js index 01af8ef..6de29d0 100644 --- a/lib/messageFormatFactory.js +++ b/lib/messageFormatFactory.js @@ -2,8 +2,8 @@ const formatDate = require('./formatDate') const colorizerFactory = require('pino-pretty').colorizerFactory -const messageFormatFactory = (colorize, levels) => { - const colorizer = colorizerFactory(colorize === true) +const messageFormatFactory = (colorize, levels, customColors) => { + const colorizer = colorizerFactory(colorize === true, customColors) const levelLookUp = { 60: colorizer('fatal').toLowerCase(), diff --git a/test/index.test.js b/test/index.test.js index c8b7396..0b6fba3 100644 --- a/test/index.test.js +++ b/test/index.test.js @@ -113,3 +113,38 @@ logDescriptorColorizedLogPairs.forEach(([logDescriptor, logColorized]) => { }) }) } + +{ + const levels = { + foo: 35, + bar: 45 + } + const messageFormat = messageFormatFactory(true, levels, [[35, "bgCyanBright"], [45, "yellow"]]) + + const logCustomLevelsLogPairs = [ + [ + { time: EPOCH, level: 35, [MESSAGE_KEY]: 'basic foo log' }, + `${TIME} - \u001B[106mfoo\u001B[49m - \u001B[36mbasic foo log\u001B[39m` + ], + [ + { + time: EPOCH, + level: 45, + [MESSAGE_KEY]: 'basic incoming request bar log', + req: { + method: 'GET', + url: '/bar' + } + }, + `${TIME} - \u001B[33mbar\u001B[39m - GET /bar - \u001B[36mbasic incoming request bar log\u001B[39m` + ] + ] + logCustomLevelsLogPairs.forEach(([logDescriptor, expectedLog]) => { + test('format log correctly with custom colors per level', (t) => { + const log = messageFormat(logDescriptor, MESSAGE_KEY) + + t.equal(log, expectedLog) + t.end() + }) + }) +} \ No newline at end of file From 1650893ac3cf38ce4d9e9c69aedbb78976732d34 Mon Sep 17 00:00:00 2001 From: Cristian Barlutiu Date: Mon, 11 Mar 2024 17:20:20 +0100 Subject: [PATCH 02/17] added option to accept colors when setting up the transport --- README.md | 30 ++++++++++++++++++++++++++++++ index.js | 4 ++-- lib/messageFormatFactory.js | 5 ++++- test/index.test.js | 2 +- types/index.d.ts | 7 ++++++- types/index.test-d.ts | 9 +++++---- 6 files changed, 48 insertions(+), 9 deletions(-) diff --git a/README.md b/README.md index e2566f4..8115333 100644 --- a/README.md +++ b/README.md @@ -64,6 +64,36 @@ server.get("/", (request, reply) => { }); ``` +## Custom level colors + +Custom levels colors could be used by passing it into logger opts. They can also overwrite the default level's colors. Check all the supported colors [here](https://github.com/jorgebucaran/colorette?tab=readme-ov-file#supported-colors). + +```js +const server = fastify({ + logger: { + transport: { + target: "@fastify/one-line-logger", + colors: { + 35: "bgYellow", + 45: "magenta", + 60: "bgRedBright" // overwriting the `fatal` log color + } + }, + customLevels: { + foo: 35, + bar: 45, + }, + }, +}); + +server.get("/", (request, reply) => { + request.log.fatal("An error occured"); + request.log.foo("FOO!"); + request.log.bar("BAR!"); + reply.send({ foobar: true }); +}); +``` + ## License diff --git a/index.js b/index.js index ce357e2..f6f3ea1 100644 --- a/index.js +++ b/index.js @@ -4,9 +4,9 @@ const pretty = require('pino-pretty') const messageFormatFactory = require('./lib/messageFormatFactory') const oneLineLogger = (opts = {}) => { - const { colorize, levels, ...rest } = opts + const { colorize, levels, colors, ...rest } = opts - const messageFormat = messageFormatFactory(colorize, levels) + const messageFormat = messageFormatFactory(colorize, levels, colors) return pretty({ messageFormat, diff --git a/lib/messageFormatFactory.js b/lib/messageFormatFactory.js index 6de29d0..6f228f2 100644 --- a/lib/messageFormatFactory.js +++ b/lib/messageFormatFactory.js @@ -2,7 +2,10 @@ const formatDate = require('./formatDate') const colorizerFactory = require('pino-pretty').colorizerFactory -const messageFormatFactory = (colorize, levels, customColors) => { +const messageFormatFactory = (colorize, levels, colors) => { + const customColors = colors != null ? Object.entries(colors).reduce((colors, [level, color]) => { + return [...colors, [level, color]] + }, []) : undefined; const colorizer = colorizerFactory(colorize === true, customColors) const levelLookUp = { diff --git a/test/index.test.js b/test/index.test.js index 0b6fba3..47cdf32 100644 --- a/test/index.test.js +++ b/test/index.test.js @@ -119,7 +119,7 @@ logDescriptorColorizedLogPairs.forEach(([logDescriptor, logColorized]) => { foo: 35, bar: 45 } - const messageFormat = messageFormatFactory(true, levels, [[35, "bgCyanBright"], [45, "yellow"]]) + const messageFormat = messageFormatFactory(true, levels, {35: "bgCyanBright", 45: "yellow"}) const logCustomLevelsLogPairs = [ [ diff --git a/types/index.d.ts b/types/index.d.ts index 5d57050..1db4b64 100644 --- a/types/index.d.ts +++ b/types/index.d.ts @@ -8,12 +8,17 @@ declare namespace oneLineLogger { url: string; } + export interface CustomColor { + [key: number]: string; + } + export type LogDescriptor = Record & { time: number; level: number; + colors?: CustomColor; req?: Request; } - export const messageFormatFactory: (colorize: boolean, levels: Record) => (log: LogDescriptor, messageKey: string) => string + export const messageFormatFactory: (colorize: boolean, levels: Record, colors?: CustomColor) => (log: LogDescriptor, messageKey: string) => string export const oneLineLogger: OneLineLogger export { oneLineLogger as default} diff --git a/types/index.test-d.ts b/types/index.test-d.ts index ec78282..a584afb 100644 --- a/types/index.test-d.ts +++ b/types/index.test-d.ts @@ -1,11 +1,12 @@ +import pretty from 'pino-pretty'; +import { expectType } from "tsd"; import oneLineLogger, { - Request, + CustomColor, LogDescriptor, + Request, messageFormatFactory, oneLineLogger as oneLineLoggerNamed } from ".."; -import { expectType } from "tsd" -import pretty from 'pino-pretty' expectType(({} as Request).method) expectType(({} as Request).url) @@ -14,7 +15,7 @@ expectType(({} as LogDescriptor).level) expectType(({} as LogDescriptor).time) expectType(({} as LogDescriptor).req) -expectType<(colorize: boolean, levels: Record) => (log: LogDescriptor, messageKey: string) => string>(messageFormatFactory) +expectType<(colorize: boolean, levels: Record, colors?: CustomColor) => (log: LogDescriptor, messageKey: string) => string>(messageFormatFactory) expectType(oneLineLoggerNamed) expectType<(opts?: pretty.PrettyOptions) => pretty.PrettyStream>(oneLineLogger) From 081cbaa65bb9513380a31b3ebb0836a09f83b3bf Mon Sep 17 00:00:00 2001 From: Cristian Barlutiu Date: Tue, 12 Mar 2024 08:17:11 +0100 Subject: [PATCH 03/17] fixed linting issues --- lib/messageFormatFactory.js | 8 +++++--- test/index.test.js | 4 ++-- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/lib/messageFormatFactory.js b/lib/messageFormatFactory.js index 6f228f2..b5e31c8 100644 --- a/lib/messageFormatFactory.js +++ b/lib/messageFormatFactory.js @@ -3,9 +3,11 @@ const formatDate = require('./formatDate') const colorizerFactory = require('pino-pretty').colorizerFactory const messageFormatFactory = (colorize, levels, colors) => { - const customColors = colors != null ? Object.entries(colors).reduce((colors, [level, color]) => { - return [...colors, [level, color]] - }, []) : undefined; + const customColors = colors != null + ? Object.entries(colors).reduce((colors, [level, color]) => { + return [...colors, [level, color]] + }, []) + : undefined const colorizer = colorizerFactory(colorize === true, customColors) const levelLookUp = { diff --git a/test/index.test.js b/test/index.test.js index 47cdf32..904fbf2 100644 --- a/test/index.test.js +++ b/test/index.test.js @@ -119,7 +119,7 @@ logDescriptorColorizedLogPairs.forEach(([logDescriptor, logColorized]) => { foo: 35, bar: 45 } - const messageFormat = messageFormatFactory(true, levels, {35: "bgCyanBright", 45: "yellow"}) + const messageFormat = messageFormatFactory(true, levels, { 35: 'bgCyanBright', 45: 'yellow' }) const logCustomLevelsLogPairs = [ [ @@ -147,4 +147,4 @@ logDescriptorColorizedLogPairs.forEach(([logDescriptor, logColorized]) => { t.end() }) }) -} \ No newline at end of file +} From 7586bb1aa899373bbd01f8cb1696763734b92e6b Mon Sep 17 00:00:00 2001 From: Cristian Barlutiu Date: Wed, 22 May 2024 08:57:32 +0200 Subject: [PATCH 04/17] enabled colorization by default --- index.js | 24 +++---- lib/messageFormatFactory.js | 61 ++++++++-------- test/fastify.test.js | 114 +++++++++++++++--------------- test/helpers.js | 69 +++++++++--------- test/index.test.js | 137 ++++++++++++++++++------------------ 5 files changed, 203 insertions(+), 202 deletions(-) diff --git a/index.js b/index.js index f6f3ea1..e3005a0 100644 --- a/index.js +++ b/index.js @@ -1,24 +1,24 @@ -'use strict' +'use strict'; -const pretty = require('pino-pretty') -const messageFormatFactory = require('./lib/messageFormatFactory') +const pretty = require('pino-pretty'); +const messageFormatFactory = require('./lib/messageFormatFactory'); const oneLineLogger = (opts = {}) => { - const { colorize, levels, colors, ...rest } = opts + const { levels, colors, ...rest } = opts; - const messageFormat = messageFormatFactory(colorize, levels, colors) + const messageFormat = messageFormatFactory(levels, colors); return pretty({ messageFormat, ignore: 'pid,hostname,time,level', hideObject: true, colorize: false, - ...rest - }) -} + ...rest, + }); +}; -module.exports = oneLineLogger -module.exports.default = oneLineLogger -module.exports.oneLineLogger = oneLineLogger +module.exports = oneLineLogger; +module.exports.default = oneLineLogger; +module.exports.oneLineLogger = oneLineLogger; -module.exports.messageFormatFactory = messageFormatFactory +module.exports.messageFormatFactory = messageFormatFactory; diff --git a/lib/messageFormatFactory.js b/lib/messageFormatFactory.js index b5e31c8..25cb713 100644 --- a/lib/messageFormatFactory.js +++ b/lib/messageFormatFactory.js @@ -1,14 +1,15 @@ -'use strict' -const formatDate = require('./formatDate') -const colorizerFactory = require('pino-pretty').colorizerFactory - -const messageFormatFactory = (colorize, levels, colors) => { - const customColors = colors != null - ? Object.entries(colors).reduce((colors, [level, color]) => { - return [...colors, [level, color]] - }, []) - : undefined - const colorizer = colorizerFactory(colorize === true, customColors) +'use strict'; +const formatDate = require('./formatDate'); +const colorizerFactory = require('pino-pretty').colorizerFactory; + +const messageFormatFactory = (levels, colors) => { + const customColors = + colors != null + ? Object.entries(colors).reduce((colors, [level, color]) => { + return [...colors, [level, color]]; + }, []) + : undefined; + const colorizer = colorizerFactory(true, customColors); const levelLookUp = { 60: colorizer('fatal').toLowerCase(), @@ -16,30 +17,34 @@ const messageFormatFactory = (colorize, levels, colors) => { 40: colorizer('warn').toLowerCase(), 30: colorizer('info').toLowerCase(), 20: colorizer('debug').toLowerCase(), - 10: colorizer('trace').toLowerCase() - } + 10: colorizer('trace').toLowerCase(), + }; - const shouldAddCustomLevels = !!levels + const shouldAddCustomLevels = !!levels; if (shouldAddCustomLevels) { Object.entries(levels).forEach(([name, level]) => { - const customLevels = { [level]: name } - const customLevelNames = { [name]: level } - levelLookUp[level] = colorizer(name, { customLevelNames, customLevels }).toLowerCase() - }) + const customLevels = { [level]: name }; + const customLevelNames = { [name]: level }; + levelLookUp[level] = colorizer(name, { + customLevelNames, + customLevels, + }).toLowerCase(); + }); } - - const colorizeMessage = colorizer.message + const colorizeMessage = colorizer.message; const messageFormat = (log, messageKey) => { - const time = formatDate(log.time) - const level = levelLookUp[log.level] + const time = formatDate(log.time); + const level = levelLookUp[log.level]; return log.req - ? `${time} - ${level} - ${log.req.method} ${log.req.url} - ${colorizeMessage(log[messageKey])}` - : `${time} - ${level} - ${colorizeMessage(log[messageKey])}` - } + ? `${time} - ${level} - ${log.req.method} ${ + log.req.url + } - ${colorizeMessage(log[messageKey])}` + : `${time} - ${level} - ${colorizeMessage(log[messageKey])}`; + }; - return messageFormat -} + return messageFormat; +}; -module.exports = messageFormatFactory +module.exports = messageFormatFactory; diff --git a/test/fastify.test.js b/test/fastify.test.js index ab088c1..83b4f7e 100644 --- a/test/fastify.test.js +++ b/test/fastify.test.js @@ -1,92 +1,90 @@ -'use strict' +'use strict'; -const { serverFactory, TIME, unmockTime, mockTime } = require('./helpers') -const tap = require('tap') +const { serverFactory, TIME, unmockTime, mockTime } = require('./helpers'); +const tap = require('tap'); -const { test } = tap +const { test } = tap; -const messages = [] -let server = serverFactory(messages, { colorize: false }) +const messages = []; +let server = serverFactory(messages, { colorize: false }); tap.before(() => { - mockTime() -}) + mockTime(); +}); tap.teardown(() => { - unmockTime() -}) + unmockTime(); +}); tap.beforeEach(() => { // empty messages array - messages.splice(0, messages.length) + messages.splice(0, messages.length); - server = serverFactory(messages) -}) + server = serverFactory(messages); +}); test('should log server started messages', async (t) => { - await server.listen({ port: 63995 }) + await server.listen({ port: 63995 }); const messagesExpected = [ - `${TIME} - info - Server listening at http://127.0.0.1:63995\n`, - `${TIME} - info - Server listening at http://[::1]:63995\n` - ] + `${TIME} - \x1B[32minfo\x1B[39m - \x1B[36mServer listening at http://127.0.0.1:63995\x1B[39m\n`, + `${TIME} - \x1B[32minfo\x1B[39m - \x1B[36mServer listening at http://[::1]:63995\x1B[39m\n`, + ]; // sort because the order of the messages is not guaranteed - t.same(messages.sort(), messagesExpected.sort()) - await server.close() - t.end() -}) + t.same(messages.sort(), messagesExpected.sort()); + await server.close(); + t.end(); +}); -const methods = ['GET', 'POST', 'PUT', 'DELETE', 'PATCH', 'OPTIONS', 'HEAD'] +const methods = ['GET', 'POST', 'PUT', 'DELETE', 'PATCH', 'OPTIONS', 'HEAD']; methods.forEach((method) => { test('should log request and response messages for %p', async (t) => { - const serverMethod = method === 'HEAD' ? 'GET' : method + const serverMethod = method === 'HEAD' ? 'GET' : method; server[serverMethod.toLowerCase()]('/path', (_, req) => { - req.send() - }) + req.send(); + }); await server.inject({ method, - url: '/path' - }) + url: '/path', + }); const messagesExpected = [ - `${TIME} - info - ${method} /path - incoming request\n`, - `${TIME} - info - request completed\n` - ] - - t.same(messages, messagesExpected) - t.end() - }) -}) + `${TIME} - \x1B[32minfo\x1B[39m - ${method} /path - \x1B[36mincoming request\x1B[39m\n`, + `${TIME} - \x1B[32minfo\x1B[39m - \x1B[36mrequest completed\x1B[39m\n`, + ]; + t.same(messages, messagesExpected); + t.end(); + }); +}); test('should handle user defined log', async (t) => { - server = serverFactory(messages, { minimumLevel: 'trace' }) + server = serverFactory(messages, { minimumLevel: 'trace' }); server.get('/a-path-with-user-defined-log', (res, req) => { - res.log.fatal('a user defined fatal log') - res.log.error('a user defined error log') - res.log.warn('a user defined warn log') - res.log.info('a user defined info log') - res.log.debug('a user defined debug log') - res.log.trace('a user defined trace log') + res.log.fatal('a user defined fatal log'); + res.log.error('a user defined error log'); + res.log.warn('a user defined warn log'); + res.log.info('a user defined info log'); + res.log.debug('a user defined debug log'); + res.log.trace('a user defined trace log'); - req.send() - }) + req.send(); + }); - await server.inject('/a-path-with-user-defined-log') + await server.inject('/a-path-with-user-defined-log'); const messagesExpected = [ - `${TIME} - info - GET /a-path-with-user-defined-log - incoming request\n`, - `${TIME} - fatal - a user defined fatal log\n`, - `${TIME} - error - a user defined error log\n`, - `${TIME} - warn - a user defined warn log\n`, - `${TIME} - info - a user defined info log\n`, - `${TIME} - debug - a user defined debug log\n`, - `${TIME} - trace - a user defined trace log\n`, - `${TIME} - info - request completed\n` - ] - - t.same(messages, messagesExpected) - t.end() -}) + `${TIME} - \x1B[32minfo\x1B[39m - GET /a-path-with-user-defined-log - \x1B[36mincoming request\x1B[39m\n`, + `${TIME} - \x1B[41mfatal\x1B[49m - \x1B[36ma user defined fatal log\x1B[39m\n`, + `${TIME} - \x1B[31merror\x1B[39m - \x1B[36ma user defined error log\x1B[39m\n`, + `${TIME} - \x1B[33mwarn\x1B[39m - \x1B[36ma user defined warn log\x1B[39m\n`, + `${TIME} - \x1B[32minfo\x1B[39m - \x1B[36ma user defined info log\x1B[39m\n`, + `${TIME} - \x1B[34mdebug\x1B[39m - \x1B[36ma user defined debug log\x1B[39m\n`, + `${TIME} - \x1B[90mtrace\x1B[39m - \x1B[36ma user defined trace log\x1B[39m\n`, + `${TIME} - \x1B[32minfo\x1B[39m - \x1B[36mrequest completed\x1B[39m\n`, + ]; + t.same(messages, messagesExpected); + t.end(); +}); diff --git a/test/helpers.js b/test/helpers.js index d5eea6a..9c773b0 100644 --- a/test/helpers.js +++ b/test/helpers.js @@ -1,66 +1,65 @@ -'use strict' +'use strict'; -const { Writable } = require('readable-stream') -const fastify = require('fastify') -const pino = require('pino') -const target = require('..') +const { Writable } = require('readable-stream'); +const fastify = require('fastify'); +const pino = require('pino'); +const target = require('..'); -const HOUR = 20 -const TIME = `2017-02-14 ${HOUR}:51:48.000+0800` -const EPOCH = 1487076708000 -const TIMEZONE_OFFSET = -8 * 60 -const MESSAGE_KEY = 'message' +const HOUR = 20; +const TIME = `2017-02-14 ${HOUR}:51:48.000+0800`; +const EPOCH = 1487076708000; +const TIMEZONE_OFFSET = -8 * 60; +const MESSAGE_KEY = 'message'; const pinoFactory = (opts) => { - const level = opts.minimumLevel || 'info' + const level = opts.minimumLevel || 'info'; return pino( { level }, target({ - colorize: false, - ...opts + ...opts, }) - ) -} + ); +}; const serverFactory = (messages, opts, fastifyOpts) => { const destination = new Writable({ - write (chunk, _enc, cb) { - messages.push(chunk.toString()) + write(chunk, _enc, cb) { + messages.push(chunk.toString()); - process.nextTick(cb) - } - }) + process.nextTick(cb); + }, + }); - const pinoLogger = pinoFactory({ destination, ...opts }) + const pinoLogger = pinoFactory({ destination, ...opts }); return fastify({ logger: pinoLogger, - ...fastifyOpts - }) -} + ...fastifyOpts, + }); +}; -const dateOriginalNow = Date.now -const dateGetTimezoneOffset = Date.prototype.getTimezoneOffset -const dateOriginalGetHours = Date.prototype.getHours +const dateOriginalNow = Date.now; +const dateGetTimezoneOffset = Date.prototype.getTimezoneOffset; +const dateOriginalGetHours = Date.prototype.getHours; const mockTime = () => { - Date.now = () => EPOCH + Date.now = () => EPOCH; // eslint-disable-next-line Date.prototype.getTimezoneOffset = () => TIMEZONE_OFFSET; // eslint-disable-next-line Date.prototype.getHours = () => HOUR; -} +}; const unmockTime = () => { - Date.now = dateOriginalNow + Date.now = dateOriginalNow; // eslint-disable-next-line - Date.prototype.getTimezoneOffset = dateGetTimezoneOffset + Date.prototype.getTimezoneOffset = dateGetTimezoneOffset; // eslint-disable-next-line - Date.prototype.getHours = dateOriginalGetHours -} + Date.prototype.getHours = dateOriginalGetHours; +}; module.exports = { TIME, @@ -70,5 +69,5 @@ module.exports = { pinoFactory, serverFactory, mockTime, - unmockTime -} + unmockTime, +}; diff --git a/test/index.test.js b/test/index.test.js index 904fbf2..1496449 100644 --- a/test/index.test.js +++ b/test/index.test.js @@ -1,34 +1,33 @@ -'use strict' +'use strict'; -const { EPOCH, TIME, MESSAGE_KEY, mockTime, unmockTime } = require('./helpers') -const target = require('..') -const tap = require('tap') +const { EPOCH, TIME, MESSAGE_KEY, mockTime, unmockTime } = require('./helpers'); +const target = require('..'); +const tap = require('tap'); -const { messageFormatFactory } = target +const { messageFormatFactory } = target; -const { test } = tap +const { test } = tap; -const messageFormat = messageFormatFactory(false) -const messageFormatColorized = messageFormatFactory(true) +const messageFormat = messageFormatFactory(); tap.before(() => { - mockTime() -}) + mockTime(); +}); tap.teardown(() => { - unmockTime() -}) + unmockTime(); +}); test('able to instantiate target without arguments', (t) => { - target() - t.pass() - t.end() -}) + target(); + t.pass(); + t.end(); +}); const logDescriptorLogPairs = [ [ { time: EPOCH, level: 10, [MESSAGE_KEY]: 'basic log' }, - `${TIME} - trace - basic log` + `${TIME} - \x1B[90mtrace\x1B[39m - \x1B[36mbasic log\x1B[39m`, ], [ { @@ -37,25 +36,24 @@ const logDescriptorLogPairs = [ [MESSAGE_KEY]: 'basic incoming request log', req: { method: 'GET', - url: '/path' - } + url: '/path', + }, }, - `${TIME} - info - GET /path - basic incoming request log` - ] -] + `${TIME} - \x1B[32minfo\x1B[39m - GET /path - \x1B[36mbasic incoming request log\x1B[39m`, + ], +]; logDescriptorLogPairs.forEach(([logDescriptor, expectedLog]) => { test('format log correctly with different logDescriptor', (t) => { - const log = messageFormat(logDescriptor, MESSAGE_KEY) - - t.equal(log, expectedLog) - t.end() - }) -}) + const log = messageFormat(logDescriptor, MESSAGE_KEY); + t.equal(log, expectedLog); + t.end(); + }); +}); const logDescriptorColorizedLogPairs = [ [ { time: EPOCH, level: 10, [MESSAGE_KEY]: 'basic log' }, - `${TIME} - \u001B[90mtrace\u001B[39m - \u001B[36mbasic log\u001B[39m` + `${TIME} - \u001B[90mtrace\u001B[39m - \u001B[36mbasic log\u001B[39m`, ], [ { @@ -64,32 +62,32 @@ const logDescriptorColorizedLogPairs = [ [MESSAGE_KEY]: 'basic incoming request log', req: { method: 'GET', - url: '/path' - } + url: '/path', + }, }, - `${TIME} - \u001B[32minfo\u001B[39m - GET /path - \u001B[36mbasic incoming request log\u001B[39m` - ] -] + `${TIME} - \u001B[32minfo\u001B[39m - GET /path - \u001B[36mbasic incoming request log\u001B[39m`, + ], +]; logDescriptorColorizedLogPairs.forEach(([logDescriptor, logColorized]) => { test('colorize log correctly with different logDescriptor', (t) => { - const log = messageFormatColorized(logDescriptor, MESSAGE_KEY) + const log = messageFormat(logDescriptor, MESSAGE_KEY); - t.equal(log, logColorized) - t.end() - }) -}) + t.equal(log, logColorized); + t.end(); + }); +}); { const levels = { foo: 35, - bar: 45 - } - const messageFormat = messageFormatFactory(false, levels) + bar: 45, + }; + const messageFormat = messageFormatFactory(levels); const logCustomLevelsLogPairs = [ [ { time: EPOCH, level: 35, [MESSAGE_KEY]: 'basic foo log' }, - `${TIME} - foo - basic foo log` + `${TIME} - \u001b[37mfoo\u001b[39m - \u001B[36mbasic foo log\u001B[39m`, ], [ { @@ -98,33 +96,35 @@ logDescriptorColorizedLogPairs.forEach(([logDescriptor, logColorized]) => { [MESSAGE_KEY]: 'basic incoming request bar log', req: { method: 'GET', - url: '/bar' - } + url: '/bar', + }, }, - `${TIME} - bar - GET /bar - basic incoming request bar log` - ] - ] + `${TIME} - \u001b[37mbar\u001b[39m - GET /bar - \u001B[36mbasic incoming request bar log\u001B[39m`, + ], + ]; logCustomLevelsLogPairs.forEach(([logDescriptor, expectedLog]) => { test('format log correctly with custom levels', (t) => { - const log = messageFormat(logDescriptor, MESSAGE_KEY) - - t.equal(log, expectedLog) - t.end() - }) - }) + const log = messageFormat(logDescriptor, MESSAGE_KEY); + t.equal(log, expectedLog); + t.end(); + }); + }); } { const levels = { foo: 35, - bar: 45 - } - const messageFormat = messageFormatFactory(true, levels, { 35: 'bgCyanBright', 45: 'yellow' }) + bar: 45, + }; + const messageFormat = messageFormatFactory(levels, { + 35: 'bgCyanBright', + 45: 'yellow', + }); const logCustomLevelsLogPairs = [ [ { time: EPOCH, level: 35, [MESSAGE_KEY]: 'basic foo log' }, - `${TIME} - \u001B[106mfoo\u001B[49m - \u001B[36mbasic foo log\u001B[39m` + `${TIME} - \u001B[106mfoo\u001B[49m - \u001B[36mbasic foo log\u001B[39m`, ], [ { @@ -133,18 +133,17 @@ logDescriptorColorizedLogPairs.forEach(([logDescriptor, logColorized]) => { [MESSAGE_KEY]: 'basic incoming request bar log', req: { method: 'GET', - url: '/bar' - } + url: '/bar', + }, }, - `${TIME} - \u001B[33mbar\u001B[39m - GET /bar - \u001B[36mbasic incoming request bar log\u001B[39m` - ] - ] + `${TIME} - \u001B[33mbar\u001B[39m - GET /bar - \u001B[36mbasic incoming request bar log\u001B[39m`, + ], + ]; logCustomLevelsLogPairs.forEach(([logDescriptor, expectedLog]) => { test('format log correctly with custom colors per level', (t) => { - const log = messageFormat(logDescriptor, MESSAGE_KEY) - - t.equal(log, expectedLog) - t.end() - }) - }) + const log = messageFormat(logDescriptor, MESSAGE_KEY); + t.equal(log, expectedLog); + t.end(); + }); + }); } From 6c55ee593165473a60c3c1ab911ed43f8d70988e Mon Sep 17 00:00:00 2001 From: Cristian Barlutiu Date: Wed, 22 May 2024 08:59:03 +0200 Subject: [PATCH 05/17] fixed linting --- index.js | 24 +++---- lib/messageFormatFactory.js | 46 ++++++------- test/fastify.test.js | 94 ++++++++++++------------- test/helpers.js | 64 ++++++++--------- test/index.test.js | 132 ++++++++++++++++++------------------ 5 files changed, 180 insertions(+), 180 deletions(-) diff --git a/index.js b/index.js index e3005a0..b934e5e 100644 --- a/index.js +++ b/index.js @@ -1,24 +1,24 @@ -'use strict'; +'use strict' -const pretty = require('pino-pretty'); -const messageFormatFactory = require('./lib/messageFormatFactory'); +const pretty = require('pino-pretty') +const messageFormatFactory = require('./lib/messageFormatFactory') const oneLineLogger = (opts = {}) => { - const { levels, colors, ...rest } = opts; + const { levels, colors, ...rest } = opts - const messageFormat = messageFormatFactory(levels, colors); + const messageFormat = messageFormatFactory(levels, colors) return pretty({ messageFormat, ignore: 'pid,hostname,time,level', hideObject: true, colorize: false, - ...rest, - }); -}; + ...rest + }) +} -module.exports = oneLineLogger; -module.exports.default = oneLineLogger; -module.exports.oneLineLogger = oneLineLogger; +module.exports = oneLineLogger +module.exports.default = oneLineLogger +module.exports.oneLineLogger = oneLineLogger -module.exports.messageFormatFactory = messageFormatFactory; +module.exports.messageFormatFactory = messageFormatFactory diff --git a/lib/messageFormatFactory.js b/lib/messageFormatFactory.js index 25cb713..508cec6 100644 --- a/lib/messageFormatFactory.js +++ b/lib/messageFormatFactory.js @@ -1,15 +1,15 @@ -'use strict'; -const formatDate = require('./formatDate'); -const colorizerFactory = require('pino-pretty').colorizerFactory; +'use strict' +const formatDate = require('./formatDate') +const colorizerFactory = require('pino-pretty').colorizerFactory const messageFormatFactory = (levels, colors) => { const customColors = colors != null ? Object.entries(colors).reduce((colors, [level, color]) => { - return [...colors, [level, color]]; - }, []) - : undefined; - const colorizer = colorizerFactory(true, customColors); + return [...colors, [level, color]] + }, []) + : undefined + const colorizer = colorizerFactory(true, customColors) const levelLookUp = { 60: colorizer('fatal').toLowerCase(), @@ -17,34 +17,34 @@ const messageFormatFactory = (levels, colors) => { 40: colorizer('warn').toLowerCase(), 30: colorizer('info').toLowerCase(), 20: colorizer('debug').toLowerCase(), - 10: colorizer('trace').toLowerCase(), - }; + 10: colorizer('trace').toLowerCase() + } - const shouldAddCustomLevels = !!levels; + const shouldAddCustomLevels = !!levels if (shouldAddCustomLevels) { Object.entries(levels).forEach(([name, level]) => { - const customLevels = { [level]: name }; - const customLevelNames = { [name]: level }; + const customLevels = { [level]: name } + const customLevelNames = { [name]: level } levelLookUp[level] = colorizer(name, { customLevelNames, - customLevels, - }).toLowerCase(); - }); + customLevels + }).toLowerCase() + }) } - const colorizeMessage = colorizer.message; + const colorizeMessage = colorizer.message const messageFormat = (log, messageKey) => { - const time = formatDate(log.time); - const level = levelLookUp[log.level]; + const time = formatDate(log.time) + const level = levelLookUp[log.level] return log.req ? `${time} - ${level} - ${log.req.method} ${ log.req.url } - ${colorizeMessage(log[messageKey])}` - : `${time} - ${level} - ${colorizeMessage(log[messageKey])}`; - }; + : `${time} - ${level} - ${colorizeMessage(log[messageKey])}` + } - return messageFormat; -}; + return messageFormat +} -module.exports = messageFormatFactory; +module.exports = messageFormatFactory diff --git a/test/fastify.test.js b/test/fastify.test.js index 83b4f7e..c95a8a7 100644 --- a/test/fastify.test.js +++ b/test/fastify.test.js @@ -1,79 +1,79 @@ -'use strict'; +'use strict' -const { serverFactory, TIME, unmockTime, mockTime } = require('./helpers'); -const tap = require('tap'); +const { serverFactory, TIME, unmockTime, mockTime } = require('./helpers') +const tap = require('tap') -const { test } = tap; +const { test } = tap -const messages = []; -let server = serverFactory(messages, { colorize: false }); +const messages = [] +let server = serverFactory(messages, { colorize: false }) tap.before(() => { - mockTime(); -}); + mockTime() +}) tap.teardown(() => { - unmockTime(); -}); + unmockTime() +}) tap.beforeEach(() => { // empty messages array - messages.splice(0, messages.length); + messages.splice(0, messages.length) - server = serverFactory(messages); -}); + server = serverFactory(messages) +}) test('should log server started messages', async (t) => { - await server.listen({ port: 63995 }); + await server.listen({ port: 63995 }) const messagesExpected = [ `${TIME} - \x1B[32minfo\x1B[39m - \x1B[36mServer listening at http://127.0.0.1:63995\x1B[39m\n`, - `${TIME} - \x1B[32minfo\x1B[39m - \x1B[36mServer listening at http://[::1]:63995\x1B[39m\n`, - ]; + `${TIME} - \x1B[32minfo\x1B[39m - \x1B[36mServer listening at http://[::1]:63995\x1B[39m\n` + ] // sort because the order of the messages is not guaranteed - t.same(messages.sort(), messagesExpected.sort()); - await server.close(); - t.end(); -}); + t.same(messages.sort(), messagesExpected.sort()) + await server.close() + t.end() +}) -const methods = ['GET', 'POST', 'PUT', 'DELETE', 'PATCH', 'OPTIONS', 'HEAD']; +const methods = ['GET', 'POST', 'PUT', 'DELETE', 'PATCH', 'OPTIONS', 'HEAD'] methods.forEach((method) => { test('should log request and response messages for %p', async (t) => { - const serverMethod = method === 'HEAD' ? 'GET' : method; + const serverMethod = method === 'HEAD' ? 'GET' : method server[serverMethod.toLowerCase()]('/path', (_, req) => { - req.send(); - }); + req.send() + }) await server.inject({ method, - url: '/path', - }); + url: '/path' + }) const messagesExpected = [ `${TIME} - \x1B[32minfo\x1B[39m - ${method} /path - \x1B[36mincoming request\x1B[39m\n`, - `${TIME} - \x1B[32minfo\x1B[39m - \x1B[36mrequest completed\x1B[39m\n`, - ]; - t.same(messages, messagesExpected); - t.end(); - }); -}); + `${TIME} - \x1B[32minfo\x1B[39m - \x1B[36mrequest completed\x1B[39m\n` + ] + t.same(messages, messagesExpected) + t.end() + }) +}) test('should handle user defined log', async (t) => { - server = serverFactory(messages, { minimumLevel: 'trace' }); + server = serverFactory(messages, { minimumLevel: 'trace' }) server.get('/a-path-with-user-defined-log', (res, req) => { - res.log.fatal('a user defined fatal log'); - res.log.error('a user defined error log'); - res.log.warn('a user defined warn log'); - res.log.info('a user defined info log'); - res.log.debug('a user defined debug log'); - res.log.trace('a user defined trace log'); + res.log.fatal('a user defined fatal log') + res.log.error('a user defined error log') + res.log.warn('a user defined warn log') + res.log.info('a user defined info log') + res.log.debug('a user defined debug log') + res.log.trace('a user defined trace log') - req.send(); - }); + req.send() + }) - await server.inject('/a-path-with-user-defined-log'); + await server.inject('/a-path-with-user-defined-log') const messagesExpected = [ `${TIME} - \x1B[32minfo\x1B[39m - GET /a-path-with-user-defined-log - \x1B[36mincoming request\x1B[39m\n`, @@ -83,8 +83,8 @@ test('should handle user defined log', async (t) => { `${TIME} - \x1B[32minfo\x1B[39m - \x1B[36ma user defined info log\x1B[39m\n`, `${TIME} - \x1B[34mdebug\x1B[39m - \x1B[36ma user defined debug log\x1B[39m\n`, `${TIME} - \x1B[90mtrace\x1B[39m - \x1B[36ma user defined trace log\x1B[39m\n`, - `${TIME} - \x1B[32minfo\x1B[39m - \x1B[36mrequest completed\x1B[39m\n`, - ]; - t.same(messages, messagesExpected); - t.end(); -}); + `${TIME} - \x1B[32minfo\x1B[39m - \x1B[36mrequest completed\x1B[39m\n` + ] + t.same(messages, messagesExpected) + t.end() +}) diff --git a/test/helpers.js b/test/helpers.js index 9c773b0..8363c50 100644 --- a/test/helpers.js +++ b/test/helpers.js @@ -1,65 +1,65 @@ -'use strict'; +'use strict' -const { Writable } = require('readable-stream'); -const fastify = require('fastify'); -const pino = require('pino'); -const target = require('..'); +const { Writable } = require('readable-stream') +const fastify = require('fastify') +const pino = require('pino') +const target = require('..') -const HOUR = 20; -const TIME = `2017-02-14 ${HOUR}:51:48.000+0800`; -const EPOCH = 1487076708000; -const TIMEZONE_OFFSET = -8 * 60; -const MESSAGE_KEY = 'message'; +const HOUR = 20 +const TIME = `2017-02-14 ${HOUR}:51:48.000+0800` +const EPOCH = 1487076708000 +const TIMEZONE_OFFSET = -8 * 60 +const MESSAGE_KEY = 'message' const pinoFactory = (opts) => { - const level = opts.minimumLevel || 'info'; + const level = opts.minimumLevel || 'info' return pino( { level }, target({ - ...opts, + ...opts }) - ); -}; + ) +} const serverFactory = (messages, opts, fastifyOpts) => { const destination = new Writable({ - write(chunk, _enc, cb) { - messages.push(chunk.toString()); + write (chunk, _enc, cb) { + messages.push(chunk.toString()) - process.nextTick(cb); - }, - }); + process.nextTick(cb) + } + }) - const pinoLogger = pinoFactory({ destination, ...opts }); + const pinoLogger = pinoFactory({ destination, ...opts }) return fastify({ logger: pinoLogger, - ...fastifyOpts, - }); -}; + ...fastifyOpts + }) +} -const dateOriginalNow = Date.now; -const dateGetTimezoneOffset = Date.prototype.getTimezoneOffset; -const dateOriginalGetHours = Date.prototype.getHours; +const dateOriginalNow = Date.now +const dateGetTimezoneOffset = Date.prototype.getTimezoneOffset +const dateOriginalGetHours = Date.prototype.getHours const mockTime = () => { - Date.now = () => EPOCH; + Date.now = () => EPOCH // eslint-disable-next-line Date.prototype.getTimezoneOffset = () => TIMEZONE_OFFSET; // eslint-disable-next-line Date.prototype.getHours = () => HOUR; -}; +} const unmockTime = () => { - Date.now = dateOriginalNow; + Date.now = dateOriginalNow // eslint-disable-next-line Date.prototype.getTimezoneOffset = dateGetTimezoneOffset; // eslint-disable-next-line Date.prototype.getHours = dateOriginalGetHours; -}; +} module.exports = { TIME, @@ -69,5 +69,5 @@ module.exports = { pinoFactory, serverFactory, mockTime, - unmockTime, -}; + unmockTime +} diff --git a/test/index.test.js b/test/index.test.js index 1496449..33c8dbc 100644 --- a/test/index.test.js +++ b/test/index.test.js @@ -1,33 +1,33 @@ -'use strict'; +'use strict' -const { EPOCH, TIME, MESSAGE_KEY, mockTime, unmockTime } = require('./helpers'); -const target = require('..'); -const tap = require('tap'); +const { EPOCH, TIME, MESSAGE_KEY, mockTime, unmockTime } = require('./helpers') +const target = require('..') +const tap = require('tap') -const { messageFormatFactory } = target; +const { messageFormatFactory } = target -const { test } = tap; +const { test } = tap -const messageFormat = messageFormatFactory(); +const messageFormat = messageFormatFactory() tap.before(() => { - mockTime(); -}); + mockTime() +}) tap.teardown(() => { - unmockTime(); -}); + unmockTime() +}) test('able to instantiate target without arguments', (t) => { - target(); - t.pass(); - t.end(); -}); + target() + t.pass() + t.end() +}) const logDescriptorLogPairs = [ [ { time: EPOCH, level: 10, [MESSAGE_KEY]: 'basic log' }, - `${TIME} - \x1B[90mtrace\x1B[39m - \x1B[36mbasic log\x1B[39m`, + `${TIME} - \x1B[90mtrace\x1B[39m - \x1B[36mbasic log\x1B[39m` ], [ { @@ -36,24 +36,24 @@ const logDescriptorLogPairs = [ [MESSAGE_KEY]: 'basic incoming request log', req: { method: 'GET', - url: '/path', - }, + url: '/path' + } }, - `${TIME} - \x1B[32minfo\x1B[39m - GET /path - \x1B[36mbasic incoming request log\x1B[39m`, - ], -]; + `${TIME} - \x1B[32minfo\x1B[39m - GET /path - \x1B[36mbasic incoming request log\x1B[39m` + ] +] logDescriptorLogPairs.forEach(([logDescriptor, expectedLog]) => { test('format log correctly with different logDescriptor', (t) => { - const log = messageFormat(logDescriptor, MESSAGE_KEY); - t.equal(log, expectedLog); - t.end(); - }); -}); + const log = messageFormat(logDescriptor, MESSAGE_KEY) + t.equal(log, expectedLog) + t.end() + }) +}) const logDescriptorColorizedLogPairs = [ [ { time: EPOCH, level: 10, [MESSAGE_KEY]: 'basic log' }, - `${TIME} - \u001B[90mtrace\u001B[39m - \u001B[36mbasic log\u001B[39m`, + `${TIME} - \u001B[90mtrace\u001B[39m - \u001B[36mbasic log\u001B[39m` ], [ { @@ -62,32 +62,32 @@ const logDescriptorColorizedLogPairs = [ [MESSAGE_KEY]: 'basic incoming request log', req: { method: 'GET', - url: '/path', - }, + url: '/path' + } }, - `${TIME} - \u001B[32minfo\u001B[39m - GET /path - \u001B[36mbasic incoming request log\u001B[39m`, - ], -]; + `${TIME} - \u001B[32minfo\u001B[39m - GET /path - \u001B[36mbasic incoming request log\u001B[39m` + ] +] logDescriptorColorizedLogPairs.forEach(([logDescriptor, logColorized]) => { test('colorize log correctly with different logDescriptor', (t) => { - const log = messageFormat(logDescriptor, MESSAGE_KEY); + const log = messageFormat(logDescriptor, MESSAGE_KEY) - t.equal(log, logColorized); - t.end(); - }); -}); + t.equal(log, logColorized) + t.end() + }) +}) { const levels = { foo: 35, - bar: 45, - }; - const messageFormat = messageFormatFactory(levels); + bar: 45 + } + const messageFormat = messageFormatFactory(levels) const logCustomLevelsLogPairs = [ [ { time: EPOCH, level: 35, [MESSAGE_KEY]: 'basic foo log' }, - `${TIME} - \u001b[37mfoo\u001b[39m - \u001B[36mbasic foo log\u001B[39m`, + `${TIME} - \u001b[37mfoo\u001b[39m - \u001B[36mbasic foo log\u001B[39m` ], [ { @@ -96,35 +96,35 @@ logDescriptorColorizedLogPairs.forEach(([logDescriptor, logColorized]) => { [MESSAGE_KEY]: 'basic incoming request bar log', req: { method: 'GET', - url: '/bar', - }, + url: '/bar' + } }, - `${TIME} - \u001b[37mbar\u001b[39m - GET /bar - \u001B[36mbasic incoming request bar log\u001B[39m`, - ], - ]; + `${TIME} - \u001b[37mbar\u001b[39m - GET /bar - \u001B[36mbasic incoming request bar log\u001B[39m` + ] + ] logCustomLevelsLogPairs.forEach(([logDescriptor, expectedLog]) => { test('format log correctly with custom levels', (t) => { - const log = messageFormat(logDescriptor, MESSAGE_KEY); - t.equal(log, expectedLog); - t.end(); - }); - }); + const log = messageFormat(logDescriptor, MESSAGE_KEY) + t.equal(log, expectedLog) + t.end() + }) + }) } { const levels = { foo: 35, - bar: 45, - }; + bar: 45 + } const messageFormat = messageFormatFactory(levels, { 35: 'bgCyanBright', - 45: 'yellow', - }); + 45: 'yellow' + }) const logCustomLevelsLogPairs = [ [ { time: EPOCH, level: 35, [MESSAGE_KEY]: 'basic foo log' }, - `${TIME} - \u001B[106mfoo\u001B[49m - \u001B[36mbasic foo log\u001B[39m`, + `${TIME} - \u001B[106mfoo\u001B[49m - \u001B[36mbasic foo log\u001B[39m` ], [ { @@ -133,17 +133,17 @@ logDescriptorColorizedLogPairs.forEach(([logDescriptor, logColorized]) => { [MESSAGE_KEY]: 'basic incoming request bar log', req: { method: 'GET', - url: '/bar', - }, + url: '/bar' + } }, - `${TIME} - \u001B[33mbar\u001B[39m - GET /bar - \u001B[36mbasic incoming request bar log\u001B[39m`, - ], - ]; + `${TIME} - \u001B[33mbar\u001B[39m - GET /bar - \u001B[36mbasic incoming request bar log\u001B[39m` + ] + ] logCustomLevelsLogPairs.forEach(([logDescriptor, expectedLog]) => { test('format log correctly with custom colors per level', (t) => { - const log = messageFormat(logDescriptor, MESSAGE_KEY); - t.equal(log, expectedLog); - t.end(); - }); - }); + const log = messageFormat(logDescriptor, MESSAGE_KEY) + t.equal(log, expectedLog) + t.end() + }) + }) } From d69c6a22578aef8d4004677dcc0a406c392b6b03 Mon Sep 17 00:00:00 2001 From: Cristian Barlutiu Date: Wed, 22 May 2024 09:03:47 +0200 Subject: [PATCH 06/17] fixed broken test from merge --- test/index.test.js | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/test/index.test.js b/test/index.test.js index 8c76a6e..2c1f3bb 100644 --- a/test/index.test.js +++ b/test/index.test.js @@ -153,7 +153,10 @@ logDescriptorColorizedLogPairs.forEach(([logDescriptor, logColorized]) => { foo: 35, bar: 45 } - const messageFormat = messageFormatFactory(true, levels, { 35: 'bgCyanBright', 45: 'yellow' }) + const messageFormat = messageFormatFactory(levels, { + 35: 'bgCyanBright', + 45: 'yellow' + }) const logCustomLevelsLogPairs = [ [ @@ -176,7 +179,6 @@ logDescriptorColorizedLogPairs.forEach(([logDescriptor, logColorized]) => { logCustomLevelsLogPairs.forEach(([logDescriptor, expectedLog]) => { test('format log correctly with custom colors per level', (t) => { const log = messageFormat(logDescriptor, MESSAGE_KEY) - t.equal(log, expectedLog) t.end() }) From d8cff416c4278c4417da46264b5d2deca4296c60 Mon Sep 17 00:00:00 2001 From: Cristian Barlutiu Date: Thu, 23 May 2024 13:53:08 +0200 Subject: [PATCH 07/17] added TTY color availability --- index.js | 6 +++++- lib/messageFormatFactory.js | 4 ++-- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/index.js b/index.js index b934e5e..a59ebe3 100644 --- a/index.js +++ b/index.js @@ -6,7 +6,11 @@ const messageFormatFactory = require('./lib/messageFormatFactory') const oneLineLogger = (opts = {}) => { const { levels, colors, ...rest } = opts - const messageFormat = messageFormatFactory(levels, colors) + const messageFormat = messageFormatFactory( + levels, + colors, + pretty.isColorSupported + ) return pretty({ messageFormat, diff --git a/lib/messageFormatFactory.js b/lib/messageFormatFactory.js index 508cec6..eccbc99 100644 --- a/lib/messageFormatFactory.js +++ b/lib/messageFormatFactory.js @@ -2,14 +2,14 @@ const formatDate = require('./formatDate') const colorizerFactory = require('pino-pretty').colorizerFactory -const messageFormatFactory = (levels, colors) => { +const messageFormatFactory = (levels, colors, useColors = true) => { const customColors = colors != null ? Object.entries(colors).reduce((colors, [level, color]) => { return [...colors, [level, color]] }, []) : undefined - const colorizer = colorizerFactory(true, customColors) + const colorizer = colorizerFactory(useColors, customColors) const levelLookUp = { 60: colorizer('fatal').toLowerCase(), From 2b4fbc648a629b2cd4b1fad6cd8a13453ed431b5 Mon Sep 17 00:00:00 2001 From: Cristian Barlutiu Date: Fri, 24 May 2024 08:31:57 +0200 Subject: [PATCH 08/17] updated pino-pretty dependency --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 051fab3..f202ecf 100644 --- a/package.json +++ b/package.json @@ -11,7 +11,7 @@ "test": "test" }, "dependencies": { - "pino-pretty": "^11.0.0" + "pino-pretty": "^11.1.0" }, "devDependencies": { "benchmark": "^2.1.4", From dda4d6e12576918f78c6b32fe674b89d899159d6 Mon Sep 17 00:00:00 2001 From: Cristian Barlutiu Date: Fri, 24 May 2024 10:39:24 +0200 Subject: [PATCH 09/17] fixed tests for TTY without support for color --- test/fastify.test.js | 73 ++++++++++++++++++++++++++++++++------------ 1 file changed, 54 insertions(+), 19 deletions(-) diff --git a/test/fastify.test.js b/test/fastify.test.js index c95a8a7..e1b28d2 100644 --- a/test/fastify.test.js +++ b/test/fastify.test.js @@ -1,6 +1,7 @@ 'use strict' const { serverFactory, TIME, unmockTime, mockTime } = require('./helpers') +const pretty = require('pino-pretty') const tap = require('tap') const { test } = tap @@ -25,11 +26,19 @@ tap.beforeEach(() => { test('should log server started messages', async (t) => { await server.listen({ port: 63995 }) - - const messagesExpected = [ - `${TIME} - \x1B[32minfo\x1B[39m - \x1B[36mServer listening at http://127.0.0.1:63995\x1B[39m\n`, - `${TIME} - \x1B[32minfo\x1B[39m - \x1B[36mServer listening at http://[::1]:63995\x1B[39m\n` - ] + let messagesExpected = [] + + t.before(() => { + messagesExpected = pretty.isColorSupported + ? [ + `${TIME} - \x1B[32minfo\x1B[39m - \x1B[36mServer listening at http://127.0.0.1:63995\x1B[39m\n`, + `${TIME} - \x1B[32minfo\x1B[39m - \x1B[36mServer listening at http://[::1]:63995\x1B[39m\n` + ] + : [ + `${TIME} - info - Server listening at http://127.0.0.1:63995\n`, + `${TIME} - info - Server listening at http://[::1]:63995\n` + ] + }) // sort because the order of the messages is not guaranteed t.same(messages.sort(), messagesExpected.sort()) @@ -40,6 +49,20 @@ test('should log server started messages', async (t) => { const methods = ['GET', 'POST', 'PUT', 'DELETE', 'PATCH', 'OPTIONS', 'HEAD'] methods.forEach((method) => { test('should log request and response messages for %p', async (t) => { + let messagesExpected = [] + + t.before(() => { + messagesExpected = pretty.isColorSupported + ? [ + `${TIME} - \x1B[32minfo\x1B[39m - ${method} /path - \x1B[36mincoming request\x1B[39m\n`, + `${TIME} - \x1B[32minfo\x1B[39m - \x1B[36mrequest completed\x1B[39m\n` + ] + : [ + `${TIME} - info - ${method} /path - incoming request\n`, + `${TIME} - info - request completed\n` + ] + }) + const serverMethod = method === 'HEAD' ? 'GET' : method server[serverMethod.toLowerCase()]('/path', (_, req) => { req.send() @@ -50,16 +73,38 @@ methods.forEach((method) => { url: '/path' }) - const messagesExpected = [ - `${TIME} - \x1B[32minfo\x1B[39m - ${method} /path - \x1B[36mincoming request\x1B[39m\n`, - `${TIME} - \x1B[32minfo\x1B[39m - \x1B[36mrequest completed\x1B[39m\n` - ] t.same(messages, messagesExpected) t.end() }) }) test('should handle user defined log', async (t) => { + let messagesExpected = [] + + t.before(() => { + messagesExpected = pretty.isColorSupported + ? [ + `${TIME} - \x1B[32minfo\x1B[39m - GET /a-path-with-user-defined-log - \x1B[36mincoming request\x1B[39m\n`, + `${TIME} - \x1B[41mfatal\x1B[49m - \x1B[36ma user defined fatal log\x1B[39m\n`, + `${TIME} - \x1B[31merror\x1B[39m - \x1B[36ma user defined error log\x1B[39m\n`, + `${TIME} - \x1B[33mwarn\x1B[39m - \x1B[36ma user defined warn log\x1B[39m\n`, + `${TIME} - \x1B[32minfo\x1B[39m - \x1B[36ma user defined info log\x1B[39m\n`, + `${TIME} - \x1B[34mdebug\x1B[39m - \x1B[36ma user defined debug log\x1B[39m\n`, + `${TIME} - \x1B[90mtrace\x1B[39m - \x1B[36ma user defined trace log\x1B[39m\n`, + `${TIME} - \x1B[32minfo\x1B[39m - \x1B[36mrequest completed\x1B[39m\n` + ] + : [ + `${TIME} - info - GET /a-path-with-user-defined-log - incoming request\n`, + `${TIME} - fatal - a user defined fatal log\n`, + `${TIME} - error - a user defined error log\n`, + `${TIME} - warn - a user defined warn log\n`, + `${TIME} - info - a user defined info log\n`, + `${TIME} - debug - a user defined debug log\n`, + `${TIME} - trace - a user defined trace log\n`, + `${TIME} - info - request completed\n` + ] + }) + server = serverFactory(messages, { minimumLevel: 'trace' }) server.get('/a-path-with-user-defined-log', (res, req) => { @@ -75,16 +120,6 @@ test('should handle user defined log', async (t) => { await server.inject('/a-path-with-user-defined-log') - const messagesExpected = [ - `${TIME} - \x1B[32minfo\x1B[39m - GET /a-path-with-user-defined-log - \x1B[36mincoming request\x1B[39m\n`, - `${TIME} - \x1B[41mfatal\x1B[49m - \x1B[36ma user defined fatal log\x1B[39m\n`, - `${TIME} - \x1B[31merror\x1B[39m - \x1B[36ma user defined error log\x1B[39m\n`, - `${TIME} - \x1B[33mwarn\x1B[39m - \x1B[36ma user defined warn log\x1B[39m\n`, - `${TIME} - \x1B[32minfo\x1B[39m - \x1B[36ma user defined info log\x1B[39m\n`, - `${TIME} - \x1B[34mdebug\x1B[39m - \x1B[36ma user defined debug log\x1B[39m\n`, - `${TIME} - \x1B[90mtrace\x1B[39m - \x1B[36ma user defined trace log\x1B[39m\n`, - `${TIME} - \x1B[32minfo\x1B[39m - \x1B[36mrequest completed\x1B[39m\n` - ] t.same(messages, messagesExpected) t.end() }) From e396c5c97327a96463d77f00dbed7c433ba4bf8c Mon Sep 17 00:00:00 2001 From: Cristian Barlutiu Date: Fri, 24 May 2024 11:53:41 +0200 Subject: [PATCH 10/17] added separate tests for both support and unsuported colors --- test/fastify.test.js | 245 +++++++++++++++++------------- test/index.test.js | 353 +++++++++++++++++++++++++++---------------- 2 files changed, 363 insertions(+), 235 deletions(-) diff --git a/test/fastify.test.js b/test/fastify.test.js index e1b28d2..979fd8a 100644 --- a/test/fastify.test.js +++ b/test/fastify.test.js @@ -1,125 +1,154 @@ -'use strict' +'use strict'; -const { serverFactory, TIME, unmockTime, mockTime } = require('./helpers') -const pretty = require('pino-pretty') -const tap = require('tap') +const { serverFactory, TIME, unmockTime, mockTime } = require('./helpers'); +const pretty = require('pino-pretty'); +const tap = require('tap'); -const { test } = tap +const { test } = tap; -const messages = [] -let server = serverFactory(messages, { colorize: false }) +const messages = []; +let server = serverFactory(messages, { colorize: false }); tap.before(() => { - mockTime() -}) + mockTime(); +}); tap.teardown(() => { - unmockTime() -}) + unmockTime(); +}); tap.beforeEach(() => { // empty messages array - messages.splice(0, messages.length) + messages.splice(0, messages.length); - server = serverFactory(messages) -}) + server = serverFactory(messages); +}); test('should log server started messages', async (t) => { - await server.listen({ port: 63995 }) - let messagesExpected = [] - - t.before(() => { - messagesExpected = pretty.isColorSupported - ? [ - `${TIME} - \x1B[32minfo\x1B[39m - \x1B[36mServer listening at http://127.0.0.1:63995\x1B[39m\n`, - `${TIME} - \x1B[32minfo\x1B[39m - \x1B[36mServer listening at http://[::1]:63995\x1B[39m\n` - ] - : [ - `${TIME} - info - Server listening at http://127.0.0.1:63995\n`, - `${TIME} - info - Server listening at http://[::1]:63995\n` - ] - }) - - // sort because the order of the messages is not guaranteed - t.same(messages.sort(), messagesExpected.sort()) - await server.close() - t.end() -}) - -const methods = ['GET', 'POST', 'PUT', 'DELETE', 'PATCH', 'OPTIONS', 'HEAD'] + t.beforeEach(async () => { + await server.listen({ port: 63995 }); + t.teardown(async () => await server.close()); + }); + + t.test('colors supported in TTY', { skip: !pretty.isColorSupported }, (t) => { + const messagesExpected = [ + `${TIME} - \x1B[32minfo\x1B[39m - \x1B[36mServer listening at http://127.0.0.1:63995\x1B[39m\n`, + `${TIME} - \x1B[32minfo\x1B[39m - \x1B[36mServer listening at http://[::1]:63995\x1B[39m\n`, + ]; + + // sort because the order of the messages is not guaranteed + t.same(messages.sort(), messagesExpected.sort()); + t.end(); + }); + + t.test( + 'colors not supported in TTY', + { skip: pretty.isColorSupported }, + (t) => { + const messagesExpected = [ + `${TIME} - info - Server listening at http://127.0.0.1:63995\n`, + `${TIME} - info - Server listening at http://[::1]:63995\n`, + ]; + + // sort because the order of the messages is not guaranteed + t.same(messages.sort(), messagesExpected.sort()); + t.end(); + } + ); +}); + +const methods = ['GET', 'POST', 'PUT', 'DELETE', 'PATCH', 'OPTIONS', 'HEAD']; methods.forEach((method) => { test('should log request and response messages for %p', async (t) => { - let messagesExpected = [] - - t.before(() => { - messagesExpected = pretty.isColorSupported - ? [ - `${TIME} - \x1B[32minfo\x1B[39m - ${method} /path - \x1B[36mincoming request\x1B[39m\n`, - `${TIME} - \x1B[32minfo\x1B[39m - \x1B[36mrequest completed\x1B[39m\n` - ] - : [ - `${TIME} - info - ${method} /path - incoming request\n`, - `${TIME} - info - request completed\n` - ] - }) - - const serverMethod = method === 'HEAD' ? 'GET' : method - server[serverMethod.toLowerCase()]('/path', (_, req) => { - req.send() - }) - - await server.inject({ - method, - url: '/path' - }) - - t.same(messages, messagesExpected) - t.end() - }) -}) + t.beforeEach(async () => { + const serverMethod = method === 'HEAD' ? 'GET' : method; + server[serverMethod.toLowerCase()]('/path', (_, req) => { + req.send(); + }); + + await server.inject({ + method, + url: '/path', + }); + }); + + t.test( + 'colors supported in TTY', + { skip: !pretty.isColorSupported }, + (t) => { + const messagesExpected = [ + `${TIME} - \x1B[32minfo\x1B[39m - ${method} /path - \x1B[36mincoming request\x1B[39m\n`, + `${TIME} - \x1B[32minfo\x1B[39m - \x1B[36mrequest completed\x1B[39m\n`, + ]; + t.same(messages, messagesExpected); + t.end(); + } + ); + + t.test( + 'colors not supported in TTY', + { skip: pretty.isColorSupported }, + (t) => { + const messagesExpected = [ + `${TIME} - info - ${method} /path - incoming request\n`, + `${TIME} - info - request completed\n`, + ]; + t.same(messages, messagesExpected); + t.end(); + } + ); + }); +}); test('should handle user defined log', async (t) => { - let messagesExpected = [] - - t.before(() => { - messagesExpected = pretty.isColorSupported - ? [ - `${TIME} - \x1B[32minfo\x1B[39m - GET /a-path-with-user-defined-log - \x1B[36mincoming request\x1B[39m\n`, - `${TIME} - \x1B[41mfatal\x1B[49m - \x1B[36ma user defined fatal log\x1B[39m\n`, - `${TIME} - \x1B[31merror\x1B[39m - \x1B[36ma user defined error log\x1B[39m\n`, - `${TIME} - \x1B[33mwarn\x1B[39m - \x1B[36ma user defined warn log\x1B[39m\n`, - `${TIME} - \x1B[32minfo\x1B[39m - \x1B[36ma user defined info log\x1B[39m\n`, - `${TIME} - \x1B[34mdebug\x1B[39m - \x1B[36ma user defined debug log\x1B[39m\n`, - `${TIME} - \x1B[90mtrace\x1B[39m - \x1B[36ma user defined trace log\x1B[39m\n`, - `${TIME} - \x1B[32minfo\x1B[39m - \x1B[36mrequest completed\x1B[39m\n` - ] - : [ - `${TIME} - info - GET /a-path-with-user-defined-log - incoming request\n`, - `${TIME} - fatal - a user defined fatal log\n`, - `${TIME} - error - a user defined error log\n`, - `${TIME} - warn - a user defined warn log\n`, - `${TIME} - info - a user defined info log\n`, - `${TIME} - debug - a user defined debug log\n`, - `${TIME} - trace - a user defined trace log\n`, - `${TIME} - info - request completed\n` - ] - }) - - server = serverFactory(messages, { minimumLevel: 'trace' }) - - server.get('/a-path-with-user-defined-log', (res, req) => { - res.log.fatal('a user defined fatal log') - res.log.error('a user defined error log') - res.log.warn('a user defined warn log') - res.log.info('a user defined info log') - res.log.debug('a user defined debug log') - res.log.trace('a user defined trace log') - - req.send() - }) - - await server.inject('/a-path-with-user-defined-log') - - t.same(messages, messagesExpected) - t.end() -}) + t.beforeEach(async () => { + server = serverFactory(messages, { minimumLevel: 'trace' }); + + server.get('/a-path-with-user-defined-log', (res, req) => { + res.log.fatal('a user defined fatal log'); + res.log.error('a user defined error log'); + res.log.warn('a user defined warn log'); + res.log.info('a user defined info log'); + res.log.debug('a user defined debug log'); + res.log.trace('a user defined trace log'); + + req.send(); + }); + + await server.inject('/a-path-with-user-defined-log'); + }); + + t.test('colors supported in TTY', { skip: !pretty.isColorSupported }, (t) => { + const messagesExpected = [ + `${TIME} - \x1B[32minfo\x1B[39m - GET /a-path-with-user-defined-log - \x1B[36mincoming request\x1B[39m\n`, + `${TIME} - \x1B[41mfatal\x1B[49m - \x1B[36ma user defined fatal log\x1B[39m\n`, + `${TIME} - \x1B[31merror\x1B[39m - \x1B[36ma user defined error log\x1B[39m\n`, + `${TIME} - \x1B[33mwarn\x1B[39m - \x1B[36ma user defined warn log\x1B[39m\n`, + `${TIME} - \x1B[32minfo\x1B[39m - \x1B[36ma user defined info log\x1B[39m\n`, + `${TIME} - \x1B[34mdebug\x1B[39m - \x1B[36ma user defined debug log\x1B[39m\n`, + `${TIME} - \x1B[90mtrace\x1B[39m - \x1B[36ma user defined trace log\x1B[39m\n`, + `${TIME} - \x1B[32minfo\x1B[39m - \x1B[36mrequest completed\x1B[39m\n`, + ]; + t.same(messages, messagesExpected); + t.end(); + }); + + t.test( + 'colors not supported in TTY', + { skip: pretty.isColorSupported }, + (t) => { + const messagesExpected = [ + `${TIME} - info - GET /a-path-with-user-defined-log - incoming request\n`, + `${TIME} - fatal - a user defined fatal log\n`, + `${TIME} - error - a user defined error log\n`, + `${TIME} - warn - a user defined warn log\n`, + `${TIME} - info - a user defined info log\n`, + `${TIME} - debug - a user defined debug log\n`, + `${TIME} - trace - a user defined trace log\n`, + `${TIME} - info - request completed\n`, + ]; + t.same(messages, messagesExpected); + t.end(); + } + ); +}); diff --git a/test/index.test.js b/test/index.test.js index 2c1f3bb..035dbe0 100644 --- a/test/index.test.js +++ b/test/index.test.js @@ -1,93 +1,136 @@ -'use strict' +'use strict'; -const { EPOCH, TIME, MESSAGE_KEY, mockTime, unmockTime } = require('./helpers') -const target = require('..') -const tap = require('tap') +const { EPOCH, TIME, MESSAGE_KEY, mockTime, unmockTime } = require('./helpers'); +const target = require('..'); +const tap = require('tap'); +const pretty = require('pino-pretty'); -const { messageFormatFactory } = target +const { messageFormatFactory } = target; -const { test } = tap +const { test } = tap; -const messageFormat = messageFormatFactory() +const messageFormat = messageFormatFactory(); tap.before(() => { - mockTime() -}) + mockTime(); +}); tap.teardown(() => { - unmockTime() -}) + unmockTime(); +}); test('able to instantiate target without arguments', (t) => { - target() - t.pass() - t.end() -}) - -const logDescriptorLogPairs = [ - [ - { time: EPOCH, level: 10, [MESSAGE_KEY]: 'basic log' }, - `${TIME} - \x1B[90mtrace\x1B[39m - \x1B[36mbasic log\x1B[39m` - ], - [ - { - time: EPOCH, - level: 30, - [MESSAGE_KEY]: 'basic incoming request log', - req: { - method: 'GET', - url: '/path' - } - }, - `${TIME} - \x1B[32minfo\x1B[39m - GET /path - \x1B[36mbasic incoming request log\x1B[39m` - ] -] -logDescriptorLogPairs.forEach(([logDescriptor, expectedLog]) => { - test('format log correctly with different logDescriptor', (t) => { - const log = messageFormat(logDescriptor, MESSAGE_KEY) - t.equal(log, expectedLog) - t.end() - }) -}) - -const logDescriptorColorizedLogPairs = [ - [ - { time: EPOCH, level: 10, [MESSAGE_KEY]: 'basic log' }, - `${TIME} - \u001B[90mtrace\u001B[39m - \u001B[36mbasic log\u001B[39m` - ], - [ - { - time: EPOCH, - level: 30, - [MESSAGE_KEY]: 'basic incoming request log', - req: { - method: 'GET', - url: '/path' - } - }, - `${TIME} - \u001B[32minfo\u001B[39m - GET /path - \u001B[36mbasic incoming request log\u001B[39m` - ] -] -logDescriptorColorizedLogPairs.forEach(([logDescriptor, logColorized]) => { - test('colorize log correctly with different logDescriptor', (t) => { - const log = messageFormat(logDescriptor, MESSAGE_KEY) - - t.equal(log, logColorized) - t.end() - }) -}) - -{ + target(); + t.pass(); + t.end(); +}); + +test('format log correctly with different logDescriptor', async (t) => { + const logDescriptorLogPairs = [ + [ + { time: EPOCH, level: 10, [MESSAGE_KEY]: 'basic log' }, + `${TIME} - \x1B[90mtrace\x1B[39m - \x1B[36mbasic log\x1B[39m`, + `${TIME} - trace - basic log`, + ], + [ + { + time: EPOCH, + level: 30, + [MESSAGE_KEY]: 'basic incoming request log', + req: { + method: 'GET', + url: '/path', + }, + }, + `${TIME} - \x1B[32minfo\x1B[39m - GET /path - \x1B[36mbasic incoming request log\x1B[39m`, + `${TIME} - info - GET /path - basic incoming request log`, + ], + ]; + + await logDescriptorLogPairs.forEach( + async ([logDescriptor, expectedLogColored, expectedLogUncolored]) => { + await t.test( + 'colors supported in TTY', + { skip: !pretty.isColorSupported }, + (t) => { + const log = messageFormat(logDescriptor, MESSAGE_KEY); + t.equal(log, expectedLogColored); + t.end(); + } + ); + + await t.test( + 'colors not supported in TTY', + { skip: pretty.isColorSupported }, + (t) => { + const log = messageFormat(logDescriptor, MESSAGE_KEY); + t.equal(log, expectedLogUncolored); + t.end(); + } + ); + } + ); +}); + +test('colorize log correctly with different logDescriptor', async (t) => { + const logDescriptorColorizedLogPairs = [ + [ + { time: EPOCH, level: 10, [MESSAGE_KEY]: 'basic log' }, + `${TIME} - \u001B[90mtrace\u001B[39m - \u001B[36mbasic log\u001B[39m`, + `${TIME} - trace - basic log`, + ], + [ + { + time: EPOCH, + level: 30, + [MESSAGE_KEY]: 'basic incoming request log', + req: { + method: 'GET', + url: '/path', + }, + }, + `${TIME} - \u001B[32minfo\u001B[39m - GET /path - \u001B[36mbasic incoming request log\u001B[39m`, + `${TIME} - info - GET /path - basic incoming request log`, + ], + ]; + + await logDescriptorColorizedLogPairs.forEach( + async ([logDescriptor, expectedLogColored, expectedLogUncolored]) => { + await t.test( + 'colors supported in TTY', + { skip: !pretty.isColorSupported }, + (t) => { + const log = messageFormat(logDescriptor, MESSAGE_KEY); + t.equal(log, expectedLogColored); + t.end(); + } + ); + + await t.test( + 'colors not supported in TTY', + { skip: pretty.isColorSupported }, + (t) => { + const log = messageFormat(logDescriptor, MESSAGE_KEY); + t.equal(log, expectedLogUncolored); + t.end(); + } + ); + } + ); +}); + +test('format log correctly with custom levels', async (t) => { const levels = { foo: 35, - bar: 45 - } - const messageFormat = messageFormatFactory(levels) + bar: 45, + }; + const messageFormat = messageFormatFactory(levels); const logCustomLevelsLogPairs = [ [ { time: EPOCH, level: 35, [MESSAGE_KEY]: 'basic foo log' }, - `${TIME} - \u001b[37mfoo\u001b[39m - \u001B[36mbasic foo log\u001B[39m` + `${TIME} - \u001b[37mfoo\u001b[39m - \u001B[36mbasic foo log\u001B[39m`, + `${TIME} - foo - basic foo log`, ], [ { @@ -96,35 +139,54 @@ logDescriptorColorizedLogPairs.forEach(([logDescriptor, logColorized]) => { [MESSAGE_KEY]: 'basic incoming request bar log', req: { method: 'GET', - url: '/bar' - } + url: '/bar', + }, }, - `${TIME} - \u001b[37mbar\u001b[39m - GET /bar - \u001B[36mbasic incoming request bar log\u001B[39m` - ] - ] - logCustomLevelsLogPairs.forEach(([logDescriptor, expectedLog]) => { - test('format log correctly with custom levels', (t) => { - const log = messageFormat(logDescriptor, MESSAGE_KEY) - t.equal(log, expectedLog) - t.end() - }) - }) -} - -{ + `${TIME} - \u001b[37mbar\u001b[39m - GET /bar - \u001B[36mbasic incoming request bar log\u001B[39m`, + `${TIME} - bar - GET /bar - basic incoming request bar log`, + ], + ]; + + await logCustomLevelsLogPairs.forEach( + async ([logDescriptor, expectedLogColored, expectedLogUncolored]) => { + await t.test( + 'colors supported in TTY', + { skip: !pretty.isColorSupported }, + (t) => { + const log = messageFormat(logDescriptor, MESSAGE_KEY); + t.equal(log, expectedLogColored); + t.end(); + } + ); + + await t.test( + 'colors not supported in TTY', + { skip: pretty.isColorSupported }, + (t) => { + const log = messageFormat(logDescriptor, MESSAGE_KEY); + t.equal(log, expectedLogUncolored); + t.end(); + } + ); + } + ); +}); + +test('format log correctly with custom colors per level', async (t) => { const levels = { foo: 35, - bar: 45 - } + bar: 45, + }; const messageFormat = messageFormatFactory(levels, { 35: 'bgCyanBright', - 45: 'yellow' - }) + 45: 'yellow', + }); const logCustomLevelsLogPairs = [ [ { time: EPOCH, level: 35, [MESSAGE_KEY]: 'basic foo log' }, - `${TIME} - \u001B[106mfoo\u001B[49m - \u001B[36mbasic foo log\u001B[39m` + `${TIME} - \u001B[106mfoo\u001B[49m - \u001B[36mbasic foo log\u001B[39m`, + `${TIME} - foo - basic foo log`, ], [ { @@ -133,35 +195,54 @@ logDescriptorColorizedLogPairs.forEach(([logDescriptor, logColorized]) => { [MESSAGE_KEY]: 'basic incoming request bar log', req: { method: 'GET', - url: '/bar' - } + url: '/bar', + }, }, - `${TIME} - \u001B[33mbar\u001B[39m - GET /bar - \u001B[36mbasic incoming request bar log\u001B[39m` - ] - ] - logCustomLevelsLogPairs.forEach(([logDescriptor, expectedLog]) => { - test('format log correctly with custom colors per level', (t) => { - const log = messageFormat(logDescriptor, MESSAGE_KEY) - t.equal(log, expectedLog) - t.end() - }) - }) -} - -{ + `${TIME} - \u001B[33mbar\u001B[39m - GET /bar - \u001B[36mbasic incoming request bar log\u001B[39m`, + `${TIME} - bar - GET /bar - basic incoming request bar log`, + ], + ]; + + await logCustomLevelsLogPairs.forEach( + async ([logDescriptor, expectedLogColored, expectedLogUncolored]) => { + await t.test( + 'colors supported in TTY', + { skip: !pretty.isColorSupported }, + (t) => { + const log = messageFormat(logDescriptor, MESSAGE_KEY); + t.equal(log, expectedLogColored); + t.end(); + } + ); + + await t.test( + 'colors not supported in TTY', + { skip: pretty.isColorSupported }, + (t) => { + const log = messageFormat(logDescriptor, MESSAGE_KEY); + t.equal(log, expectedLogUncolored); + t.end(); + } + ); + } + ); +}); + +test('format log correctly with custom colors per level', async (t) => { const levels = { foo: 35, - bar: 45 - } + bar: 45, + }; const messageFormat = messageFormatFactory(levels, { 35: 'bgCyanBright', - 45: 'yellow' - }) + 45: 'yellow', + }); const logCustomLevelsLogPairs = [ [ { time: EPOCH, level: 35, [MESSAGE_KEY]: 'basic foo log' }, - `${TIME} - \u001B[106mfoo\u001B[49m - \u001B[36mbasic foo log\u001B[39m` + `${TIME} - \u001B[106mfoo\u001B[49m - \u001B[36mbasic foo log\u001B[39m`, + `${TIME} - foo - basic foo log`, ], [ { @@ -170,17 +251,35 @@ logDescriptorColorizedLogPairs.forEach(([logDescriptor, logColorized]) => { [MESSAGE_KEY]: 'basic incoming request bar log', req: { method: 'GET', - url: '/bar' - } + url: '/bar', + }, }, - `${TIME} - \u001B[33mbar\u001B[39m - GET /bar - \u001B[36mbasic incoming request bar log\u001B[39m` - ] - ] - logCustomLevelsLogPairs.forEach(([logDescriptor, expectedLog]) => { - test('format log correctly with custom colors per level', (t) => { - const log = messageFormat(logDescriptor, MESSAGE_KEY) - t.equal(log, expectedLog) - t.end() - }) - }) -} + `${TIME} - \u001B[33mbar\u001B[39m - GET /bar - \u001B[36mbasic incoming request bar log\u001B[39m`, + `${TIME} - bar - GET /bar - basic incoming request bar log`, + ], + ]; + + await logCustomLevelsLogPairs.forEach( + async ([logDescriptor, expectedLogColored, expectedLogUncolored]) => { + await t.test( + 'colors supported in TTY', + { skip: !pretty.isColorSupported }, + (t) => { + const log = messageFormat(logDescriptor, MESSAGE_KEY); + t.equal(log, expectedLogColored); + t.end(); + } + ); + + await t.test( + 'colors not supported in TTY', + { skip: pretty.isColorSupported }, + (t) => { + const log = messageFormat(logDescriptor, MESSAGE_KEY); + t.equal(log, expectedLogUncolored); + t.end(); + } + ); + } + ); +}); From d56afb29b8a0fc6b11684403388439655a064488 Mon Sep 17 00:00:00 2001 From: Cristian Barlutiu Date: Fri, 24 May 2024 11:55:32 +0200 Subject: [PATCH 11/17] fixed linting --- test/fastify.test.js | 138 ++++++++++++++-------------- test/index.test.js | 214 +++++++++++++++++++++---------------------- 2 files changed, 176 insertions(+), 176 deletions(-) diff --git a/test/fastify.test.js b/test/fastify.test.js index 979fd8a..e32da61 100644 --- a/test/fastify.test.js +++ b/test/fastify.test.js @@ -1,45 +1,45 @@ -'use strict'; +'use strict' -const { serverFactory, TIME, unmockTime, mockTime } = require('./helpers'); -const pretty = require('pino-pretty'); -const tap = require('tap'); +const { serverFactory, TIME, unmockTime, mockTime } = require('./helpers') +const pretty = require('pino-pretty') +const tap = require('tap') -const { test } = tap; +const { test } = tap -const messages = []; -let server = serverFactory(messages, { colorize: false }); +const messages = [] +let server = serverFactory(messages, { colorize: false }) tap.before(() => { - mockTime(); -}); + mockTime() +}) tap.teardown(() => { - unmockTime(); -}); + unmockTime() +}) tap.beforeEach(() => { // empty messages array - messages.splice(0, messages.length); + messages.splice(0, messages.length) - server = serverFactory(messages); -}); + server = serverFactory(messages) +}) test('should log server started messages', async (t) => { t.beforeEach(async () => { - await server.listen({ port: 63995 }); - t.teardown(async () => await server.close()); - }); + await server.listen({ port: 63995 }) + t.teardown(async () => await server.close()) + }) t.test('colors supported in TTY', { skip: !pretty.isColorSupported }, (t) => { const messagesExpected = [ `${TIME} - \x1B[32minfo\x1B[39m - \x1B[36mServer listening at http://127.0.0.1:63995\x1B[39m\n`, - `${TIME} - \x1B[32minfo\x1B[39m - \x1B[36mServer listening at http://[::1]:63995\x1B[39m\n`, - ]; + `${TIME} - \x1B[32minfo\x1B[39m - \x1B[36mServer listening at http://[::1]:63995\x1B[39m\n` + ] // sort because the order of the messages is not guaranteed - t.same(messages.sort(), messagesExpected.sort()); - t.end(); - }); + t.same(messages.sort(), messagesExpected.sort()) + t.end() + }) t.test( 'colors not supported in TTY', @@ -47,30 +47,30 @@ test('should log server started messages', async (t) => { (t) => { const messagesExpected = [ `${TIME} - info - Server listening at http://127.0.0.1:63995\n`, - `${TIME} - info - Server listening at http://[::1]:63995\n`, - ]; + `${TIME} - info - Server listening at http://[::1]:63995\n` + ] // sort because the order of the messages is not guaranteed - t.same(messages.sort(), messagesExpected.sort()); - t.end(); + t.same(messages.sort(), messagesExpected.sort()) + t.end() } - ); -}); + ) +}) -const methods = ['GET', 'POST', 'PUT', 'DELETE', 'PATCH', 'OPTIONS', 'HEAD']; +const methods = ['GET', 'POST', 'PUT', 'DELETE', 'PATCH', 'OPTIONS', 'HEAD'] methods.forEach((method) => { test('should log request and response messages for %p', async (t) => { t.beforeEach(async () => { - const serverMethod = method === 'HEAD' ? 'GET' : method; + const serverMethod = method === 'HEAD' ? 'GET' : method server[serverMethod.toLowerCase()]('/path', (_, req) => { - req.send(); - }); + req.send() + }) await server.inject({ method, - url: '/path', - }); - }); + url: '/path' + }) + }) t.test( 'colors supported in TTY', @@ -78,12 +78,12 @@ methods.forEach((method) => { (t) => { const messagesExpected = [ `${TIME} - \x1B[32minfo\x1B[39m - ${method} /path - \x1B[36mincoming request\x1B[39m\n`, - `${TIME} - \x1B[32minfo\x1B[39m - \x1B[36mrequest completed\x1B[39m\n`, - ]; - t.same(messages, messagesExpected); - t.end(); + `${TIME} - \x1B[32minfo\x1B[39m - \x1B[36mrequest completed\x1B[39m\n` + ] + t.same(messages, messagesExpected) + t.end() } - ); + ) t.test( 'colors not supported in TTY', @@ -91,32 +91,32 @@ methods.forEach((method) => { (t) => { const messagesExpected = [ `${TIME} - info - ${method} /path - incoming request\n`, - `${TIME} - info - request completed\n`, - ]; - t.same(messages, messagesExpected); - t.end(); + `${TIME} - info - request completed\n` + ] + t.same(messages, messagesExpected) + t.end() } - ); - }); -}); + ) + }) +}) test('should handle user defined log', async (t) => { t.beforeEach(async () => { - server = serverFactory(messages, { minimumLevel: 'trace' }); + server = serverFactory(messages, { minimumLevel: 'trace' }) server.get('/a-path-with-user-defined-log', (res, req) => { - res.log.fatal('a user defined fatal log'); - res.log.error('a user defined error log'); - res.log.warn('a user defined warn log'); - res.log.info('a user defined info log'); - res.log.debug('a user defined debug log'); - res.log.trace('a user defined trace log'); + res.log.fatal('a user defined fatal log') + res.log.error('a user defined error log') + res.log.warn('a user defined warn log') + res.log.info('a user defined info log') + res.log.debug('a user defined debug log') + res.log.trace('a user defined trace log') - req.send(); - }); + req.send() + }) - await server.inject('/a-path-with-user-defined-log'); - }); + await server.inject('/a-path-with-user-defined-log') + }) t.test('colors supported in TTY', { skip: !pretty.isColorSupported }, (t) => { const messagesExpected = [ @@ -127,11 +127,11 @@ test('should handle user defined log', async (t) => { `${TIME} - \x1B[32minfo\x1B[39m - \x1B[36ma user defined info log\x1B[39m\n`, `${TIME} - \x1B[34mdebug\x1B[39m - \x1B[36ma user defined debug log\x1B[39m\n`, `${TIME} - \x1B[90mtrace\x1B[39m - \x1B[36ma user defined trace log\x1B[39m\n`, - `${TIME} - \x1B[32minfo\x1B[39m - \x1B[36mrequest completed\x1B[39m\n`, - ]; - t.same(messages, messagesExpected); - t.end(); - }); + `${TIME} - \x1B[32minfo\x1B[39m - \x1B[36mrequest completed\x1B[39m\n` + ] + t.same(messages, messagesExpected) + t.end() + }) t.test( 'colors not supported in TTY', @@ -145,10 +145,10 @@ test('should handle user defined log', async (t) => { `${TIME} - info - a user defined info log\n`, `${TIME} - debug - a user defined debug log\n`, `${TIME} - trace - a user defined trace log\n`, - `${TIME} - info - request completed\n`, - ]; - t.same(messages, messagesExpected); - t.end(); + `${TIME} - info - request completed\n` + ] + t.same(messages, messagesExpected) + t.end() } - ); -}); + ) +}) diff --git a/test/index.test.js b/test/index.test.js index 035dbe0..bccd8ca 100644 --- a/test/index.test.js +++ b/test/index.test.js @@ -1,36 +1,36 @@ -'use strict'; +'use strict' -const { EPOCH, TIME, MESSAGE_KEY, mockTime, unmockTime } = require('./helpers'); -const target = require('..'); -const tap = require('tap'); -const pretty = require('pino-pretty'); +const { EPOCH, TIME, MESSAGE_KEY, mockTime, unmockTime } = require('./helpers') +const target = require('..') +const tap = require('tap') +const pretty = require('pino-pretty') -const { messageFormatFactory } = target; +const { messageFormatFactory } = target -const { test } = tap; +const { test } = tap -const messageFormat = messageFormatFactory(); +const messageFormat = messageFormatFactory() tap.before(() => { - mockTime(); -}); + mockTime() +}) tap.teardown(() => { - unmockTime(); -}); + unmockTime() +}) test('able to instantiate target without arguments', (t) => { - target(); - t.pass(); - t.end(); -}); + target() + t.pass() + t.end() +}) test('format log correctly with different logDescriptor', async (t) => { const logDescriptorLogPairs = [ [ { time: EPOCH, level: 10, [MESSAGE_KEY]: 'basic log' }, `${TIME} - \x1B[90mtrace\x1B[39m - \x1B[36mbasic log\x1B[39m`, - `${TIME} - trace - basic log`, + `${TIME} - trace - basic log` ], [ { @@ -39,13 +39,13 @@ test('format log correctly with different logDescriptor', async (t) => { [MESSAGE_KEY]: 'basic incoming request log', req: { method: 'GET', - url: '/path', - }, + url: '/path' + } }, `${TIME} - \x1B[32minfo\x1B[39m - GET /path - \x1B[36mbasic incoming request log\x1B[39m`, - `${TIME} - info - GET /path - basic incoming request log`, - ], - ]; + `${TIME} - info - GET /path - basic incoming request log` + ] + ] await logDescriptorLogPairs.forEach( async ([logDescriptor, expectedLogColored, expectedLogUncolored]) => { @@ -53,31 +53,31 @@ test('format log correctly with different logDescriptor', async (t) => { 'colors supported in TTY', { skip: !pretty.isColorSupported }, (t) => { - const log = messageFormat(logDescriptor, MESSAGE_KEY); - t.equal(log, expectedLogColored); - t.end(); + const log = messageFormat(logDescriptor, MESSAGE_KEY) + t.equal(log, expectedLogColored) + t.end() } - ); + ) await t.test( 'colors not supported in TTY', { skip: pretty.isColorSupported }, (t) => { - const log = messageFormat(logDescriptor, MESSAGE_KEY); - t.equal(log, expectedLogUncolored); - t.end(); + const log = messageFormat(logDescriptor, MESSAGE_KEY) + t.equal(log, expectedLogUncolored) + t.end() } - ); + ) } - ); -}); + ) +}) test('colorize log correctly with different logDescriptor', async (t) => { const logDescriptorColorizedLogPairs = [ [ { time: EPOCH, level: 10, [MESSAGE_KEY]: 'basic log' }, `${TIME} - \u001B[90mtrace\u001B[39m - \u001B[36mbasic log\u001B[39m`, - `${TIME} - trace - basic log`, + `${TIME} - trace - basic log` ], [ { @@ -86,13 +86,13 @@ test('colorize log correctly with different logDescriptor', async (t) => { [MESSAGE_KEY]: 'basic incoming request log', req: { method: 'GET', - url: '/path', - }, + url: '/path' + } }, `${TIME} - \u001B[32minfo\u001B[39m - GET /path - \u001B[36mbasic incoming request log\u001B[39m`, - `${TIME} - info - GET /path - basic incoming request log`, - ], - ]; + `${TIME} - info - GET /path - basic incoming request log` + ] + ] await logDescriptorColorizedLogPairs.forEach( async ([logDescriptor, expectedLogColored, expectedLogUncolored]) => { @@ -100,37 +100,37 @@ test('colorize log correctly with different logDescriptor', async (t) => { 'colors supported in TTY', { skip: !pretty.isColorSupported }, (t) => { - const log = messageFormat(logDescriptor, MESSAGE_KEY); - t.equal(log, expectedLogColored); - t.end(); + const log = messageFormat(logDescriptor, MESSAGE_KEY) + t.equal(log, expectedLogColored) + t.end() } - ); + ) await t.test( 'colors not supported in TTY', { skip: pretty.isColorSupported }, (t) => { - const log = messageFormat(logDescriptor, MESSAGE_KEY); - t.equal(log, expectedLogUncolored); - t.end(); + const log = messageFormat(logDescriptor, MESSAGE_KEY) + t.equal(log, expectedLogUncolored) + t.end() } - ); + ) } - ); -}); + ) +}) test('format log correctly with custom levels', async (t) => { const levels = { foo: 35, - bar: 45, - }; - const messageFormat = messageFormatFactory(levels); + bar: 45 + } + const messageFormat = messageFormatFactory(levels) const logCustomLevelsLogPairs = [ [ { time: EPOCH, level: 35, [MESSAGE_KEY]: 'basic foo log' }, `${TIME} - \u001b[37mfoo\u001b[39m - \u001B[36mbasic foo log\u001B[39m`, - `${TIME} - foo - basic foo log`, + `${TIME} - foo - basic foo log` ], [ { @@ -139,13 +139,13 @@ test('format log correctly with custom levels', async (t) => { [MESSAGE_KEY]: 'basic incoming request bar log', req: { method: 'GET', - url: '/bar', - }, + url: '/bar' + } }, `${TIME} - \u001b[37mbar\u001b[39m - GET /bar - \u001B[36mbasic incoming request bar log\u001B[39m`, - `${TIME} - bar - GET /bar - basic incoming request bar log`, - ], - ]; + `${TIME} - bar - GET /bar - basic incoming request bar log` + ] + ] await logCustomLevelsLogPairs.forEach( async ([logDescriptor, expectedLogColored, expectedLogUncolored]) => { @@ -153,40 +153,40 @@ test('format log correctly with custom levels', async (t) => { 'colors supported in TTY', { skip: !pretty.isColorSupported }, (t) => { - const log = messageFormat(logDescriptor, MESSAGE_KEY); - t.equal(log, expectedLogColored); - t.end(); + const log = messageFormat(logDescriptor, MESSAGE_KEY) + t.equal(log, expectedLogColored) + t.end() } - ); + ) await t.test( 'colors not supported in TTY', { skip: pretty.isColorSupported }, (t) => { - const log = messageFormat(logDescriptor, MESSAGE_KEY); - t.equal(log, expectedLogUncolored); - t.end(); + const log = messageFormat(logDescriptor, MESSAGE_KEY) + t.equal(log, expectedLogUncolored) + t.end() } - ); + ) } - ); -}); + ) +}) test('format log correctly with custom colors per level', async (t) => { const levels = { foo: 35, - bar: 45, - }; + bar: 45 + } const messageFormat = messageFormatFactory(levels, { 35: 'bgCyanBright', - 45: 'yellow', - }); + 45: 'yellow' + }) const logCustomLevelsLogPairs = [ [ { time: EPOCH, level: 35, [MESSAGE_KEY]: 'basic foo log' }, `${TIME} - \u001B[106mfoo\u001B[49m - \u001B[36mbasic foo log\u001B[39m`, - `${TIME} - foo - basic foo log`, + `${TIME} - foo - basic foo log` ], [ { @@ -195,13 +195,13 @@ test('format log correctly with custom colors per level', async (t) => { [MESSAGE_KEY]: 'basic incoming request bar log', req: { method: 'GET', - url: '/bar', - }, + url: '/bar' + } }, `${TIME} - \u001B[33mbar\u001B[39m - GET /bar - \u001B[36mbasic incoming request bar log\u001B[39m`, - `${TIME} - bar - GET /bar - basic incoming request bar log`, - ], - ]; + `${TIME} - bar - GET /bar - basic incoming request bar log` + ] + ] await logCustomLevelsLogPairs.forEach( async ([logDescriptor, expectedLogColored, expectedLogUncolored]) => { @@ -209,40 +209,40 @@ test('format log correctly with custom colors per level', async (t) => { 'colors supported in TTY', { skip: !pretty.isColorSupported }, (t) => { - const log = messageFormat(logDescriptor, MESSAGE_KEY); - t.equal(log, expectedLogColored); - t.end(); + const log = messageFormat(logDescriptor, MESSAGE_KEY) + t.equal(log, expectedLogColored) + t.end() } - ); + ) await t.test( 'colors not supported in TTY', { skip: pretty.isColorSupported }, (t) => { - const log = messageFormat(logDescriptor, MESSAGE_KEY); - t.equal(log, expectedLogUncolored); - t.end(); + const log = messageFormat(logDescriptor, MESSAGE_KEY) + t.equal(log, expectedLogUncolored) + t.end() } - ); + ) } - ); -}); + ) +}) test('format log correctly with custom colors per level', async (t) => { const levels = { foo: 35, - bar: 45, - }; + bar: 45 + } const messageFormat = messageFormatFactory(levels, { 35: 'bgCyanBright', - 45: 'yellow', - }); + 45: 'yellow' + }) const logCustomLevelsLogPairs = [ [ { time: EPOCH, level: 35, [MESSAGE_KEY]: 'basic foo log' }, `${TIME} - \u001B[106mfoo\u001B[49m - \u001B[36mbasic foo log\u001B[39m`, - `${TIME} - foo - basic foo log`, + `${TIME} - foo - basic foo log` ], [ { @@ -251,13 +251,13 @@ test('format log correctly with custom colors per level', async (t) => { [MESSAGE_KEY]: 'basic incoming request bar log', req: { method: 'GET', - url: '/bar', - }, + url: '/bar' + } }, `${TIME} - \u001B[33mbar\u001B[39m - GET /bar - \u001B[36mbasic incoming request bar log\u001B[39m`, - `${TIME} - bar - GET /bar - basic incoming request bar log`, - ], - ]; + `${TIME} - bar - GET /bar - basic incoming request bar log` + ] + ] await logCustomLevelsLogPairs.forEach( async ([logDescriptor, expectedLogColored, expectedLogUncolored]) => { @@ -265,21 +265,21 @@ test('format log correctly with custom colors per level', async (t) => { 'colors supported in TTY', { skip: !pretty.isColorSupported }, (t) => { - const log = messageFormat(logDescriptor, MESSAGE_KEY); - t.equal(log, expectedLogColored); - t.end(); + const log = messageFormat(logDescriptor, MESSAGE_KEY) + t.equal(log, expectedLogColored) + t.end() } - ); + ) await t.test( 'colors not supported in TTY', { skip: pretty.isColorSupported }, (t) => { - const log = messageFormat(logDescriptor, MESSAGE_KEY); - t.equal(log, expectedLogUncolored); - t.end(); + const log = messageFormat(logDescriptor, MESSAGE_KEY) + t.equal(log, expectedLogUncolored) + t.end() } - ); + ) } - ); -}); + ) +}) From c0b86c4af03449fa6001374dd664471811e586d7 Mon Sep 17 00:00:00 2001 From: Cristian Barlutiu Date: Fri, 24 May 2024 12:07:44 +0200 Subject: [PATCH 12/17] change default handling --- lib/messageFormatFactory.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/messageFormatFactory.js b/lib/messageFormatFactory.js index eccbc99..82b67ef 100644 --- a/lib/messageFormatFactory.js +++ b/lib/messageFormatFactory.js @@ -2,14 +2,14 @@ const formatDate = require('./formatDate') const colorizerFactory = require('pino-pretty').colorizerFactory -const messageFormatFactory = (levels, colors, useColors = true) => { +const messageFormatFactory = (levels, colors, useColors) => { const customColors = colors != null ? Object.entries(colors).reduce((colors, [level, color]) => { return [...colors, [level, color]] }, []) : undefined - const colorizer = colorizerFactory(useColors, customColors) + const colorizer = colorizerFactory(useColors ?? true, customColors) const levelLookUp = { 60: colorizer('fatal').toLowerCase(), From 3ad8b342d1e9e8085a44476659bae37c693dea30 Mon Sep 17 00:00:00 2001 From: Cristian Barlutiu Date: Fri, 24 May 2024 12:17:37 +0200 Subject: [PATCH 13/17] removed duplicate test --- lib/messageFormatFactory.js | 2 +- test/index.test.js | 56 ------------------------------------- 2 files changed, 1 insertion(+), 57 deletions(-) diff --git a/lib/messageFormatFactory.js b/lib/messageFormatFactory.js index 82b67ef..8714304 100644 --- a/lib/messageFormatFactory.js +++ b/lib/messageFormatFactory.js @@ -9,7 +9,7 @@ const messageFormatFactory = (levels, colors, useColors) => { return [...colors, [level, color]] }, []) : undefined - const colorizer = colorizerFactory(useColors ?? true, customColors) + const colorizer = colorizerFactory(useColors, customColors) const levelLookUp = { 60: colorizer('fatal').toLowerCase(), diff --git a/test/index.test.js b/test/index.test.js index bccd8ca..e7d6dbc 100644 --- a/test/index.test.js +++ b/test/index.test.js @@ -227,59 +227,3 @@ test('format log correctly with custom colors per level', async (t) => { } ) }) - -test('format log correctly with custom colors per level', async (t) => { - const levels = { - foo: 35, - bar: 45 - } - const messageFormat = messageFormatFactory(levels, { - 35: 'bgCyanBright', - 45: 'yellow' - }) - - const logCustomLevelsLogPairs = [ - [ - { time: EPOCH, level: 35, [MESSAGE_KEY]: 'basic foo log' }, - `${TIME} - \u001B[106mfoo\u001B[49m - \u001B[36mbasic foo log\u001B[39m`, - `${TIME} - foo - basic foo log` - ], - [ - { - time: EPOCH, - level: 45, - [MESSAGE_KEY]: 'basic incoming request bar log', - req: { - method: 'GET', - url: '/bar' - } - }, - `${TIME} - \u001B[33mbar\u001B[39m - GET /bar - \u001B[36mbasic incoming request bar log\u001B[39m`, - `${TIME} - bar - GET /bar - basic incoming request bar log` - ] - ] - - await logCustomLevelsLogPairs.forEach( - async ([logDescriptor, expectedLogColored, expectedLogUncolored]) => { - await t.test( - 'colors supported in TTY', - { skip: !pretty.isColorSupported }, - (t) => { - const log = messageFormat(logDescriptor, MESSAGE_KEY) - t.equal(log, expectedLogColored) - t.end() - } - ) - - await t.test( - 'colors not supported in TTY', - { skip: pretty.isColorSupported }, - (t) => { - const log = messageFormat(logDescriptor, MESSAGE_KEY) - t.equal(log, expectedLogUncolored) - t.end() - } - ) - } - ) -}) From 41d2cdb0a28d2815847fef0736379294197af196 Mon Sep 17 00:00:00 2001 From: Cristian Barlutiu Date: Fri, 24 May 2024 16:06:13 +0200 Subject: [PATCH 14/17] small test fix --- test/index.test.js | 32 +++++++++++++++++++++++++------- 1 file changed, 25 insertions(+), 7 deletions(-) diff --git a/test/index.test.js b/test/index.test.js index e7d6dbc..d79a788 100644 --- a/test/index.test.js +++ b/test/index.test.js @@ -4,12 +4,15 @@ const { EPOCH, TIME, MESSAGE_KEY, mockTime, unmockTime } = require('./helpers') const target = require('..') const tap = require('tap') const pretty = require('pino-pretty') - const { messageFormatFactory } = target const { test } = tap -const messageFormat = messageFormatFactory() +const messageFormat = messageFormatFactory( + undefined, + undefined, + pretty.isColorSupported +) tap.before(() => { mockTime() @@ -54,6 +57,13 @@ test('format log correctly with different logDescriptor', async (t) => { { skip: !pretty.isColorSupported }, (t) => { const log = messageFormat(logDescriptor, MESSAGE_KEY) + console.log( + 'TEST\n', + JSON.stringify(log, undefined, 4), + '\n', + JSON.stringify(expectedLogColored, undefined, 4), + '\n' + ) t.equal(log, expectedLogColored) t.end() } @@ -124,7 +134,11 @@ test('format log correctly with custom levels', async (t) => { foo: 35, bar: 45 } - const messageFormat = messageFormatFactory(levels) + const messageFormat = messageFormatFactory( + levels, + undefined, + pretty.isColorSupported + ) const logCustomLevelsLogPairs = [ [ @@ -177,10 +191,14 @@ test('format log correctly with custom colors per level', async (t) => { foo: 35, bar: 45 } - const messageFormat = messageFormatFactory(levels, { - 35: 'bgCyanBright', - 45: 'yellow' - }) + const messageFormat = messageFormatFactory( + levels, + { + 35: 'bgCyanBright', + 45: 'yellow' + }, + pretty.isColorSupported + ) const logCustomLevelsLogPairs = [ [ From 603d05b632708afd3c859446992dbfe0fa7ae647 Mon Sep 17 00:00:00 2001 From: Cristian Barlutiu Date: Fri, 24 May 2024 16:09:00 +0200 Subject: [PATCH 15/17] removed logs --- test/index.test.js | 7 ------- 1 file changed, 7 deletions(-) diff --git a/test/index.test.js b/test/index.test.js index d79a788..f5732a0 100644 --- a/test/index.test.js +++ b/test/index.test.js @@ -57,13 +57,6 @@ test('format log correctly with different logDescriptor', async (t) => { { skip: !pretty.isColorSupported }, (t) => { const log = messageFormat(logDescriptor, MESSAGE_KEY) - console.log( - 'TEST\n', - JSON.stringify(log, undefined, 4), - '\n', - JSON.stringify(expectedLogColored, undefined, 4), - '\n' - ) t.equal(log, expectedLogColored) t.end() } From 2fe6b3bcf8c7f5f6ce2cffa6510f09b71d03ac2a Mon Sep 17 00:00:00 2001 From: Cristian Barlutiu Date: Wed, 12 Jun 2024 15:25:19 +0200 Subject: [PATCH 16/17] updated option and docs --- README.md | 16 ++++++++++++++++ index.js | 26 +++++++++++++------------- 2 files changed, 29 insertions(+), 13 deletions(-) diff --git a/README.md b/README.md index 8115333..66b36bd 100644 --- a/README.md +++ b/README.md @@ -39,6 +39,22 @@ const server = fastify({ }); ``` +## Colors + +Colors are enabled by default when supported. To manually disable the colors you need to set the `transport.colorize` option to `false`. For more options check the `colorette` [docs](https://github.com/jorgebucaran/colorette?tab=readme-ov-file#environment). + +```js +const server = fastify({ + logger: { + transport: { + target: "@fastify/one-line-logger", + colorize: false, + }, + }, +}); +``` + + ## Custom levels Custom levels could be used by passing it into logger opts diff --git a/index.js b/index.js index a59ebe3..db1ee93 100644 --- a/index.js +++ b/index.js @@ -1,28 +1,28 @@ -'use strict' +'use strict'; -const pretty = require('pino-pretty') -const messageFormatFactory = require('./lib/messageFormatFactory') +const pretty = require('pino-pretty'); +const messageFormatFactory = require('./lib/messageFormatFactory'); const oneLineLogger = (opts = {}) => { - const { levels, colors, ...rest } = opts + const { levels, colors, ...rest } = opts; const messageFormat = messageFormatFactory( levels, colors, - pretty.isColorSupported - ) + opts.colorize ?? pretty.isColorSupported + ); return pretty({ messageFormat, ignore: 'pid,hostname,time,level', hideObject: true, colorize: false, - ...rest - }) -} + ...rest, + }); +}; -module.exports = oneLineLogger -module.exports.default = oneLineLogger -module.exports.oneLineLogger = oneLineLogger +module.exports = oneLineLogger; +module.exports.default = oneLineLogger; +module.exports.oneLineLogger = oneLineLogger; -module.exports.messageFormatFactory = messageFormatFactory +module.exports.messageFormatFactory = messageFormatFactory; From 484ae674bcecabe2cdf9c2002d5bd27a59e6fee0 Mon Sep 17 00:00:00 2001 From: Cristian Barlutiu Date: Wed, 12 Jun 2024 17:27:54 +0200 Subject: [PATCH 17/17] fixed linting issues --- index.js | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/index.js b/index.js index db1ee93..033c83b 100644 --- a/index.js +++ b/index.js @@ -1,28 +1,28 @@ -'use strict'; +'use strict' -const pretty = require('pino-pretty'); -const messageFormatFactory = require('./lib/messageFormatFactory'); +const pretty = require('pino-pretty') +const messageFormatFactory = require('./lib/messageFormatFactory') const oneLineLogger = (opts = {}) => { - const { levels, colors, ...rest } = opts; + const { levels, colors, ...rest } = opts const messageFormat = messageFormatFactory( levels, colors, opts.colorize ?? pretty.isColorSupported - ); + ) return pretty({ messageFormat, ignore: 'pid,hostname,time,level', hideObject: true, colorize: false, - ...rest, - }); -}; + ...rest + }) +} -module.exports = oneLineLogger; -module.exports.default = oneLineLogger; -module.exports.oneLineLogger = oneLineLogger; +module.exports = oneLineLogger +module.exports.default = oneLineLogger +module.exports.oneLineLogger = oneLineLogger -module.exports.messageFormatFactory = messageFormatFactory; +module.exports.messageFormatFactory = messageFormatFactory