diff --git a/CHANGELOG.md b/CHANGELOG.md index ee43ab9..b6d74bc 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] +* add custom hooks + +## v7.1.0 - 2024-02-16 + * add custom log level ## v7.0.3 - 2023-11-30 diff --git a/docs/cli-flags.md b/docs/cli-flags.md index c7d087b..2b7b43d 100644 --- a/docs/cli-flags.md +++ b/docs/cli-flags.md @@ -3,11 +3,11 @@ The **lc39** cli command support some degree of personalization via command flags. Here are listed all the available flags, their default values and the accepted ones. -| Description | Short Command | Full Command | Default Value | -| ------------ | ------------- |--------------| ------------- | -| Port to listen on | `-p` | `--port` | `3000` | -| Log level | `-l` | `--log-level` | `info` | -| Set the prefix | `-x` | `--prefix` | | -| The path of the dotenv file to load during launch | `-e` | `--env-path` | | -| Expose Prometheus metrics | | `--expose-metrics` | `true` | -| Enable tracing | | `--enable-tracing` | `false` | +| Description | Short Command | Full Command | Default Value | +|---------------------------------------------------|---------------|--------------------|---------------| +| Port to listen on | `-p` | `--port` | `3000` | +| Log level | `-l` | `--log-level` | `info` | +| Set the prefix | `-x` | `--prefix` | | +| The path of the dotenv file to load during launch | `-e` | `--env-path` | | +| Expose Prometheus metrics | | `--expose-metrics` | `true` | +| Enable tracing | | `--enable-tracing` | `false` | diff --git a/docs/logging.md b/docs/logging.md index 9f4244c..86e7345 100644 --- a/docs/logging.md +++ b/docs/logging.md @@ -2,7 +2,7 @@ The library generates logs following [Mia-Platform logging guidelines](https://docs.mia-platform.eu/docs/development_suite/monitoring/resources/pods#pod-logs). -For a json schema example check [test log schema file](https://github.com/mia-platform/lc39/blob/master/tests/log.schema.json) +For a JSON schema example check [test log schema file](https://github.com/mia-platform/lc39/blob/master/tests/log.schema.json) ## Additional information to response logs diff --git a/docs/service-options.md b/docs/service-options.md index 21f901a..55d238c 100644 --- a/docs/service-options.md +++ b/docs/service-options.md @@ -1,7 +1,7 @@ # Service Options If you want to customize the Fastify instance over the default settings that **lc39** will set -you can export a json object in your module: +you can export a JSON object in your module: ```javascript module.exports.options = { @@ -19,19 +19,31 @@ module.exports.options = { customLevels: { audit: 35, success: 70 + }, + hooks: { + logMethod (inputArgs, method, level) { + // Here you can manipulate the parameters passed to the logger methods + return method.apply(this, inputArgs) // This achieves the default behavior, i.e. not manipulating anything + } } } } ``` -The values supported in this object are the supported keys and value for the Fastify server instance -that you can find at this [link][fastify-server-options]; with the exception of the `logger` parameter. +The key and values supported in this object correspond to the options of the Fastify server instance documented at [link][fastify-server-options], +with the exception of the `logger` parameter, that allows you to: + +- add a [custom logging level][pino-custom-levels] using the `customLevel` field; +- add [hooks][pino-hooks] to customize internal logger operations using the `hooks` field. + Instead you can customize the `pino` instance via the `logLevel` and `logger.customLevels` keys, and you can modify the redaction rules via the `redact` key. For this key the accepted values are listed [here][pino-redact-options]. You have the following additional keys: - `oasRefResolver` that is passed to the `fastify-swagger` plugin as `refResolver`; its usage can be found [here][fastify-swagger-refs]. -[fastify-server-options]: https://github.com/fastify/fastify/blob/main/docs/Reference/Server.md -[pino-redact-options]: https://github.com/pinojs/pino/blob/master/docs/redaction.md [fastify-sensible-error-handler]: https://github.com/fastify/fastify-sensible#custom-error-handler +[fastify-server-options]: https://github.com/fastify/fastify/blob/main/docs/Reference/Server.md [fastify-swagger-refs]: https://github.com/fastify/fastify-swagger#managing-your-refs +[pino-custom-levels]: https://github.com/pinojs/pino/blob/master/docs/api.md#opt-customlevels +[pino-hooks]: https://github.com/pinojs/pino/blob/master/docs/api.md#hooks-object +[pino-redact-options]: https://github.com/pinojs/pino/blob/master/docs/redaction.md diff --git a/test-d/index.d-test.ts b/test-d/index.d-test.ts index 61deb36..3855052 100644 --- a/test-d/index.d-test.ts +++ b/test-d/index.d-test.ts @@ -35,6 +35,11 @@ const serverWithModuleAndAllOptions = lc39(plugin, { logger: { customLevels: { audit: 35, + }, + hooks: { + logMethod (inputArgs, method, level) { + return method.apply(this, inputArgs) + } } }, healthinessHandler: async (fastify) => { diff --git a/tests/custom-logger.test.js b/tests/custom-logger.test.js index 345c0fb..d9646a0 100644 --- a/tests/custom-logger.test.js +++ b/tests/custom-logger.test.js @@ -53,7 +53,11 @@ test('Test generation custom logger default options', assert => { assert.end() }) -test('Test generation custom logger custom options', assert => { +test('Test generation custom logger with custom options', assert => { + // eslint-disable-next-line no-unused-vars + const logMethod = (inputArgs, method, level) => { + return method.apply(this, inputArgs) + } const options = { redact: { censor: '[BRACE YOURSELF, GDPR IS COMING]', @@ -68,6 +72,9 @@ test('Test generation custom logger custom options', assert => { audit: 35, success: 70, }, + hooks: { + logMethod, + }, }, } @@ -83,7 +90,9 @@ test('Test generation custom logger custom options', assert => { audit: 35, success: 70, }, - + hooks: { + logMethod, + }, }) assert.end() @@ -246,3 +255,39 @@ test('Test log with custom log levels', async assert => { assert.strictSame(payload, 'success') assert.end() }) + +test('Test with custom hooks', async assert => { + const data = [] + const logStream = new PassThrough() + .on('data', (streamData) => { + data.push(Buffer.from(streamData, 'utf8').toString()) + }) + + const fastifyInstance = await launch('./tests/modules/custom-hooks', { + stream: logStream, + }) + assert.ok(fastifyInstance) + + await fastifyInstance.inject({ + method: 'POST', + url: `/custom-hooks`, + }) + + await fastifyInstance.close() + data.reduce((acc, log) => { + const parseLog = JSON.parse(log) + if (parseLog.msg === 'Custom hooks> Log message with arguments') { + assert.match(parseLog, { + auditEvent: { + auditInfo: 'audit details', + }, + }) + } + if (parseLog.msg === 'Custom hooks> Log message without arguments') { + assert.strictSame(parseLog.auditEvent, undefined) + } + return [...acc, log] + }, []) + + assert.end() +}) diff --git a/tests/launch-fastify.test.js b/tests/launch-fastify.test.js index 5663548..b41fad5 100644 --- a/tests/launch-fastify.test.js +++ b/tests/launch-fastify.test.js @@ -815,3 +815,16 @@ test('should use correctly the logger with custom levels', async assert => { assert.end() }) + +test('should use correctly logger custom hooks', async assert => { + const fastifyInstance = await launch('./tests/modules/custom-hooks', {}) + assert.teardown(() => fastifyInstance.close()) + + const response = await fastifyInstance.inject({ + method: 'POST', + url: '/custom-hooks', + }) + + assert.strictSame(response.statusCode, 200) + assert.end() +}) diff --git a/tests/modules/custom-hooks.js b/tests/modules/custom-hooks.js new file mode 100644 index 0000000..a08e336 --- /dev/null +++ b/tests/modules/custom-hooks.js @@ -0,0 +1,44 @@ +/* + * Copyright 2024 Mia srl + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* istanbul ignore file */ + +'use strict' + +module.exports = async function plugin(fastify) { + fastify.post('/custom-hooks', function handler(request, reply) { + this.log.info({ + auditInfo: 'audit details', + }, 'Custom hooks> Log message with arguments') + this.log.info('Custom hooks> Log message without arguments') + reply.send({}) + }) +} + +module.exports.options = { + logger: { + hooks: { + // eslint-disable-next-line no-unused-vars + logMethod(inputArgs, method, level) { + if (inputArgs.length >= 2) { + const arg1 = inputArgs.shift() + return method.apply(this, [{ auditEvent: arg1 }, ...inputArgs]) + } + return method.apply(this, inputArgs) + }, + }, + }, +}