diff --git a/.kuzzlerc.sample.jsonc b/.kuzzlerc.sample.jsonc index a979f9a243..50eb50e652 100644 --- a/.kuzzlerc.sample.jsonc +++ b/.kuzzlerc.sample.jsonc @@ -142,7 +142,6 @@ "maxConcurrentPipes": 50, "pipesBufferSize": 50000, "include": [ - "kuzzle-plugin-logger", "kuzzle-plugin-auth-passport-local" ] }, diff --git a/lib/config/default.config.ts b/lib/config/default.config.ts index fab4b90e7c..423ecf7a3c 100644 --- a/lib/config/default.config.ts +++ b/lib/config/default.config.ts @@ -75,7 +75,7 @@ const defaultConfig: KuzzleConfiguration = { initTimeout: 10000, maxConcurrentPipes: 50, pipesBufferSize: 50000, - include: ["kuzzle-plugin-logger", "kuzzle-plugin-auth-passport-local"], + include: ["kuzzle-plugin-auth-passport-local"], }, "kuzzle-plugin-logger": { services: { diff --git a/lib/core/plugin/pluginsManager.js b/lib/core/plugin/pluginsManager.js index a10c976074..483a2a81fb 100644 --- a/lib/core/plugin/pluginsManager.js +++ b/lib/core/plugin/pluginsManager.js @@ -43,10 +43,7 @@ const strategyError = kerror.wrap("plugin", "strategy"); const controllerError = kerror.wrap("plugin", "controller"); // Without those plugins, Kuzzle won't start at all. -const CORE_PLUGINS = [ - "kuzzle-plugin-logger", - "kuzzle-plugin-auth-passport-local", -]; +const CORE_PLUGINS = ["kuzzle-plugin-auth-passport-local"]; /** * @class PluginsManager diff --git a/lib/kuzzle/Logger.ts b/lib/kuzzle/Logger.ts new file mode 100644 index 0000000000..3538a4bc62 --- /dev/null +++ b/lib/kuzzle/Logger.ts @@ -0,0 +1,178 @@ +/* + * Kuzzle, a backend software, self-hostable and ready to use + * to power modern apps + * + * Copyright 2015-2022 Kuzzle + * mailto: support AT kuzzle.io + * website: http://kuzzle.io + * + * 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 + * + * https://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. + */ + +import { ecsFormat } from "@elastic/ecs-pino-format"; +import { pino, Logger as PinoLogger } from "pino"; + +/** + * The Logger class provides logging functionality for Kuzzle. + */ +export class Logger { + private pino: PinoLogger<"silly" | "verbose">; + private failsafeModeString: string; + + constructor() { + const config = global.kuzzle.config.server.logs; + const deprecatedConfig = + global.kuzzle.config.plugins["kuzzle-plugin-logger"]; + + const transport = pino.transport({ + targets: [ + { + target: "pino-elasticsearch", + options: { + index: "&platform.logs", + node: "http://localhost:9200", + esVersion: 7, + flushBytes: 1000, + }, + }, + ], + }); + + const pinoConfigEcs = ecsFormat(); + + this.pino = pino<"silly" | "verbose">( + { + ...pinoConfigEcs, + customLevels: { + silly: 5, + verbose: 25, + }, + }, + transport, + ); + + this.pino.setBindings({ + _kuzzle_info: { + author: -1, + createdAt: new Date().toISOString(), + updatedAt: new Date().toISOString(), + updater: -1, + }, + }); + + this.failsafeModeString = global.kuzzle.config.plugins.common.failsafeMode + ? "[FAILSAFE MODE] " + : ""; + + if (deprecatedConfig) { + this.warn( + "[DEPRECATED] The plugins.kuzzle-plugin-logger configuration is deprecated, use server.logs instead.", + ); + } + } + + /** + * Logs a message with the "trace" level. + * + * @param message - The message to log. + */ + trace(message: string) { + this.pino.trace(this.formatMessage(message)); + } + + /** + * Logs a message with the "debug" level. + * + * @param message - The message to log. + */ + debug(message: string) { + this.pino.debug(this.formatMessage(message)); + } + + /** + * Logs a message with the "info" level. + * + * @param message - The message to log. + */ + info(message: string) { + this.pino.info(this.formatMessage(message)); + } + + /** + * Logs a message with the "warn" level. + * + * @param message - The message to log. + */ + warn(message: string) { + this.pino.warn(this.formatMessage(message)); + } + + /** + * Logs a message with the "error" level. + * + * @param message - The message to log. + */ + error(message: string) { + this.pino.error(this.formatMessage(message)); + } + + /** + * Logs a message with the "fatal" level. + * + * @param message - The message to log. + */ + fatal(message: string) { + this.pino.fatal(this.formatMessage(message)); + } + + /** + * Logs a message with the "silly" level. + * + * @deprecated Use Logger.trace instead. + * @param message - The message to log. + */ + silly(message: string) { + this.pino.warn( + "[DEPRECATED] Logger.silly is deprecated, use Logger.trace instead.", + ); + this.pino.silly(this.formatMessage(message)); + } + + /** + * Logs a message with the "verbose" level. + * + * @deprecated Use Logger.debug instead. + * @param message - The message to log. + */ + verbose(message: string) { + this.pino.warn( + "[DEPRECATED] Logger.verbose is deprecated, use Logger.debug instead.", + ); + this.pino.verbose(this.formatMessage(message)); + } + + private formatMessage(message: string): string { + const nodeIdString = global.kuzzle.id ? `[${global.kuzzle.id}] ` : ""; + let requestIdString = ""; + + if ( + global.kuzzle.asyncStore?.exists() && + global.kuzzle.asyncStore?.has("REQUEST") + ) { + const request = global.kuzzle.asyncStore.get("REQUEST"); + + requestIdString = `[${request.id}] `; + } + return `${nodeIdString}${this.failsafeModeString}${requestIdString}${message}`; + } +} diff --git a/lib/kuzzle/kuzzle.ts b/lib/kuzzle/kuzzle.ts index 1285a229ca..37d6807d8b 100644 --- a/lib/kuzzle/kuzzle.ts +++ b/lib/kuzzle/kuzzle.ts @@ -38,7 +38,7 @@ import Router from "../core/network/router"; import Statistics from "../core/statistics"; import { TokenManager } from "../core/auth/tokenManager"; import Validation from "../core/validation"; -import Logger from "./log"; +import { Logger } from "./Logger"; import vault from "./vault"; import DumpGenerator from "./dumpGenerator"; import AsyncStore from "../util/asyncStore"; diff --git a/lib/kuzzle/log.js b/lib/kuzzle/log.js deleted file mode 100644 index 87e0c21d79..0000000000 --- a/lib/kuzzle/log.js +++ /dev/null @@ -1,74 +0,0 @@ -/* - * Kuzzle, a backend software, self-hostable and ready to use - * to power modern apps - * - * Copyright 2015-2022 Kuzzle - * mailto: support AT kuzzle.io - * website: http://kuzzle.io - * - * 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 - * - * https://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. - */ - -"use strict"; - -class Logger { - constructor() { - this.logMethods = ["info", "warn", "error", "silly", "debug", "verbose"]; - - this.failsafeModeString = global.kuzzle.config.plugins.common.failsafeMode - ? "[FAILSAFE MODE] " - : ""; - - this._useConsole(); - - global.kuzzle.once("core:kuzzleStart", this._useLogger.bind(this)); - } - - _useConsole() { - // until kuzzle has started, use the console to print logs - for (const method of this.logMethods) { - this[method] = (message) => { - /* eslint-disable-next-line no-console */ - const writer = console[method] || console.log; - - writer(`${this.failsafeModeString}${message}`); - }; - } - } - - _useLogger() { - // when kuzzle has started, use the event to dispatch logs - for (const method of this.logMethods) { - this[method] = (message) => { - if ( - global.kuzzle.asyncStore.exists() && - global.kuzzle.asyncStore.has("REQUEST") - ) { - const request = global.kuzzle.asyncStore.get("REQUEST"); - - global.kuzzle.emit( - `log:${method}`, - `[${global.kuzzle.id}] ${this.failsafeModeString}[${request.id}] ${message}`, - ); - } else { - global.kuzzle.emit( - `log:${method}`, - `[${global.kuzzle.id}] ${this.failsafeModeString}${message}`, - ); - } - }; - } - } -} - -module.exports = Logger; diff --git a/lib/types/config/PluginsConfiguration.ts b/lib/types/config/PluginsConfiguration.ts index d28f08869d..bcbd21e07c 100644 --- a/lib/types/config/PluginsConfiguration.ts +++ b/lib/types/config/PluginsConfiguration.ts @@ -31,7 +31,7 @@ export type PluginsConfiguration = { * Edit this list to deactivate one or more of those plugins. * NOTE: this list does not control plugins installed manually. * - * @default ["kuzzle-plugin-logger","kuzzle-plugin-auth-passport-local"] + * @default ["kuzzle-plugin-auth-passport-local"] */ include: string[]; @@ -76,23 +76,16 @@ export type PluginsConfiguration = { }; /** - * Default logger plugin configuration. - * - * This plugin use Winston to transport the logs. - * - * @see https://github.com/kuzzleio/kuzzle-plugin-logger + * Logger plugin configuration. + * @deprecated use server.logs */ "kuzzle-plugin-logger": { /** - * Winston transport services declaration + * Services declaration */ services: { /** * Print logs to STDOUT - * - * @default - * - * @see https://github.com/winstonjs/winston/blob/master/docs/transports.md#console-transport */ stdout: { /** diff --git a/lib/types/config/ServerConfiguration.ts b/lib/types/config/ServerConfiguration.ts index 9bc92f1dea..eef2e0109e 100644 --- a/lib/types/config/ServerConfiguration.ts +++ b/lib/types/config/ServerConfiguration.ts @@ -19,16 +19,15 @@ export type ServerConfiguration = { port: number; /** - * Configuration section for Kuzzle access logs. + * Configuration section for Kuzzle logs. */ logs: { /** - * An array of Winston transports configurations to output access - * logs. + * An array of Pino transports configurations to output logs. * * Possible transport types are: console, file, elasticsearch and syslog. * - * Please refer to https://github.com/winstonjs/winston/blob/master/docs/transports.md + * Please refer to https://getpino.io/#/docs/transports?id=known-transports * for more information on transports configuration. * * @default @@ -55,6 +54,7 @@ export type ServerConfiguration = { * be consumed by logstash agent. * * @default "combined" + * @deprecated use the "pino-clf" to get combined logs or "pino-socket" to send logs to logstash. */ accessLogFormat: "combined" | "logstash"; diff --git a/test/core/backend/Backend.test.js b/test/core/backend/Backend.test.js index c9ff5326f9..51e455f7a1 100644 --- a/test/core/backend/Backend.test.js +++ b/test/core/backend/Backend.test.js @@ -110,10 +110,7 @@ describe("Backend", () => { should(options.secretsFile).be.eql(application._secretsFile); should(options.vaultKey).be.eql(application._vaultKey); - should(options.plugins).have.keys( - "kuzzle-plugin-logger", - "kuzzle-plugin-auth-passport-local", - ); + should(options.plugins).have.keys("kuzzle-plugin-auth-passport-local"); should(options.installations).be.eql( application._installationsWaitingList, ); @@ -129,7 +126,7 @@ describe("Backend", () => { ); application.config.content.plugins.common.include = [ - "kuzzle-plugin-logger", + "kuzzle-plugin-auth-passport-local", ]; await application.start(); @@ -138,8 +135,7 @@ describe("Backend", () => { const [, options] = global.kuzzle.start.getCall(0).args; - should(options.plugins).have.keys("kuzzle-plugin-logger"); - should(options.plugins).not.have.keys( + should(options.plugins).have.only.keys( "kuzzle-plugin-auth-passport-local", ); }); diff --git a/test/core/plugin/pluginsManager.test.js b/test/core/plugin/pluginsManager.test.js index 7477ed798c..4b085a6754 100644 --- a/test/core/plugin/pluginsManager.test.js +++ b/test/core/plugin/pluginsManager.test.js @@ -112,13 +112,9 @@ describe("Plugin", () => { }); it("should only load core plugins in failsafe mode", async () => { - const loggerPlugin = createPlugin("kuzzle-plugin-logger"); const localPlugin = createPlugin("kuzzle-plugin-auth-passport-local"); pluginsManager.loadPlugins.returns( - new Map([ - [loggerPlugin.name, loggerPlugin], - [localPlugin.name, localPlugin], - ]), + new Map([[localPlugin.name, localPlugin]]), ); pluginsManager._plugins.set(plugin.name, plugin); pluginsManager.config.common.failsafeMode = true; @@ -126,7 +122,6 @@ describe("Plugin", () => { await pluginsManager.init(); should(pluginsManager.loadedPlugins).be.eql([ - "kuzzle-plugin-logger", "kuzzle-plugin-auth-passport-local", ]); });