From 3f1c89a1804499d4e6319ba2da496d2eb9391335 Mon Sep 17 00:00:00 2001 From: Cassio Deon Date: Mon, 15 Mar 2021 13:59:19 -0300 Subject: [PATCH 1/2] Added tracing in logs and fixed meta parameters --- README.md | 102 +++++++++++++++++++++++++++-- package-lock.json | 83 ++++++++++++++---------- package.json | 5 +- src/index.d.ts | 5 ++ src/index.js | 9 +++ src/lib/logger.d.ts | 16 ++--- src/lib/logger.js | 9 +++ src/middleware/trace.d.ts | 3 + src/middleware/trace.js | 25 ++++++++ test/index.spec.js | 9 +++ test/middleware/trace.spec.js | 117 ++++++++++++++++++++++++++++++++++ 11 files changed, 331 insertions(+), 52 deletions(-) create mode 100644 src/index.d.ts create mode 100644 src/index.js create mode 100644 src/middleware/trace.d.ts create mode 100644 src/middleware/trace.js create mode 100644 test/index.spec.js create mode 100644 test/middleware/trace.spec.js diff --git a/README.md b/README.md index 9ba7c9c..34cea36 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ # Zenvia Logger for Node.js -A wrapper for [Winston](https://github.com/winstonjs/winston) Logging [Node.js](https://nodejs.org/) library that formats the output on STDOUT as [Logstash](https://www.elastic.co/logstash) JSON format. +A wrapper for [Winston](https://github.com/winstonjs/winston) Logging [Node.js](https://nodejs.org/) library that formats the output on STDOUT as [Logstash](https://www.elastic.co/logstash) JSON format. Since version 1.5.0 it is possible to use log tracking. Zenvia Logger uses the [cls-trace](https://www.npmjs.com/package/cls-rtracer) to perform the tracking [![License](https://img.shields.io/github/license/zenvia/zenvia-logger-node.svg)](LICENSE.md) [![Build Status](https://travis-ci.com/zenvia/zenvia-logger-node.svg?branch=master)](https://travis-ci.com/zenvia/zenvia-logger-node) @@ -28,17 +28,62 @@ The following environment variables can be used for increase the log information - **HOST** or **HOSTNAME**: value to filled the "host" field in the output JSON. - **LOGGING_LEVEL**: set the level of messages that the logger should log. Default to `DEBUG`. - **LOGGING_FORMATTER_DISABLED** *(version 1.1.0 and above)*: When `true`, the output logging will not be formatted to JSON. Useful during development time. Default to `false`. +- **LOGGING_FRAMEWORK_MIDDLEWARE** *(version 1.5.0 and above)*: Value that defines which middleware will be used. It is possible to choose between the middlewares: EXPRESS, FASTIFY, HAPI and KOA. If empty, the middleware default is `EXPRESS`. +- **LOGGING_TRACE_HEADER** *(version 1.5.0 and above)*: Value indicating the header name that must be obtained from the traceId value in the request. Default is `X-B3-TraceId`. +## Basic Usage (Express users) -## Basic Usage +```js +// ES6 or Typescript +import express from 'express'; +import logger, { traceMiddleware } from '@zenvia/logger'; + +const app = express(); +app.use(traceMiddleware); + +logger.info('some message'); +``` +## Basic Usage (FASTIFY users) + +```js +// ES6 or Typescript +import fastify from 'fastify' +import logger, { traceMiddleware } from '@zenvia/logger'; + +fastify.register(traceMiddleware); + +logger.info('some message'); +``` +## Basic Usage (KOA users) ```js -// ES5 -const logger = require('@zenvia/logger'); +// ES6 or Typescript +import Koa from 'koa'; +import logger, { traceMiddleware } from '@zenvia/logger'; + +const app = new Koa(); +app.use(traceMiddleware); +logger.info('some message'); +``` +## Basic Usage (HAPI users) + +```js // ES6 or Typescript -import * as logger from '@zenvia/logger'; +import Koa from 'koa'; +import logger, { traceMiddleware } from '@zenvia/logger'; + +const init = async () => { + const server = Hapi.server({ + port: 3000, + host: 'localhost' + }); + + await server.register({ + plugin: traceMiddleware + }); +} logger.info('some message'); ``` @@ -51,7 +96,8 @@ Output: "@version": 1, "application": "application-name", "message": "some message", - "level": "INFO" + "level": "INFO", + "traceID": "123e4567-e32b-12d3-a432-626614174888" } ``` @@ -111,7 +157,7 @@ Output: Due to limitations of winston lib, when a text, an error and extra key/value fields are logged at once, the output message field will contain the text message, the error message and the full stack trace as shown. ```js -logger.fatal('Ops!', new Error('Something goes wrong'), { keyA: 'value A', keyB: 'value B' }); +logger.fatal('Ops!', { new Error('Something goes wrong'), { keyA: 'value A', keyB: 'value B' } }); ``` Output: @@ -128,7 +174,49 @@ Output: } ``` +### Using trace logs +From version 1.5.0 it is possible to track logs. To do traceability, the cls-rTrace package is used. To use it, just add the middleware in the framework you are using. In this way it is possible to propagate the traceId received in a request to the logs throughout your project. If no traceId is passed in the request, Zenvia Logger generates a random traceId for the request being processed. +**Request example sending traceId:** +```bash +curl 'http://localhost/your-application' \ +--header 'X-TraceId: dbcdd40e-10cd-40a7-b912-1b0a17483d67' \ +``` +Log +```javascript +logger.info('message with traceID'); +``` +Log Output +```json +{ + "@timestamp": "2018-06-05T18:20:42.345Z", + "@version": 1, + "application": "application-name", + "message": "message with traceID", + "level": "INFO", + "traceID": "dbcdd40e-10cd-40a7-b912-1b0a17483d67'" +} +``` + +**Request example without sending traceId:** +```bash +curl 'http://localhost/your-application' +``` +Log +```javascript +logger.info('message without traceID'); +``` +Log Output +```json +{ + "@timestamp": "2018-06-05T18:20:42.345Z", + "@version": 1, + "application": "application-name", + "message": "message with traceID", + "level": "INFO", + "traceID": "912c029c-c38f-49e7-9968-e575c5108178'" +} +``` ## License diff --git a/package-lock.json b/package-lock.json index 9ffda4c..306b1dc 100644 --- a/package-lock.json +++ b/package-lock.json @@ -254,7 +254,7 @@ }, "@dabh/diagnostics": { "version": "2.0.2", - "resolved": "https://registry.npmjs.org/@dabh/diagnostics/-/diagnostics-2.0.2.tgz", + "resolved": "http://nexus.zenvia.com/repository/npm-group/@dabh/diagnostics/-/diagnostics-2.0.2.tgz", "integrity": "sha512-+A1YivoVDNNVCdfozHSR8v/jyuuLTMXwjWuxPFlFlUapXoGc+Gj9mDlTDDfrwl7rXCl2tNZ0kE8sIBO6YOn96Q==", "requires": { "colorspace": "1.1.x", @@ -474,7 +474,7 @@ }, "app-root-dir": { "version": "1.0.2", - "resolved": "https://registry.npmjs.org/app-root-dir/-/app-root-dir-1.0.2.tgz", + "resolved": "http://nexus.zenvia.com/repository/npm-group/app-root-dir/-/app-root-dir-1.0.2.tgz", "integrity": "sha1-OBh+wt6nV3//Az/8sSFyaS/24Rg=" }, "append-transform": { @@ -626,7 +626,7 @@ }, "async": { "version": "3.2.0", - "resolved": "https://registry.npmjs.org/async/-/async-3.2.0.tgz", + "resolved": "http://nexus.zenvia.com/repository/npm-group/async/-/async-3.2.0.tgz", "integrity": "sha512-TR2mEZFVOj2pLStYxLht7TyfuRzaydfpxr3k9RpHIzMgw7A64dzsdqCxH1WJyQdoe8T10nDXd9wnEigmiuHIZw==" }, "asynckit": { @@ -853,9 +853,24 @@ } } }, + "cls-rtracer": { + "version": "2.6.0", + "resolved": "http://nexus.zenvia.com/repository/npm-group/cls-rtracer/-/cls-rtracer-2.6.0.tgz", + "integrity": "sha512-AkerGNOczlS5mj7giIGi0KvqwLy2sckUF7RQe5r0dV4Z/SWUclUwVEhIOJQ3rOcTOBqlBVAtmGbSWirkW1GK4w==", + "requires": { + "uuid": "8.3.1" + }, + "dependencies": { + "uuid": { + "version": "8.3.1", + "resolved": "http://nexus.zenvia.com/repository/npm-group/uuid/-/uuid-8.3.1.tgz", + "integrity": "sha512-FOmRr+FmWEIG8uhZv6C2bTgEVXsHk08kE7mPlrBbEe+c3r9pjceVPgupIfNIhc4yx55H69OXANrUaSuu9eInKg==" + } + } + }, "color": { "version": "3.0.0", - "resolved": "https://registry.npmjs.org/color/-/color-3.0.0.tgz", + "resolved": "http://nexus.zenvia.com/repository/npm-group/color/-/color-3.0.0.tgz", "integrity": "sha512-jCpd5+s0s0t7p3pHQKpnJ0TpQKKdleP71LWcA0aqiljpiuAkOSUFN/dyH8ZwF0hRmFlrIuRhufds1QyEP9EB+w==", "requires": { "color-convert": "^1.9.1", @@ -864,7 +879,7 @@ }, "color-convert": { "version": "1.9.3", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "resolved": "http://nexus.zenvia.com/repository/npm-group/color-convert/-/color-convert-1.9.3.tgz", "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", "requires": { "color-name": "1.1.3" @@ -872,7 +887,7 @@ }, "color-name": { "version": "1.1.3", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "resolved": "http://nexus.zenvia.com/repository/npm-group/color-name/-/color-name-1.1.3.tgz", "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=" }, "color-string": { @@ -886,12 +901,12 @@ }, "colors": { "version": "1.4.0", - "resolved": "https://registry.npmjs.org/colors/-/colors-1.4.0.tgz", + "resolved": "http://nexus.zenvia.com/repository/npm-group/colors/-/colors-1.4.0.tgz", "integrity": "sha512-a+UqTh4kgZg/SlGvfbzDHpgRu7AAQOmmqRHJnxhRZICKFUT91brVhNNt58CMWU9PsBbv3PDCZUHbVxuDiH2mtA==" }, "colorspace": { "version": "1.1.2", - "resolved": "https://registry.npmjs.org/colorspace/-/colorspace-1.1.2.tgz", + "resolved": "http://nexus.zenvia.com/repository/npm-group/colorspace/-/colorspace-1.1.2.tgz", "integrity": "sha512-vt+OoIP2d76xLhjwbBaucYlNSpPsrJWPlBTtwCpQKIu6/CSMutyzX93O/Do0qzpH3YoHEes8YEFXyZ797rEhzQ==", "requires": { "color": "3.0.x", @@ -950,7 +965,7 @@ }, "core-util-is": { "version": "1.0.2", - "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", + "resolved": "http://nexus.zenvia.com/repository/npm-group/core-util-is/-/core-util-is-1.0.2.tgz", "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=" }, "coveralls": { @@ -1081,7 +1096,7 @@ }, "enabled": { "version": "2.0.0", - "resolved": "https://registry.npmjs.org/enabled/-/enabled-2.0.0.tgz", + "resolved": "http://nexus.zenvia.com/repository/npm-group/enabled/-/enabled-2.0.0.tgz", "integrity": "sha512-AKrN98kuwOzMIdAizXGI86UFBoo26CL21UM763y1h/GMSJ4/OHU9k2YlsmBpyScFo/wbLzWQJBMCW4+IO3/+OQ==" }, "enquirer": { @@ -1479,12 +1494,12 @@ }, "fast-safe-stringify": { "version": "2.0.7", - "resolved": "https://registry.npmjs.org/fast-safe-stringify/-/fast-safe-stringify-2.0.7.tgz", + "resolved": "http://nexus.zenvia.com/repository/npm-group/fast-safe-stringify/-/fast-safe-stringify-2.0.7.tgz", "integrity": "sha512-Utm6CdzT+6xsDk2m8S6uL8VHxNwI6Jub+e9NYTcAms28T84pTa25GJQV9j0CY0N1rM8hK4x6grpF2BQf+2qwVA==" }, "fecha": { "version": "4.2.0", - "resolved": "https://registry.npmjs.org/fecha/-/fecha-4.2.0.tgz", + "resolved": "http://nexus.zenvia.com/repository/npm-group/fecha/-/fecha-4.2.0.tgz", "integrity": "sha512-aN3pcx/DSmtyoovUudctc8+6Hl4T+hI9GBBHLjA76jdZl7+b1sgh5g4k+u/GL3dTy1/pnYzKp69FpJ0OicE3Wg==" }, "file-entry-cache": { @@ -1613,7 +1628,7 @@ }, "fn.name": { "version": "1.1.0", - "resolved": "https://registry.npmjs.org/fn.name/-/fn.name-1.1.0.tgz", + "resolved": "http://nexus.zenvia.com/repository/npm-group/fn.name/-/fn.name-1.1.0.tgz", "integrity": "sha512-GRnmB5gPyJpAhTQdSZTSp9uaPSvl09KoYcMQtsB9rQoOmzs9dH6ffeccH+Z+cv6P68Hu5bC6JjRh4Ah/mHSNRw==" }, "foreground-child": { @@ -1867,7 +1882,7 @@ }, "inherits": { "version": "2.0.4", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "resolved": "http://nexus.zenvia.com/repository/npm-group/inherits/-/inherits-2.0.4.tgz", "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" }, "is-arguments": { @@ -1878,7 +1893,7 @@ }, "is-arrayish": { "version": "0.3.2", - "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.3.2.tgz", + "resolved": "http://nexus.zenvia.com/repository/npm-group/is-arrayish/-/is-arrayish-0.3.2.tgz", "integrity": "sha512-eVRqCvVlZbuw3GrM63ovNSNAeA1K16kaR/LRY/92w0zxQ5/1YzwblUX652i4Xs9RwAGjW9d9y6X88t8OaAJfWQ==" }, "is-binary-path": { @@ -1970,7 +1985,7 @@ }, "is-stream": { "version": "2.0.0", - "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.0.tgz", + "resolved": "http://nexus.zenvia.com/repository/npm-group/is-stream/-/is-stream-2.0.0.tgz", "integrity": "sha512-XCoy+WlUr7d1+Z8GgSuXmpuUFC9fOhRXglJMx+dwLKTkL44Cjd4W1Z5P+BQZpr+cR93aGP4S/s7Ftw6Nd/kiEw==" }, "is-string": { @@ -2002,7 +2017,7 @@ }, "isarray": { "version": "1.0.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "resolved": "http://nexus.zenvia.com/repository/npm-group/isarray/-/isarray-1.0.0.tgz", "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=" }, "isexe": { @@ -2232,7 +2247,7 @@ }, "kuler": { "version": "2.0.0", - "resolved": "https://registry.npmjs.org/kuler/-/kuler-2.0.0.tgz", + "resolved": "http://nexus.zenvia.com/repository/npm-group/kuler/-/kuler-2.0.0.tgz", "integrity": "sha512-Xq9nH7KlWZmXAtodXDDRE7vs6DU1gTU8zYDHDiWLSip45Egwq3plLHzPn27NgvzL2r1LMPC1vdqh98sQxtqj4A==" }, "lcov-parse": { @@ -2308,7 +2323,7 @@ }, "logform": { "version": "2.2.0", - "resolved": "https://registry.npmjs.org/logform/-/logform-2.2.0.tgz", + "resolved": "http://nexus.zenvia.com/repository/npm-group/logform/-/logform-2.2.0.tgz", "integrity": "sha512-N0qPlqfypFx7UHNn4B3lzS/b0uLqt2hmuoa+PpuXNYgozdJYAyauF5Ky0BWVjrxDlMWiT3qN4zPq3vVAfZy7Yg==", "requires": { "colors": "^1.2.1", @@ -2870,7 +2885,7 @@ }, "one-time": { "version": "1.0.0", - "resolved": "https://registry.npmjs.org/one-time/-/one-time-1.0.0.tgz", + "resolved": "http://nexus.zenvia.com/repository/npm-group/one-time/-/one-time-1.0.0.tgz", "integrity": "sha512-5DXOiRKwuSEcQ/l0kGCF6Q3jcADFv5tSmRaJck/OqkVFcOzutB134KRSfF0xDrL39MNnqxbHBbUUcjZIhTgb2g==", "requires": { "fn.name": "1.x.x" @@ -3044,7 +3059,7 @@ }, "process-nextick-args": { "version": "2.0.1", - "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", + "resolved": "http://nexus.zenvia.com/repository/npm-group/process-nextick-args/-/process-nextick-args-2.0.1.tgz", "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==" }, "process-on-spawn": { @@ -3146,7 +3161,7 @@ }, "readable-stream": { "version": "3.6.0", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "resolved": "http://nexus.zenvia.com/repository/npm-group/readable-stream/-/readable-stream-3.6.0.tgz", "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", "requires": { "inherits": "^2.0.3", @@ -3244,7 +3259,7 @@ }, "safe-buffer": { "version": "5.2.1", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "resolved": "http://nexus.zenvia.com/repository/npm-group/safe-buffer/-/safe-buffer-5.2.1.tgz", "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==" }, "safer-buffer": { @@ -3297,7 +3312,7 @@ }, "simple-swizzle": { "version": "0.2.2", - "resolved": "https://registry.npmjs.org/simple-swizzle/-/simple-swizzle-0.2.2.tgz", + "resolved": "http://nexus.zenvia.com/repository/npm-group/simple-swizzle/-/simple-swizzle-0.2.2.tgz", "integrity": "sha1-pNprY1/8zMoz9w0Xy5JZLeleVXo=", "requires": { "is-arrayish": "^0.3.1" @@ -3440,7 +3455,7 @@ }, "stack-trace": { "version": "0.0.10", - "resolved": "https://registry.npmjs.org/stack-trace/-/stack-trace-0.0.10.tgz", + "resolved": "http://nexus.zenvia.com/repository/npm-group/stack-trace/-/stack-trace-0.0.10.tgz", "integrity": "sha1-VHxws0fo0ytOEI6hoqFZ5f3eGcA=" }, "std-mocks": { @@ -3544,7 +3559,7 @@ }, "string_decoder": { "version": "1.3.0", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", + "resolved": "http://nexus.zenvia.com/repository/npm-group/string_decoder/-/string_decoder-1.3.0.tgz", "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", "requires": { "safe-buffer": "~5.2.0" @@ -3605,7 +3620,7 @@ }, "text-hex": { "version": "1.0.0", - "resolved": "https://registry.npmjs.org/text-hex/-/text-hex-1.0.0.tgz", + "resolved": "http://nexus.zenvia.com/repository/npm-group/text-hex/-/text-hex-1.0.0.tgz", "integrity": "sha512-uuVGNWzgJ4yhRaNSiubPY7OjISw4sw4E5Uv0wbjp+OzcbmVU/rsT8ujgcXJhn9ypzsgr5vlzpPqP+MBBKcGvbg==" }, "text-table": { @@ -3641,7 +3656,7 @@ }, "triple-beam": { "version": "1.3.0", - "resolved": "https://registry.npmjs.org/triple-beam/-/triple-beam-1.3.0.tgz", + "resolved": "http://nexus.zenvia.com/repository/npm-group/triple-beam/-/triple-beam-1.3.0.tgz", "integrity": "sha512-XrHUvV5HpdLmIj4uVMxHggLbFSZYIn7HEWsqePZcI50pco+MPqJ50wMGY794X7AOOhxOBAjbkqfAbEe/QMp2Lw==" }, "tsconfig-paths": { @@ -3712,7 +3727,7 @@ }, "util-deprecate": { "version": "1.0.2", - "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "resolved": "http://nexus.zenvia.com/repository/npm-group/util-deprecate/-/util-deprecate-1.0.2.tgz", "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=" }, "uuid": { @@ -3801,7 +3816,7 @@ }, "winston": { "version": "3.3.3", - "resolved": "https://registry.npmjs.org/winston/-/winston-3.3.3.tgz", + "resolved": "http://nexus.zenvia.com/repository/npm-group/winston/-/winston-3.3.3.tgz", "integrity": "sha512-oEXTISQnC8VlSAKf1KYSSd7J6IWuRPQqDdo8eoRNaYKLvwSb5+79Z3Yi1lrl6KDpU6/VWaxpakDAtb1oQ4n9aw==", "requires": { "@dabh/diagnostics": "^2.0.2", @@ -3817,7 +3832,7 @@ }, "winston-transport": { "version": "4.4.0", - "resolved": "https://registry.npmjs.org/winston-transport/-/winston-transport-4.4.0.tgz", + "resolved": "http://nexus.zenvia.com/repository/npm-group/winston-transport/-/winston-transport-4.4.0.tgz", "integrity": "sha512-Lc7/p3GtqtqPBYYtS6KCN3c77/2QCev51DvcJKbkFPQNoj1sinkGwLGFDxkXY9J6p9+EPnYs+D90uwbnaiURTw==", "requires": { "readable-stream": "^2.3.7", @@ -3826,7 +3841,7 @@ "dependencies": { "readable-stream": { "version": "2.3.7", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", + "resolved": "http://nexus.zenvia.com/repository/npm-group/readable-stream/-/readable-stream-2.3.7.tgz", "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", "requires": { "core-util-is": "~1.0.0", @@ -3840,12 +3855,12 @@ }, "safe-buffer": { "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "resolved": "http://nexus.zenvia.com/repository/npm-group/safe-buffer/-/safe-buffer-5.1.2.tgz", "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" }, "string_decoder": { "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "resolved": "http://nexus.zenvia.com/repository/npm-group/string_decoder/-/string_decoder-1.1.1.tgz", "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", "requires": { "safe-buffer": "~5.1.0" diff --git a/package.json b/package.json index 07adcaf..2ba7e67 100644 --- a/package.json +++ b/package.json @@ -1,9 +1,9 @@ { "name": "@zenvia/logger", - "version": "1.4.3", + "version": "1.5.0", "description": "A wrapper for Winston Logging Node.js library that formats the output on STDOUT as Logstash JSON format.", "license": "MIT", - "main": "./src/lib/logger", + "main": "./src/index", "private": false, "publishConfig": { "access": "public" @@ -33,6 +33,7 @@ ], "dependencies": { "app-root-dir": "^1.0.2", + "cls-rtracer": "^2.6.0", "winston": "^3.3.3" }, "devDependencies": { diff --git a/src/index.d.ts b/src/index.d.ts new file mode 100644 index 0000000..072695c --- /dev/null +++ b/src/index.d.ts @@ -0,0 +1,5 @@ +import logger from './lib/logger'; +import middleware from './middleware/trace'; + +export default logger; +export const traceMiddleware = middleware(); diff --git a/src/index.js b/src/index.js new file mode 100644 index 0000000..5b684fa --- /dev/null +++ b/src/index.js @@ -0,0 +1,9 @@ +Object.defineProperty(exports, '__esModule', { + value: true, +}); + +const logger = require('./lib/logger'); +const traceMiddleware = require('./middleware/trace'); + +exports.default = logger; +exports.traceMiddleware = traceMiddleware(); diff --git a/src/lib/logger.d.ts b/src/lib/logger.d.ts index c1ab897..9a72f41 100644 --- a/src/lib/logger.d.ts +++ b/src/lib/logger.d.ts @@ -1,11 +1,9 @@ -declare module '@zenvia/logger' { - import { Logger, LeveledLogMethod } from 'winston'; +import { Logger, LeveledLogMethod } from 'winston'; - interface ZenviaLogger extends Logger { - fatal: LeveledLogMethod; - isFatalEnabled(): boolean; - } - - const logger: ZenviaLogger; - export = logger; +interface ZenviaLogger extends Logger { + fatal: LeveledLogMethod; + isFatalEnabled(): boolean; } + +declare const logger: ZenviaLogger; +export default logger; diff --git a/src/lib/logger.js b/src/lib/logger.js index 44b5301..7142553 100644 --- a/src/lib/logger.js +++ b/src/lib/logger.js @@ -6,6 +6,7 @@ const winston = require('winston'); const path = require('path'); const appRootDir = require('app-root-dir').get(); +const rTrace = require('cls-rtracer'); const appPackage = require(path.join(appRootDir, 'package')); @@ -27,12 +28,20 @@ const customFormatJson = winston.format((info) => { message: info.message || '', level: ['verbose', 'silly'].includes(info.level) ? 'DEBUG' : info.level.toUpperCase(), stack_trace: stack, + traceId: rTrace.id(), }; + Object.keys(info).forEach((key) => { + if (info[key] instanceof Function) { + delete info[key]; + } + }); + return info; }); const customCombineJson = winston.format.combine( + winston.format.splat(), customFormatJson(), winston.format.json(), ); diff --git a/src/middleware/trace.d.ts b/src/middleware/trace.d.ts new file mode 100644 index 0000000..e2353c4 --- /dev/null +++ b/src/middleware/trace.d.ts @@ -0,0 +1,3 @@ +declare const traceMiddleware: () => (req: IncomingMessage, res: ServerResponse, next: (err?: any) => void) => void; + +export default traceMiddleware; \ No newline at end of file diff --git a/src/middleware/trace.js b/src/middleware/trace.js new file mode 100644 index 0000000..c1549fb --- /dev/null +++ b/src/middleware/trace.js @@ -0,0 +1,25 @@ +const rTracer = require('cls-rtracer'); + +module.exports = () => { + const frameworkMiddleware = process.env.LOGGING_FRAMEWORK_MIDDLEWARE; + + const RTRACER_OPTIONS = { + useHeader: true, + headerName: process.env.LOGGING_TRACE_HEADER || 'X-TraceId', + echoHeader: true, + }; + + const middleware = { + EXPRESS: rTracer.expressMiddleware(RTRACER_OPTIONS), + FASTIFY: rTracer.fastifyPlugin, + HAPI: rTracer.hapiPlugin, + KOA: rTracer.koaMiddleware(RTRACER_OPTIONS), + }; + + // eslint-disable-next-line no-prototype-builtins + if (frameworkMiddleware && !middleware.hasOwnProperty(frameworkMiddleware)) { + throw new Error(`Invalid framework middleware value. Please check environment variable "LOGGING_FRAMEWORK_MIDDLEWARE". Allowed values: [${Object.keys(middleware)}]`); + } + + return middleware[frameworkMiddleware || 'EXPRESS']; +}; diff --git a/test/index.spec.js b/test/index.spec.js new file mode 100644 index 0000000..d9bb8fe --- /dev/null +++ b/test/index.spec.js @@ -0,0 +1,9 @@ +const { assert } = require('chai'); +const { default: logger, traceMiddleware } = require('../src'); + +describe('Logger test', () => { + it('should load correct module', () => { + assert.isNotNull(logger); + assert.isNotNull(traceMiddleware); + }); +}); diff --git a/test/middleware/trace.spec.js b/test/middleware/trace.spec.js new file mode 100644 index 0000000..118924a --- /dev/null +++ b/test/middleware/trace.spec.js @@ -0,0 +1,117 @@ +const stdMocks = require('std-mocks'); +const rTrace = require('cls-rtracer'); +const { assert } = require('chai'); +const sinon = require('sinon'); +const traceMiddleware = require('../../src/middleware/trace'); + +const DEFAULT_HEADER_NAME = 'X-TraceId'; + +describe('Trace middleware test', () => { + let rTraceSpy; + + before(() => { + stdMocks.use({ print: true }); + rTraceSpy = { + EXPRESS: sinon.spy(rTrace, 'expressMiddleware'), + KOA: sinon.spy(rTrace, 'koaMiddleware'), + }; + }); + + beforeEach(() => { + stdMocks.flush(); + }); + + afterEach(() => { + stdMocks.restore(); + delete process.env.LOGGING_FRAMEWORK_MIDDLEWARE; + delete process.env.LOGGING_TRACE_HEADER; + }); + + describe('Return correct middleware', () => { + it('should return correct middlware EXPRESS when it is use default values', () => { + const RTRACER_OPTIONS = { + useHeader: true, + headerName: DEFAULT_HEADER_NAME, + echoHeader: true, + }; + const middleware = traceMiddleware(); + + assert.isFunction(middleware); + assert.isTrue(rTraceSpy.EXPRESS.calledWith(RTRACER_OPTIONS)); + assert.equal(rTrace.expressMiddleware(RTRACER_OPTIONS).toString(), middleware.toString()); + }); + + it('should return correct KOA middleware when environment is set to KOA', () => { + process.env.LOGGING_FRAMEWORK_MIDDLEWARE = 'KOA'; + const RTRACER_OPTIONS = { + useHeader: true, + headerName: DEFAULT_HEADER_NAME, + echoHeader: true, + }; + const middleware = traceMiddleware(); + + assert.isFunction(middleware); + assert.isTrue(rTraceSpy.KOA.calledWith(RTRACER_OPTIONS)); + assert.equal(rTrace.koaMiddleware(RTRACER_OPTIONS).toString(), middleware.toString()); + }); + + it('should return correct FASTIFY middleware when environment is set to FASTIFY', () => { + process.env.LOGGING_FRAMEWORK_MIDDLEWARE = 'FASTIFY'; + const middleware = traceMiddleware(); + + assert.isFunction(middleware); + assert.equal(rTrace.fastifyPlugin.toString(), middleware.toString()); + }); + + it('should return correct HAPI middleware when environment is set to HAPI', () => { + process.env.LOGGING_FRAMEWORK_MIDDLEWARE = 'HAPI'; + const middleware = traceMiddleware(); + + assert.isNotNull(middleware); + assert.equal(rTrace.hapiPlugin, middleware); + }); + + it('should throw error "Invalid framework middleware value" when is set invalid value in LOGGING_FRAMEWORK_MIDDLEWARE environment variable', () => { + process.env.LOGGING_FRAMEWORK_MIDDLEWARE = 'INVALID_VALUE'; + try { + traceMiddleware(); + } catch (error) { + assert.equal( + error.message, + 'Invalid framework middleware value. Please check environment variable "LOGGING_FRAMEWORK_MIDDLEWARE". Allowed values: [EXPRESS,FASTIFY,HAPI,KOA]', + ); + } + }); + }); + + describe('Use correct rTracer options', () => { + it('should use default header name when is not set LOGGING_TRACE_HEADER', () => { + process.env.LOGGING_FRAMEWORK_MIDDLEWARE = 'EXPRESS'; + const RTRACER_OPTIONS = { + useHeader: true, + headerName: DEFAULT_HEADER_NAME, + echoHeader: true, + }; + const middleware = traceMiddleware(); + + assert.isFunction(middleware); + assert.isTrue(rTraceSpy.EXPRESS.calledWith(RTRACER_OPTIONS)); + }); + + it('should use correct header name when is set LOGGING_TRACE_HEADER', () => { + const headerName = 'newHeaderName'; + process.env.LOGGING_FRAMEWORK_MIDDLEWARE = 'EXPRESS'; + process.env.LOGGING_TRACE_HEADER = headerName; + const RTRACER_OPTIONS = { + useHeader: true, + headerName, + echoHeader: true, + }; + const middleware = traceMiddleware(); + + assert.isFunction(middleware); + assert.isTrue(rTraceSpy.EXPRESS.calledWith(RTRACER_OPTIONS)); + assert.equal(rTrace.expressMiddleware(RTRACER_OPTIONS).toString(), middleware.toString()); + }); + }); +}); From b9297de0a64685fb08d1e561c0a7766d5ff3efe4 Mon Sep 17 00:00:00 2001 From: Guilherme Severo Date: Tue, 23 Mar 2021 11:54:32 -0300 Subject: [PATCH 2/2] Default traceId header documentation changed --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 34cea36..b5373df 100644 --- a/README.md +++ b/README.md @@ -29,7 +29,7 @@ The following environment variables can be used for increase the log information - **LOGGING_LEVEL**: set the level of messages that the logger should log. Default to `DEBUG`. - **LOGGING_FORMATTER_DISABLED** *(version 1.1.0 and above)*: When `true`, the output logging will not be formatted to JSON. Useful during development time. Default to `false`. - **LOGGING_FRAMEWORK_MIDDLEWARE** *(version 1.5.0 and above)*: Value that defines which middleware will be used. It is possible to choose between the middlewares: EXPRESS, FASTIFY, HAPI and KOA. If empty, the middleware default is `EXPRESS`. -- **LOGGING_TRACE_HEADER** *(version 1.5.0 and above)*: Value indicating the header name that must be obtained from the traceId value in the request. Default is `X-B3-TraceId`. +- **LOGGING_TRACE_HEADER** *(version 1.5.0 and above)*: Value indicating the header name that must be obtained from the traceId value in the request. Default is `X-TraceId`. ## Basic Usage (Express users)