From c30e28cd24dac31f962f44d40c85fd52c5bc5a92 Mon Sep 17 00:00:00 2001 From: Bud Byrd Date: Wed, 27 Dec 2023 12:59:50 -0600 Subject: [PATCH] Add functionality to customize log layout and introduce JSON logger --- package.json | 1 + src/lib/create-config.ts | 4 +++- src/lib/logger.ts | 11 +++++++++-- src/lib/types/option.ts | 2 ++ .../using-unleash/deploy/configuring-unleash.md | 1 + yarn.lock | 15 ++++++++++++++- 6 files changed, 30 insertions(+), 4 deletions(-) diff --git a/package.json b/package.json index 353ef0616ac..0c8ba5ec051 100644 --- a/package.json +++ b/package.json @@ -124,6 +124,7 @@ "lodash.groupby": "^4.6.0", "lodash.sortby": "^4.7.0", "log4js": "^6.0.0", + "log4js-json-layout": "^2.2.3", "make-fetch-happen": "^11.0.0", "memoizee": "^0.4.15", "mime": "^3.0.0", diff --git a/src/lib/create-config.ts b/src/lib/create-config.ts index 4509bf99a98..1cf3e7b6700 100644 --- a/src/lib/create-config.ts +++ b/src/lib/create-config.ts @@ -454,7 +454,9 @@ export function createConfig(options: IUnleashOptions): IUnleashConfig { const logLevel = options.logLevel || LogLevel[process.env.LOG_LEVEL] || LogLevel.error; - const getLogger = options.getLogger || getDefaultLogProvider(logLevel); + const logLayout = options.logLayout || process.env.LOG_LAYOUT || 'basic'; + const getLogger = + options.getLogger || getDefaultLogProvider(logLevel, logLayout); validateLogProvider(getLogger); const server: IServerOption = mergeAll([ diff --git a/src/lib/logger.ts b/src/lib/logger.ts index 81edb566a80..d4b5c869fff 100644 --- a/src/lib/logger.ts +++ b/src/lib/logger.ts @@ -1,4 +1,5 @@ -import { configure, getLogger } from 'log4js'; +import { configure, getLogger, addLayout, Layout } from 'log4js'; +import jsonLayout from 'log4js-json-layout'; export type LogProvider = (category?: string) => Logger; @@ -20,10 +21,16 @@ export interface Logger { export function getDefaultLogProvider( logLevel: LogLevel = LogLevel.error, + logLayout: string | Layout = 'basic', ): LogProvider { + addLayout('json', jsonLayout); + + const layout = + typeof logLayout === 'string' ? { type: logLayout } : logLayout; + configure({ appenders: { - console: { type: 'console' }, + console: { type: 'console', layout: layout }, }, categories: { default: { appenders: ['console'], level: logLevel }, diff --git a/src/lib/types/option.ts b/src/lib/types/option.ts index 9d353b2f746..46e9297078e 100644 --- a/src/lib/types/option.ts +++ b/src/lib/types/option.ts @@ -5,6 +5,7 @@ import { ILegacyApiTokenCreate } from './models/api-token'; import { IFlagResolver, IExperimentalOptions, IFlags } from './experimental'; import SMTPTransport from 'nodemailer/lib/smtp-transport'; import { IUnleashServices } from './services'; +import { Layout } from 'log4js'; export interface ISSLOption { rejectUnauthorized: boolean; @@ -109,6 +110,7 @@ export interface IUnleashOptions { session?: Partial; getLogger?: LogProvider; logLevel?: LogLevel; + logLayout?: string | Layout; server?: Partial; versionCheck?: Partial; telemetry?: boolean; diff --git a/website/docs/using-unleash/deploy/configuring-unleash.md b/website/docs/using-unleash/deploy/configuring-unleash.md index 290e670f927..502549b7472 100644 --- a/website/docs/using-unleash/deploy/configuring-unleash.md +++ b/website/docs/using-unleash/deploy/configuring-unleash.md @@ -98,6 +98,7 @@ unleash.start(unleashOptions); - ~~eventHook~~ (`function(event, data)`) - (_deprecated in Unleash 4.3_ in favor of the [Webhook integration](/reference/integrations/webhook.md). **Removed in Unleash 5**) If provided, this function will be invoked whenever a feature is mutated. The possible values for `event` are `'feature-created'`, `'feature-archived'` and `'feature-revived'`. The `data` argument contains information about the mutation. Its fields are `type` (string) - the event type (same as `event`); `createdBy` (string) - the user who performed the mutation; `data` - the contents of the change. The contents in `data` differs based on the event type; For `'feature-archived'` and `'feature-revived'`, the only field will be `name` - the name of the feature. For `'feature-created'` the data follows a schema defined in the code [here](https://github.com/Unleash/unleash/blob/7b7f0b84e8cddd5880dcf29c231672113224b9a7/src/lib/schema/feature-schema.ts#L77). See an [api here](/reference/api/legacy/unleash/admin/events). - **getLogger** (function) - Used to register a [custom log provider](#how-do-i-configure-the-log-output). - **logLevel** (`debug` | `info` | `warn` | `error` | `fatal`) - The lowest level to log at, also configurable using environment variable `LOG_LEVEL`. +- **logLayout** - A [log layout](https://log4js-node.github.io/log4js-node/layouts.html) to apply to log4js. May be the name of a layout or a complete layout object if further configuration is needed. The `LOG_LAYOUT` environment may also be used if only the layout name is required. Besides the bundled layouts provided by log4js, the [`json`](https://github.com/id0Sch/log4js-json-layout) layout is supported for structured logs. - **enableRequestLogger** (boolean) - use this to enable logging for requested urls and response codes (default: false). - **preHook** (function) - this is a hook if you need to provide any middlewares to express before `unleash` adds any. Express app instance is injected as first argument. - **preRouterHook** (function) - use this to register custom express middlewares before the `unleash` specific routers are added. diff --git a/yarn.lock b/yarn.lock index edf546b2bfa..9d871eacf0e 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2325,6 +2325,11 @@ colors@1.0.x: resolved "https://registry.yarnpkg.com/colors/-/colors-1.0.3.tgz#0433f44d809680fdeb60ed260f1b0c262e82a40b" integrity sha512-pFGrxThWcWQ2MsAz6RtgeWe4NK2kUE1WfsrvvlctdII745EW9I0yflqhe7++M5LEc7bV2c/9/5zc8sFcpL0Drw== +colors@^1.1.2: + version "1.4.0" + resolved "https://registry.yarnpkg.com/colors/-/colors-1.4.0.tgz#c50491479d4c1bdaed2c9ced32cf7c7dc2360f78" + integrity sha512-a+UqTh4kgZg/SlGvfbzDHpgRu7AAQOmmqRHJnxhRZICKFUT91brVhNNt58CMWU9PsBbv3PDCZUHbVxuDiH2mtA== + combined-stream@^1.0.6, combined-stream@^1.0.8, combined-stream@~1.0.6: version "1.0.8" resolved "https://registry.yarnpkg.com/combined-stream/-/combined-stream-1.0.8.tgz#c3d45a8b34fd730631a110a8a2520682b31d5a7f" @@ -4669,7 +4674,7 @@ lodash.sortby@^4.7.0: resolved "https://registry.yarnpkg.com/lodash.sortby/-/lodash.sortby-4.7.0.tgz#edd14c824e2cc9c1e0b0a1b42bb5210516a42438" integrity sha512-HDWXG8isMntAyRF5vZ7xKuEvOhT4AhlRt/3czTSjvGUxjYCBVRQY48ViDHyfYz9VIoBkW4TMGQNapx+l3RUwdA== -lodash@^4.17.21: +lodash@^4.17.21, lodash@^4.17.4: version "4.17.21" resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.21.tgz#679591c564c3bffaae8454cf0b3df370c3d6911c" integrity sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg== @@ -4689,6 +4694,14 @@ log-update@^4.0.0: slice-ansi "^4.0.0" wrap-ansi "^6.2.0" +log4js-json-layout@^2.2.3: + version "2.2.3" + resolved "https://registry.yarnpkg.com/log4js-json-layout/-/log4js-json-layout-2.2.3.tgz#a9e95aff1f79e3e4bdd762a8a45fc0b5c81276cc" + integrity sha512-sKebdMKxF7ehqT5x760xGAI8rujDPu5dLf0p/s5e48GQYvRCkI1ycFxb6b7R8y7IZoBaXg/piL6LsMaE6Rg4gQ== + dependencies: + colors "^1.1.2" + lodash "^4.17.4" + log4js@^6.0.0: version "6.9.1" resolved "https://registry.yarnpkg.com/log4js/-/log4js-6.9.1.tgz#aba5a3ff4e7872ae34f8b4c533706753709e38b6"