From 692e582cdaa65bcdabf976971c60bf37f6f6fa2a Mon Sep 17 00:00:00 2001 From: Nev Wylie <54870357+MSNev@users.noreply.github.com> Date: Wed, 27 Jan 2021 15:45:44 -0800 Subject: [PATCH 1/5] feat(diag-logger): introduce a new global level api.diag for internal diagnostic logging (Part 1) #1877 --- .gitignore | 3 + benchmark/tracer.js | 6 +- examples/collector-exporter-node/metrics.js | 7 +- examples/collector-exporter-node/tracing.js | 5 +- examples/metrics/metrics/observer.js | 4 +- examples/tracer-web/examples/metrics/index.js | 4 +- packages/opentelemetry-api/src/api/diag.ts | 156 ++++ .../opentelemetry-api/src/api/global-utils.ts | 6 + .../opentelemetry-api/src/common/Logger.ts | 5 +- .../src/diag/consoleLogger.ts | 111 +++ .../opentelemetry-api/src/diag/logLevel.ts | 143 +++ packages/opentelemetry-api/src/diag/logger.ts | 158 ++++ packages/opentelemetry-api/src/index.ts | 14 + .../opentelemetry-api/src/trace/NoopLogger.ts | 5 +- .../test/diag/consoleLogger.test.ts | 330 +++++++ .../test/diag/logLevel.test.ts | 650 +++++++++++++ .../test/diag/logger.test.ts | 876 ++++++++++++++++++ .../src/common/ConsoleLogger.ts | 4 + .../src/common/logging-error-handler.ts | 14 +- .../opentelemetry-core/src/common/types.ts | 11 +- 20 files changed, 2491 insertions(+), 21 deletions(-) create mode 100644 packages/opentelemetry-api/src/api/diag.ts create mode 100644 packages/opentelemetry-api/src/diag/consoleLogger.ts create mode 100644 packages/opentelemetry-api/src/diag/logLevel.ts create mode 100644 packages/opentelemetry-api/src/diag/logger.ts create mode 100644 packages/opentelemetry-api/test/diag/consoleLogger.test.ts create mode 100644 packages/opentelemetry-api/test/diag/logLevel.test.ts create mode 100644 packages/opentelemetry-api/test/diag/logger.test.ts diff --git a/.gitignore b/.gitignore index 9dcdc86554e..1f35392751d 100644 --- a/.gitignore +++ b/.gitignore @@ -78,6 +78,9 @@ package.json.lerna_backup # VsCode configs .vscode/ +#Visual Studio +.vs/ + #IDEA .idea *.iml diff --git a/benchmark/tracer.js b/benchmark/tracer.js index 274cd6de99f..a792d19260c 100644 --- a/benchmark/tracer.js +++ b/benchmark/tracer.js @@ -4,7 +4,7 @@ const benchmark = require('./benchmark'); const opentelemetry = require('../packages/opentelemetry-api'); const { BasicTracerProvider, BatchSpanProcessor, InMemorySpanExporter, SimpleSpanProcessor } = require('../packages/opentelemetry-tracing'); -const logger = new opentelemetry.NoopLogger(); +const diagLogger = opentelemetry.noopDiagLogger(); const setups = [ { @@ -13,7 +13,7 @@ const setups = [ }, { name: 'BasicTracerProvider', - provider: new BasicTracerProvider({ logger }) + provider: new BasicTracerProvider({ logger: diagLogger }) }, { name: 'BasicTracerProvider with SimpleSpanProcessor', @@ -63,7 +63,7 @@ for (const setup of setups) { suite.run({ async: false }); } function getProvider(processor) { - const provider = new BasicTracerProvider({ logger }); + const provider = new BasicTracerProvider({ logger: diagLogger }); provider.addSpanProcessor(processor); return provider; } diff --git a/examples/collector-exporter-node/metrics.js b/examples/collector-exporter-node/metrics.js index 5f59a6e191a..f7102c3bf1c 100644 --- a/examples/collector-exporter-node/metrics.js +++ b/examples/collector-exporter-node/metrics.js @@ -1,15 +1,18 @@ 'use strict'; -const { ConsoleLogger, LogLevel } = require('@opentelemetry/core'); +const { DiagConsoleLogger, DiagLogLevel, diag } = require('@opentelemetry/api'); const { CollectorMetricExporter } = require('@opentelemetry/exporter-collector'); // const { CollectorMetricExporter } = require('@opentelemetry/exporter-collector-grpc'); // const { CollectorMetricExporter } = require('@opentelemetry/exporter-collector-proto'); const { MeterProvider } = require('@opentelemetry/metrics'); +diag.setLogger(new DiagConsoleLogger()); +diag.setLogLevel(DiagLogLevel.DEBUG); + const metricExporter = new CollectorMetricExporter({ serviceName: 'basic-metric-service', // url: 'http://localhost:55681/v1/metrics', - logger: new ConsoleLogger(LogLevel.DEBUG), + logger: diag, }); const meter = new MeterProvider({ diff --git a/examples/collector-exporter-node/tracing.js b/examples/collector-exporter-node/tracing.js index af9b617b046..64ba49f9cb9 100644 --- a/examples/collector-exporter-node/tracing.js +++ b/examples/collector-exporter-node/tracing.js @@ -1,15 +1,16 @@ 'use strict'; const opentelemetry = require('@opentelemetry/api'); -// const { ConsoleLogger, LogLevel} = require('@opentelemetry/core'); const { BasicTracerProvider, ConsoleSpanExporter, SimpleSpanProcessor } = require('@opentelemetry/tracing'); const { CollectorTraceExporter } = require('@opentelemetry/exporter-collector'); // const { CollectorTraceExporter } = require('@opentelemetry/exporter-collector-grpc'); // const { CollectorTraceExporter } = require('@opentelemetry/exporter-collector-proto'); +// opentelemetry.diag.setLogger(new opentelemetry.DiagConsoleLogger()); +// opentelemetry.diag.setLogLevel(opentelemetry.DiagLogLevel.DEBUG); + const exporter = new CollectorTraceExporter({ serviceName: 'basic-service', - // logger: new ConsoleLogger(LogLevel.DEBUG), // headers: { // foo: 'bar' // }, diff --git a/examples/metrics/metrics/observer.js b/examples/metrics/metrics/observer.js index aaece51489e..010bea50da1 100644 --- a/examples/metrics/metrics/observer.js +++ b/examples/metrics/metrics/observer.js @@ -1,7 +1,7 @@ 'use strict'; const { MeterProvider } = require('@opentelemetry/metrics'); -const { ConsoleLogger, LogLevel } = require('@opentelemetry/core'); +const { DiagConsoleLogger, DiagLogLevel, diagLogLevelFilter } = require('@opentelemetry/api'); const { PrometheusExporter } = require('@opentelemetry/exporter-prometheus'); const exporter = new PrometheusExporter( @@ -61,7 +61,7 @@ meter.createBatchObserver((observerBatchResult) => { }); }, { maxTimeoutUpdateMS: 500, - logger: new ConsoleLogger(LogLevel.DEBUG) + logger: diagLogLevelFilter(DiagLogLevel.DEBUG, new DiagConsoleLogger()) }, ); diff --git a/examples/tracer-web/examples/metrics/index.js b/examples/tracer-web/examples/metrics/index.js index 6aefa8cdde3..7090c78dc3e 100644 --- a/examples/tracer-web/examples/metrics/index.js +++ b/examples/tracer-web/examples/metrics/index.js @@ -1,12 +1,12 @@ 'use strict'; -const { ConsoleLogger, LogLevel } = require('@opentelemetry/core'); +const { DiagConsoleLogger, DiagLogLevel, diagLogLevelFilter } = require('@opentelemetry/api'); const { CollectorMetricExporter } = require('@opentelemetry/exporter-collector'); const { MeterProvider } = require('@opentelemetry/metrics'); const metricExporter = new CollectorMetricExporter({ serviceName: 'basic-metric-service', - logger: new ConsoleLogger(LogLevel.DEBUG), + logger: diagLogLevelFilter(DiagLogLevel.DEBUG, new DiagConsoleLogger()), }); let interval; diff --git a/packages/opentelemetry-api/src/api/diag.ts b/packages/opentelemetry-api/src/api/diag.ts new file mode 100644 index 00000000000..1b4ebc5470b --- /dev/null +++ b/packages/opentelemetry-api/src/api/diag.ts @@ -0,0 +1,156 @@ +/* + * Copyright The OpenTelemetry Authors + * + * 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 { DiagLogger, DiagLogFunction, noopDiagLogger } from '../diag/logger'; +import { DiagLogLevel, diagLogLevelFilter } from '../diag/logLevel'; +import { + API_BACKWARDS_COMPATIBILITY_VERSION, + GLOBAL_DIAG_LOGGER_API_KEY, + makeGetter, + _global, +} from './global-utils'; + +/** Internal simple Noop Diag API that returns a noop logger and does not allow any changes */ +function noopDiagApi(): DiagAPI { + const noopApi = noopDiagLogger() as DiagAPI; + + noopApi.getLogger = () => noopApi; + noopApi.setLogger = noopApi.getLogger; + noopApi.setLogLevel = () => {}; + + return noopApi; +} + +/** + * Singleton object which represents the entry point to the OpenTelemetry internal + * diagnostic API + */ +export class DiagAPI implements DiagLogger { + /** Get the singleton instance of the DiagAPI API */ + public static inst(): DiagAPI { + let theInst = null; + if (_global[GLOBAL_DIAG_LOGGER_API_KEY]) { + // Looks like a previous instance was set, so try and fetch it + theInst = _global[GLOBAL_DIAG_LOGGER_API_KEY]?.( + API_BACKWARDS_COMPATIBILITY_VERSION + ) as DiagAPI; + } + + if (!theInst) { + theInst = new DiagAPI(); + _global[GLOBAL_DIAG_LOGGER_API_KEY] = makeGetter( + API_BACKWARDS_COMPATIBILITY_VERSION, + theInst, + noopDiagApi() + ); + } + + return theInst; + } + + /** Private internal constructor + * @private */ + private constructor() { + let _logLevel: DiagLogLevel = DiagLogLevel.INFO; + let _filteredLogger: DiagLogger | null; + let _logger: DiagLogger = noopDiagLogger(); + + function _logProxy(funcName: keyof DiagLogger): DiagLogFunction { + return function () { + const orgArguments = arguments as unknown; + const theLogger = _filteredLogger || _logger; + const theFunc = theLogger[funcName]; + if (theFunc && typeof theFunc === 'function') { + return theFunc.apply( + theLogger, + orgArguments as Parameters + ); + } + }; + } + + // Using self local variable for minification purposes as 'this' cannot be minified + const self = this; + + // DiagAPI specific functions + + self.getLogger = (): DiagLogger => { + // Return itself if no existing logger is defined (defaults effectively to a Noop) + return _logger; + }; + + self.setLogger = (logger: DiagLogger): DiagLogger => { + const prevLogger = _logger; + if (prevLogger !== logger && logger !== self) { + // Simple special case to avoid any possible infinite recursion on the logging functions + _logger = logger || noopDiagLogger(); + _filteredLogger = diagLogLevelFilter(_logLevel, _logger); + } + + return prevLogger; + }; + + self.setLogLevel = (maxLogLevel: DiagLogLevel) => { + if (maxLogLevel !== _logLevel) { + _logLevel = maxLogLevel; + if (_logger) { + _filteredLogger = diagLogLevelFilter(maxLogLevel, _logger); + } + } + }; + + // DiagLogger implementation + const theFuncs: Array = [ + 'trace', + 'debug', + 'info', + 'warn', + 'error', + 'critical', + 'terminal', + 'forcedInfo', + ]; + for (let lp = 0; lp < theFuncs.length; lp++) { + const name = theFuncs[lp]; + self[name] = _logProxy(name); + } + } + + /** Return the currently configured logger instance, if no logger has been configured + * it will return itself so any log level filtering will still be applied in this case. + */ + public getLogger!: () => DiagLogger; + + /** Set the DiagLogger instance + * @param logger - The DiagLogger instance to set as the default logger + * @returns The previously registered DiagLogger + */ + public setLogger!: (logger: DiagLogger) => DiagLogger; + + /** Set the default maximum diagnostic logging level */ + public setLogLevel!: (maxLogLevel: DiagLogLevel) => void; + + // DiagLogger implementation + public trace!: DiagLogFunction; + public debug!: DiagLogFunction; + public info!: DiagLogFunction; + public warn!: DiagLogFunction; + public error!: DiagLogFunction; + public critical!: DiagLogFunction; + public terminal!: DiagLogFunction; + + public forcedInfo!: DiagLogFunction; +} diff --git a/packages/opentelemetry-api/src/api/global-utils.ts b/packages/opentelemetry-api/src/api/global-utils.ts index 60481a114b6..b0a0e522247 100644 --- a/packages/opentelemetry-api/src/api/global-utils.ts +++ b/packages/opentelemetry-api/src/api/global-utils.ts @@ -18,6 +18,7 @@ import { ContextManager } from '@opentelemetry/context-base'; import { TextMapPropagator } from '../context/propagation/TextMapPropagator'; import { TracerProvider } from '../trace/tracer_provider'; import { _globalThis } from '../platform'; +import { DiagAPI } from '../api/diag'; export const GLOBAL_CONTEXT_MANAGER_API_KEY = Symbol.for( 'io.opentelemetry.js.api.context' @@ -28,11 +29,16 @@ export const GLOBAL_PROPAGATION_API_KEY = Symbol.for( ); export const GLOBAL_TRACE_API_KEY = Symbol.for('io.opentelemetry.js.api.trace'); +export const GLOBAL_DIAG_LOGGER_API_KEY = Symbol.for( + 'io.opentelemetry.js.api.diag' +); + type Get = (version: number) => T; type OtelGlobal = Partial<{ [GLOBAL_CONTEXT_MANAGER_API_KEY]: Get; [GLOBAL_PROPAGATION_API_KEY]: Get; [GLOBAL_TRACE_API_KEY]: Get; + [GLOBAL_DIAG_LOGGER_API_KEY]: Get; }>; export const _global = _globalThis as OtelGlobal; diff --git a/packages/opentelemetry-api/src/common/Logger.ts b/packages/opentelemetry-api/src/common/Logger.ts index f4bccbe9dbd..3f0d0406884 100644 --- a/packages/opentelemetry-api/src/common/Logger.ts +++ b/packages/opentelemetry-api/src/common/Logger.ts @@ -16,7 +16,10 @@ export type LogFunction = (message: string, ...args: unknown[]) => void; -/** Defines a logger interface. */ +/** Defines a logger interface. + * @deprecated This interface will be removed prior to v1.0, use the api.diag + * @see {@link DiagLogger} and {@link DiagAPI} + */ export interface Logger { error: LogFunction; warn: LogFunction; diff --git a/packages/opentelemetry-api/src/diag/consoleLogger.ts b/packages/opentelemetry-api/src/diag/consoleLogger.ts new file mode 100644 index 00000000000..877b4a5fa3f --- /dev/null +++ b/packages/opentelemetry-api/src/diag/consoleLogger.ts @@ -0,0 +1,111 @@ +/* + * Copyright The OpenTelemetry Authors + * + * 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 { DiagLogger, DiagLogFunction } from './logger'; + +const consoleMap: { n: keyof DiagLogger; c: keyof Console }[] = [ + { n: 'terminal', c: 'error' }, + { n: 'critical', c: 'error' }, + { n: 'error', c: 'error' }, + { n: 'warn', c: 'warn' }, + { n: 'info', c: 'info' }, + { n: 'debug', c: 'debug' }, + { n: 'trace', c: 'trace' }, + { n: 'forcedInfo', c: 'info' }, +]; + +/** + * A simple Immutable Console based diagnostic logger which will output any messages to the Console. + * If you want to limit the amount of logging to a specific level or lower use the + * {@link diagLogLevelFilter} + */ +export class DiagConsoleLogger implements DiagLogger { + constructor() { + function _consoleFunc(funcName: keyof Console): DiagLogFunction { + return function () { + const orgArguments = arguments; + if (console) { + // Some environments only expose the console when the F12 developer console is open + let theFunc = console[funcName]; + if (!theFunc) { + // Not all environments support all functions + theFunc = console.log; + } + + // One last final check + if (theFunc && typeof theFunc === 'function') { + return theFunc.apply(console, orgArguments); + } + } + }; + } + + for (let lp = 0; lp < consoleMap.length; lp++) { + const name = consoleMap[lp].n; + let consoleFunc = consoleMap[lp].c; + if (console && !console[consoleFunc]) { + consoleFunc = 'log'; + } + this[name] = _consoleFunc(consoleFunc); + } + } + + /** Log a terminal situation that would cause the API to completely fail to initialize, + * if this type of message is logged functionality of the API is not expected to be functional. + */ + public terminal!: DiagLogFunction; + + /** Log a critical error that NEEDS to be addressed, functionality of the component that emits + * this log detail may non-functional. While the overall API may be. + */ + public critical!: DiagLogFunction; + + /** Log an error scenario that was not expected and caused the requested operation to fail. */ + public error!: DiagLogFunction; + + /** Log a warning scenario to inform the developer of an issues that should be investigated. + * The requested operation may or may not have succeeded or completed. + */ + public warn!: DiagLogFunction; + + /** Log a general informational message, this should not affect functionality. + * This is also the default logging level so this should NOT be used for logging + * debugging level information. + */ + public info!: DiagLogFunction; + + /** Log a general debug message that can be useful for identifying a failure. + * Information logged at this level may include diagnostic details that would + * help identify a failure scenario. Useful scenarios would be to log the execution + * order of async operations + */ + public debug!: DiagLogFunction; + + /** Log a detailed (verbose) trace level logging that can be used to identify failures + * where debug level logging would be insufficient, this level of tracing can include + * input and output parameters and as such may include PII information passing through + * the API. As such it is recommended that this level of tracing should not be enabled + * in a production environment. + */ + public trace!: DiagLogFunction; + + /** Log a general informational message that should always be logged regardless of the + * current {@Link DiagLogLevel) and configured filtering level. This type of logging is + * useful for logging component startup and version information without causing additional + * general informational messages when the logging level is set to DiagLogLevel.WARN or lower. + */ + public forcedInfo!: DiagLogFunction; +} diff --git a/packages/opentelemetry-api/src/diag/logLevel.ts b/packages/opentelemetry-api/src/diag/logLevel.ts new file mode 100644 index 00000000000..06d3aba8e97 --- /dev/null +++ b/packages/opentelemetry-api/src/diag/logLevel.ts @@ -0,0 +1,143 @@ +/* + * Copyright The OpenTelemetry Authors + * + * 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 { DiagAPI } from '../api/diag'; +import { DiagLogger, DiagLogFunction } from './logger'; + +/** + * Defines the available internal logging levels for the diagnostic logger, the numeric values + * of the levels are defined to match the original values from the initial LogLevel to avoid + * compatibility/migration issues for any implementation that assume the numeric ordering. + */ +export enum DiagLogLevel { + /** DIagnostic Logging level setting to disable all logging (except and forced logs) */ + NONE = -99, + + /** Identifies a terminal situation that would cause the API to completely fail to initialize, + * if this type of error is logged functionality of the API is not expected to be functional. + */ + TERMINAL = -2, + + /** Identifies a critical error that needs to be addressed, functionality of the component + * that emits this log detail may non-functional. + */ + CRITICAL = -1, + + /** Identifies an error scenario */ + ERROR = 0, + + /** Identifies a warning scenario */ + WARN = 1, + + /** General informational log message */ + INFO = 2, + + /** General debug log message */ + DEBUG = 3, + + /** Detailed trace level logging should only be used for development, should only be set + * in a development environment. + */ + TRACE = 4, + + /** Used to set the logging level to include all logging */ + ALL = 9999, +} + +/** + * This is equivalent to: + * type LogLevelString = 'NONE' | TERMINAL' | 'CRITICAL' | 'ERROR' | 'WARN' | 'INFO' | 'DEBUG' | 'TRACE' | 'ALL'; + */ +export type DiagLogLevelString = keyof typeof DiagLogLevel; + +/** + * Mapping from DiagLogger function name to logging level + */ +const levelMap: { n: keyof DiagLogger; l: DiagLogLevel; f?: boolean }[] = [ + { n: 'terminal', l: DiagLogLevel.TERMINAL }, + { n: 'critical', l: DiagLogLevel.CRITICAL }, + { n: 'error', l: DiagLogLevel.ERROR }, + { n: 'warn', l: DiagLogLevel.WARN }, + { n: 'info', l: DiagLogLevel.INFO }, + { n: 'debug', l: DiagLogLevel.DEBUG }, + { n: 'trace', l: DiagLogLevel.TRACE }, + { n: 'forcedInfo', l: DiagLogLevel.INFO, f: true }, +]; + +/** + * An Immutable Diagnostic logger that limits the reported diagnostic log messages to those at the + * maximum logging level or lower. + * This can be useful to reduce the amount of logging used for a specific component based on any + * local configuration + */ + +/** + * Create a Diagnostic filter logger which limits the logged messages to the defined provided maximum + * logging level or lower. This can be useful to reduce the amount of logging used for the system or + * for a specific component based on any local configuration. + * If you don't supply a logger it will use the global api.diag as the destination which will use the + * current logger and any filtering it may have applied. + * To avoid / bypass any global level filtering you should pass the current logger returned via + * api.diag.getLogger() however, any changes to the logger used by api.diag won't be reflected for this case. + * @param maxLevel - The max level to log any logging of a lower + * @param logger - The specific logger to limit, if not defined or supplied will default to api.diag + * @implements {@link DiagLogger} + * @returns {DiagLogger} + */ + +export function diagLogLevelFilter( + maxLevel: DiagLogLevel, + logger?: DiagLogger | null +): DiagLogger { + if (!logger) { + logger = DiagAPI.inst() as DiagLogger; + } + + if (maxLevel < DiagLogLevel.NONE) { + maxLevel = DiagLogLevel.NONE; + } else if (maxLevel > DiagLogLevel.ALL) { + maxLevel = DiagLogLevel.ALL; + } + + function _filterFunc( + theLogger: DiagLogger, + funcName: keyof DiagLogger, + theLevel: DiagLogLevel, + isForced?: boolean + ): DiagLogFunction { + if (isForced || maxLevel >= theLevel) { + return function () { + const orgArguments = arguments as unknown; + const theFunc = theLogger[funcName]; + if (theFunc && typeof theFunc === 'function') { + return theFunc.apply( + logger, + orgArguments as Parameters + ); + } + }; + } + return function () {}; + } + + const newLogger = {} as DiagLogger; + for (let lp = 0; lp < levelMap.length; lp++) { + const name = levelMap[lp].n; + newLogger[name] = _filterFunc(logger, name, levelMap[lp].l, levelMap[lp].f); + } + + return newLogger; +} diff --git a/packages/opentelemetry-api/src/diag/logger.ts b/packages/opentelemetry-api/src/diag/logger.ts new file mode 100644 index 00000000000..aff46a4fb09 --- /dev/null +++ b/packages/opentelemetry-api/src/diag/logger.ts @@ -0,0 +1,158 @@ +/* + * Copyright The OpenTelemetry Authors + * + * 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 { Logger } from '../common/Logger'; + +/** Defines a type which can be used for as a parameter without breaking backward + * compatibility. The {@link Logger} reference will be removed with the removal + * of the Logger definition, this can be used as a replacement for functions + * that are currently passing Logger references during migration to minimize + * breaks that will occur with the removal of the Logger interface. + */ +export type OptionalDiagLogger = Logger | DiagLogger | null | undefined; + +export type DiagLogFunction = (message: string, ...args: unknown[]) => void; + +/** Defines an internal diagnostic logger interface which is used to log internal diagnostic + * messages, you can set the default diagnostic logger via the {@link DiagAPI} setLogger function. + * API provided implementations include :- + * - a No-Op {@link noopDiagLogger} + * - a {@link DiagLogLevel} filtering wrapper {@link diagLogLevelFilter} + * - a general Console {@link DiagConsoleLogger} version. + */ +export interface DiagLogger { + /** Log a terminal situation that would cause the API to completely fail to initialize, + * if this type of message is logged functionality of the API is not expected to be functional. + */ + terminal: DiagLogFunction; + + /** Log a critical error that NEEDS to be addressed, functionality of the component that emits + * this log detail may non-functional. While the overall API may be. + */ + critical: DiagLogFunction; + + /** Log an error scenario that was not expected and caused the requested operation to fail. */ + error: DiagLogFunction; + + /** Log a warning scenario to inform the developer of an issues that should be investigated. + * The requested operation may or may not have succeeded or completed. + */ + warn: DiagLogFunction; + + /** Log a general informational message, this should not affect functionality. + * This is also the default logging level so this should NOT be used for logging + * debugging level information. + */ + info: DiagLogFunction; + + /** Log a general debug message that can be useful for identifying a failure. + * Information logged at this level may include diagnostic details that would + * help identify a failure scenario. Useful scenarios would be to log the execution + * order of async operations + */ + debug: DiagLogFunction; + + /** Log a detailed (verbose) trace level logging that can be used to identify failures + * where debug level logging would be insufficient, this level of tracing can include + * input and output parameters and as such may include PII information passing through + * the API. As such it is recommended that this level of tracing should not be enabled + * in a production environment. + */ + trace: DiagLogFunction; + + /** Log a general informational message that should always be logged regardless of the + * current {@Link DiagLogLevel) and configured filtering level. This type of logging is + * useful for logging component startup and version information without causing additional + * general informational messages when the logging level is set to DiagLogLevel.WARN or lower. + */ + forcedInfo: DiagLogFunction; +} + +const loggerMapFuncs: { d: keyof DiagLogger; l: keyof Logger }[] = [ + { d: 'trace', l: 'debug' }, + { d: 'debug', l: 'debug' }, + { d: 'info', l: 'info' }, + { d: 'warn', l: 'warn' }, + { d: 'error', l: 'error' }, + { d: 'critical', l: 'error' }, + { d: 'terminal', l: 'error' }, + { d: 'forcedInfo', l: 'info' }, +]; + +function noopLogFunction() {} + +/** + * Returns a No-Op Diagnostic logger where all messages do nothing. + * @implements {@link DiagLogger} + * @returns {DiagLogger} + */ +export function noopDiagLogger(): DiagLogger { + const diagLogger = {} as DiagLogger; + + for (let lp = 0; lp < loggerMapFuncs.length; lp++) { + const map = loggerMapFuncs[lp]; + diagLogger[map.d] = noopLogFunction; + } + + return diagLogger; +} + +/** + * @deprecated This helper will return either the original passed logger if it implements {@link DiagLogger} a + * wrapped instance if it only implements {@link Logger} or null if it's null, undefined. + * This helper will be removed as part of the {@link Logger} deprecation, please use {@link DiagLogger} from the api. + * @see {@link DiagLogLevel} and {@link DiagLogger} + * @returns The passed Logger wrapped as a DiagLogger or null if no Logger was supplied. + */ +export function diagLoggerAdapter( + logger?: OptionalDiagLogger +): DiagLogger | null | undefined { + if (!logger) { + return null; + } + + if (typeof (logger as DiagLogger).forcedInfo === 'function') { + // already looks like a DiagLogger; + return logger as DiagLogger; + } + + function _mapToLogger( + theLogger: Logger, + funcName: keyof Logger + ): DiagLogFunction { + const theFunc = theLogger[funcName]; + if (theFunc && typeof theFunc === 'function') { + return function () { + const orgArguments = arguments as unknown; + return theFunc.apply( + theLogger, + orgArguments as Parameters + ); + }; + } + + return noopLogFunction; + } + + const diagLogger = {} as DiagLogger; + + for (let lp = 0; lp < loggerMapFuncs.length; lp++) { + const map = loggerMapFuncs[lp]; + diagLogger[map.d] = _mapToLogger(logger, map.l); + } + + return diagLogger; +} diff --git a/packages/opentelemetry-api/src/index.ts b/packages/opentelemetry-api/src/index.ts index 4c6b64ffd64..34425bc360b 100644 --- a/packages/opentelemetry-api/src/index.ts +++ b/packages/opentelemetry-api/src/index.ts @@ -43,6 +43,9 @@ export * from './trace/trace_flags'; export * from './trace/trace_state'; export * from './trace/tracer_provider'; export * from './trace/tracer'; +export * from './diag/consoleLogger'; +export * from './diag/logger'; +export * from './diag/logLevel'; export { INVALID_SPANID, @@ -75,8 +78,19 @@ export type { PropagationAPI } from './api/propagation'; /** Entrypoint for propagation API */ export const propagation = PropagationAPI.getInstance(); +import { DiagAPI } from './api/diag'; +export type { DiagAPI } from './api/diag'; + +/** Entrypoint for Diag API. + * Defines Diagnostic handler used for internal diagnostic logging operations. + * The default provides a Noop DiagLogger implementation which may be changed via the + * diag.setLogger(logger: DiagLogger) function. + */ +export const diag = DiagAPI.inst(); + export default { trace, context, propagation, + diag, }; diff --git a/packages/opentelemetry-api/src/trace/NoopLogger.ts b/packages/opentelemetry-api/src/trace/NoopLogger.ts index 1fb8b184d07..06a52724749 100644 --- a/packages/opentelemetry-api/src/trace/NoopLogger.ts +++ b/packages/opentelemetry-api/src/trace/NoopLogger.ts @@ -16,7 +16,10 @@ import { Logger } from '../common/Logger'; -/** No-op implementation of Logger */ +/** No-op implementation of Logger + * @deprecated This class will be removed prior to v1.0, use the api.diag + * @see {@link DiagAPI}, {@link DiagLogger} and {@link noopDiagLogger} + */ export class NoopLogger implements Logger { // By default does nothing debug(_message: string, ..._args: unknown[]) {} diff --git a/packages/opentelemetry-api/test/diag/consoleLogger.test.ts b/packages/opentelemetry-api/test/diag/consoleLogger.test.ts new file mode 100644 index 00000000000..d3ba79de55e --- /dev/null +++ b/packages/opentelemetry-api/test/diag/consoleLogger.test.ts @@ -0,0 +1,330 @@ +/* + * Copyright The OpenTelemetry Authors + * + * 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 * as assert from 'assert'; +import { DiagConsoleLogger } from '../../src/diag/consoleLogger'; + +describe('DiagConsoleLogger', () => { + const origConsole = console; + const origDebug = console.debug; + const origInfo = console.info; + const origWarn = console.warn; + const origError = console.error; + const origTrace = console.trace; + const origLog = console.log; + let traceCalledArgs: unknown; + let debugCalledArgs: unknown; + let infoCalledArgs: unknown; + let warnCalledArgs: unknown; + let errorCalledArgs: unknown; + let logCalledArgs: unknown; + + beforeEach(() => { + // mock + console.debug = (...args: unknown[]) => { + debugCalledArgs = args; + }; + console.info = (...args: unknown[]) => { + infoCalledArgs = args; + }; + console.warn = (...args: unknown[]) => { + warnCalledArgs = args; + }; + console.error = (...args: unknown[]) => { + errorCalledArgs = args; + }; + console.log = (...args: unknown[]) => { + logCalledArgs = args; + }; + console.trace = (...args: unknown[]) => { + traceCalledArgs = args; + }; + }); + + afterEach(() => { + // restore + debugCalledArgs = null; + infoCalledArgs = null; + warnCalledArgs = null; + errorCalledArgs = null; + logCalledArgs = null; + traceCalledArgs = null; + // eslint-disable-next-line no-global-assign + console = origConsole; + console.debug = origDebug; + console.info = origInfo; + console.warn = origWarn; + console.error = origError; + console.log = origLog; + console.trace = origTrace; + }); + + describe('constructor', () => { + it('should log with each call', () => { + const consoleLogger = new DiagConsoleLogger(); + consoleLogger.terminal('terminal called %s', 'param1'); + assert.deepStrictEqual(errorCalledArgs, ['terminal called %s', 'param1']); + consoleLogger.critical('critical called %s', 'param1'); + assert.deepStrictEqual(errorCalledArgs, ['critical called %s', 'param1']); + consoleLogger.error('error called %s', 'param1'); + assert.deepStrictEqual(errorCalledArgs, ['error called %s', 'param1']); + consoleLogger.warn('warn called %s', 'param1'); + assert.deepStrictEqual(warnCalledArgs, ['warn called %s', 'param1']); + consoleLogger.info('info called %s', 'param1'); + assert.deepStrictEqual(infoCalledArgs, ['info called %s', 'param1']); + consoleLogger.debug('debug called %s', 'param1'); + assert.deepStrictEqual(debugCalledArgs, ['debug called %s', 'param1']); + consoleLogger.trace('trace called %s', 'param1'); + assert.deepStrictEqual(traceCalledArgs, ['trace called %s', 'param1']); + consoleLogger.forcedInfo('forcedInfo called %s', 'param1'); + assert.deepStrictEqual(infoCalledArgs, [ + 'forcedInfo called %s', + 'param1', + ]); + }); + + it("should log even of console doesn't support debug", () => { + (console as any).debug = undefined; + const consoleLogger = new DiagConsoleLogger(); + consoleLogger.terminal('terminal called %s', 'param1'); + assert.deepStrictEqual(errorCalledArgs, ['terminal called %s', 'param1']); + consoleLogger.critical('critical called %s', 'param1'); + assert.deepStrictEqual(errorCalledArgs, ['critical called %s', 'param1']); + consoleLogger.error('error called %s', 'param1'); + assert.deepStrictEqual(errorCalledArgs, ['error called %s', 'param1']); + consoleLogger.warn('warn called %s', 'param1'); + assert.deepStrictEqual(warnCalledArgs, ['warn called %s', 'param1']); + consoleLogger.info('info called %s', 'param1'); + assert.deepStrictEqual(infoCalledArgs, ['info called %s', 'param1']); + consoleLogger.debug('debug called %s', 'param1'); + assert.deepStrictEqual(debugCalledArgs, null); + assert.deepStrictEqual(logCalledArgs, ['debug called %s', 'param1']); + consoleLogger.trace('trace called %s', 'param1'); + assert.deepStrictEqual(traceCalledArgs, ['trace called %s', 'param1']); + consoleLogger.forcedInfo('forcedInfo called %s', 'param1'); + assert.deepStrictEqual(infoCalledArgs, [ + 'forcedInfo called %s', + 'param1', + ]); + }); + + it('should log even if console removes debug after initialization', () => { + const consoleLogger = new DiagConsoleLogger(); + (console as any).debug = undefined; + consoleLogger.terminal('terminal called %s', 'param1'); + assert.deepStrictEqual(errorCalledArgs, ['terminal called %s', 'param1']); + consoleLogger.critical('critical called %s', 'param1'); + assert.deepStrictEqual(errorCalledArgs, ['critical called %s', 'param1']); + consoleLogger.error('error called %s', 'param1'); + assert.deepStrictEqual(errorCalledArgs, ['error called %s', 'param1']); + consoleLogger.warn('warn called %s', 'param1'); + assert.deepStrictEqual(warnCalledArgs, ['warn called %s', 'param1']); + consoleLogger.info('info called %s', 'param1'); + assert.deepStrictEqual(infoCalledArgs, ['info called %s', 'param1']); + consoleLogger.debug('debug called %s', 'param1'); + assert.deepStrictEqual(debugCalledArgs, null); + assert.deepStrictEqual(logCalledArgs, ['debug called %s', 'param1']); + consoleLogger.trace('trace called %s', 'param1'); + assert.deepStrictEqual(traceCalledArgs, ['trace called %s', 'param1']); + consoleLogger.forcedInfo('forcedInfo called %s', 'param1'); + assert.deepStrictEqual(infoCalledArgs, [ + 'forcedInfo called %s', + 'param1', + ]); + }); + + it("should log even of console doesn't support trace", () => { + (console as any).trace = undefined; + const consoleLogger = new DiagConsoleLogger(); + consoleLogger.terminal('terminal called %s', 'param1'); + assert.deepStrictEqual(errorCalledArgs, ['terminal called %s', 'param1']); + consoleLogger.critical('critical called %s', 'param1'); + assert.deepStrictEqual(errorCalledArgs, ['critical called %s', 'param1']); + consoleLogger.error('error called %s', 'param1'); + assert.deepStrictEqual(errorCalledArgs, ['error called %s', 'param1']); + consoleLogger.warn('warn called %s', 'param1'); + assert.deepStrictEqual(warnCalledArgs, ['warn called %s', 'param1']); + consoleLogger.info('info called %s', 'param1'); + assert.deepStrictEqual(infoCalledArgs, ['info called %s', 'param1']); + consoleLogger.debug('debug called %s', 'param1'); + assert.deepStrictEqual(debugCalledArgs, ['debug called %s', 'param1']); + consoleLogger.trace('trace called %s', 'param1'); + assert.deepStrictEqual(traceCalledArgs, null); + assert.deepStrictEqual(logCalledArgs, ['trace called %s', 'param1']); + consoleLogger.forcedInfo('forcedInfo called %s', 'param1'); + assert.deepStrictEqual(infoCalledArgs, [ + 'forcedInfo called %s', + 'param1', + ]); + }); + + it('should log even if console removes trace after initialization', () => { + const consoleLogger = new DiagConsoleLogger(); + (console as any).trace = undefined; + consoleLogger.terminal('terminal called %s', 'param1'); + assert.deepStrictEqual(errorCalledArgs, ['terminal called %s', 'param1']); + consoleLogger.critical('critical called %s', 'param1'); + assert.deepStrictEqual(errorCalledArgs, ['critical called %s', 'param1']); + consoleLogger.error('error called %s', 'param1'); + assert.deepStrictEqual(errorCalledArgs, ['error called %s', 'param1']); + consoleLogger.warn('warn called %s', 'param1'); + assert.deepStrictEqual(warnCalledArgs, ['warn called %s', 'param1']); + consoleLogger.info('info called %s', 'param1'); + assert.deepStrictEqual(infoCalledArgs, ['info called %s', 'param1']); + consoleLogger.debug('debug called %s', 'param1'); + assert.deepStrictEqual(debugCalledArgs, ['debug called %s', 'param1']); + consoleLogger.trace('trace called %s', 'param1'); + assert.deepStrictEqual(traceCalledArgs, null); + assert.deepStrictEqual(logCalledArgs, ['trace called %s', 'param1']); + consoleLogger.forcedInfo('forcedInfo called %s', 'param1'); + assert.deepStrictEqual(infoCalledArgs, [ + 'forcedInfo called %s', + 'param1', + ]); + }); + + it('should log even if console removes trace and log after initialization', () => { + const consoleLogger = new DiagConsoleLogger(); + (console as any).trace = undefined; + consoleLogger.terminal('terminal called %s', 'param1'); + assert.deepStrictEqual(errorCalledArgs, ['terminal called %s', 'param1']); + consoleLogger.critical('critical called %s', 'param1'); + assert.deepStrictEqual(errorCalledArgs, ['critical called %s', 'param1']); + consoleLogger.error('error called %s', 'param1'); + assert.deepStrictEqual(errorCalledArgs, ['error called %s', 'param1']); + consoleLogger.warn('warn called %s', 'param1'); + assert.deepStrictEqual(warnCalledArgs, ['warn called %s', 'param1']); + consoleLogger.info('info called %s', 'param1'); + assert.deepStrictEqual(infoCalledArgs, ['info called %s', 'param1']); + consoleLogger.debug('debug called %s', 'param1'); + assert.deepStrictEqual(debugCalledArgs, ['debug called %s', 'param1']); + consoleLogger.trace('trace called %s', 'param1'); + assert.deepStrictEqual(traceCalledArgs, null); + assert.deepStrictEqual(logCalledArgs, ['trace called %s', 'param1']); + consoleLogger.forcedInfo('forcedInfo called %s', 'param1'); + assert.deepStrictEqual(infoCalledArgs, [ + 'forcedInfo called %s', + 'param1', + ]); + }); + + it('should not throw even when console is not supported', () => { + (console as any) = undefined; + const consoleLogger = new DiagConsoleLogger(); + consoleLogger.terminal('terminal called %s', 'param1'); + assert.deepStrictEqual(errorCalledArgs, null); + consoleLogger.critical('critical called %s', 'param1'); + assert.deepStrictEqual(errorCalledArgs, null); + consoleLogger.error('error called %s', 'param1'); + assert.deepStrictEqual(errorCalledArgs, null); + consoleLogger.warn('warn called %s', 'param1'); + assert.deepStrictEqual(warnCalledArgs, null); + consoleLogger.info('info called %s', 'param1'); + assert.deepStrictEqual(infoCalledArgs, null); + consoleLogger.debug('debug called %s', 'param1'); + assert.deepStrictEqual(debugCalledArgs, null); + consoleLogger.trace('trace called %s', 'param1'); + assert.deepStrictEqual(traceCalledArgs, null); + assert.deepStrictEqual(logCalledArgs, null); + consoleLogger.forcedInfo('forcedInfo called %s', 'param1'); + assert.deepStrictEqual(infoCalledArgs, null); + }); + + it('should not throw even when console is disabled after construction', () => { + const consoleLogger = new DiagConsoleLogger(); + (console as any) = undefined; + consoleLogger.terminal('terminal called %s', 'param1'); + assert.deepStrictEqual(errorCalledArgs, null); + consoleLogger.critical('critical called %s', 'param1'); + assert.deepStrictEqual(errorCalledArgs, null); + consoleLogger.error('error called %s', 'param1'); + assert.deepStrictEqual(errorCalledArgs, null); + consoleLogger.warn('warn called %s', 'param1'); + assert.deepStrictEqual(warnCalledArgs, null); + consoleLogger.info('info called %s', 'param1'); + assert.deepStrictEqual(infoCalledArgs, null); + consoleLogger.debug('debug called %s', 'param1'); + assert.deepStrictEqual(debugCalledArgs, null); + consoleLogger.trace('trace called %s', 'param1'); + assert.deepStrictEqual(traceCalledArgs, null); + assert.deepStrictEqual(logCalledArgs, null); + consoleLogger.forcedInfo('forcedInfo called %s', 'param1'); + assert.deepStrictEqual(infoCalledArgs, null); + }); + + it('should not throw even when console is invalid after construction', () => { + const invalidConsole = { + debug: 1, + warn: 2, + error: 3, + trace: 4, + info: 5, + log: 6, + }; + + const consoleLogger = new DiagConsoleLogger(); + (console as any) = invalidConsole; + consoleLogger.terminal('terminal called %s', 'param1'); + assert.deepStrictEqual(errorCalledArgs, null); + consoleLogger.critical('critical called %s', 'param1'); + assert.deepStrictEqual(errorCalledArgs, null); + consoleLogger.error('error called %s', 'param1'); + assert.deepStrictEqual(errorCalledArgs, null); + consoleLogger.warn('warn called %s', 'param1'); + assert.deepStrictEqual(warnCalledArgs, null); + consoleLogger.info('info called %s', 'param1'); + assert.deepStrictEqual(infoCalledArgs, null); + consoleLogger.debug('debug called %s', 'param1'); + assert.deepStrictEqual(debugCalledArgs, null); + consoleLogger.trace('trace called %s', 'param1'); + assert.deepStrictEqual(traceCalledArgs, null); + assert.deepStrictEqual(logCalledArgs, null); + consoleLogger.forcedInfo('forcedInfo called %s', 'param1'); + assert.deepStrictEqual(infoCalledArgs, null); + }); + + it('should not throw even when console is invalid before construction', () => { + const invalidConsole = { + debug: 1, + warn: 2, + error: 3, + trace: 4, + info: 5, + log: 6, + }; + + (console as any) = invalidConsole; + const consoleLogger = new DiagConsoleLogger(); + consoleLogger.terminal('terminal called %s', 'param1'); + assert.deepStrictEqual(errorCalledArgs, null); + consoleLogger.critical('critical called %s', 'param1'); + assert.deepStrictEqual(errorCalledArgs, null); + consoleLogger.error('error called %s', 'param1'); + assert.deepStrictEqual(errorCalledArgs, null); + consoleLogger.warn('warn called %s', 'param1'); + assert.deepStrictEqual(warnCalledArgs, null); + consoleLogger.info('info called %s', 'param1'); + assert.deepStrictEqual(infoCalledArgs, null); + consoleLogger.debug('debug called %s', 'param1'); + assert.deepStrictEqual(debugCalledArgs, null); + consoleLogger.trace('trace called %s', 'param1'); + assert.deepStrictEqual(traceCalledArgs, null); + assert.deepStrictEqual(logCalledArgs, null); + consoleLogger.forcedInfo('forcedInfo called %s', 'param1'); + assert.deepStrictEqual(infoCalledArgs, null); + }); + }); +}); diff --git a/packages/opentelemetry-api/test/diag/logLevel.test.ts b/packages/opentelemetry-api/test/diag/logLevel.test.ts new file mode 100644 index 00000000000..4fefc121fdb --- /dev/null +++ b/packages/opentelemetry-api/test/diag/logLevel.test.ts @@ -0,0 +1,650 @@ +/* + * Copyright The OpenTelemetry Authors + * + * 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 * as assert from 'assert'; +import { DiagLogger } from '../../src/diag/logger'; +import { DiagLogLevel, diagLogLevelFilter } from '../../src/diag/logLevel'; + +describe('LogLevelFilter DiagLogger', () => { + let terminalCalledArgs: unknown; + let criticalCalledArgs: unknown; + let errorCalledArgs: unknown; + let warnCalledArgs: unknown; + let infoCalledArgs: unknown; + let debugCalledArgs: unknown; + let traceCalledArgs: unknown; + let forcedInfoCalledArgs: unknown; + + let dummyLogger: DiagLogger; + + /** Simulated Legacy logger */ + let incompleteLogger: DiagLogger; + + beforeEach(() => { + // mock + dummyLogger = { + terminal: (...args: unknown[]) => { + terminalCalledArgs = args; + }, + critical: (...args: unknown[]) => { + criticalCalledArgs = args; + }, + error: (...args: unknown[]) => { + errorCalledArgs = args; + }, + warn: (...args: unknown[]) => { + warnCalledArgs = args; + }, + info: (...args: unknown[]) => { + infoCalledArgs = args; + }, + debug: (...args: unknown[]) => { + debugCalledArgs = args; + }, + trace: (...args: unknown[]) => { + traceCalledArgs = args; + }, + forcedInfo: (...args: unknown[]) => { + forcedInfoCalledArgs = args; + }, + }; + + incompleteLogger = { + error: (...args: unknown[]) => { + errorCalledArgs = args; + }, + warn: (...args: unknown[]) => { + warnCalledArgs = args; + }, + info: (...args: unknown[]) => { + infoCalledArgs = args; + }, + debug: (...args: unknown[]) => { + debugCalledArgs = args; + }, + } as DiagLogger; + }); + + afterEach(() => { + // restore + terminalCalledArgs = null; + criticalCalledArgs = null; + errorCalledArgs = null; + warnCalledArgs = null; + infoCalledArgs = null; + debugCalledArgs = null; + traceCalledArgs = null; + forcedInfoCalledArgs = null; + }); + + describe('constructor', () => { + it('should log all calls', () => { + const testLogger = dummyLogger; + testLogger.terminal('terminal called %s', 'param1'); + assert.deepStrictEqual(terminalCalledArgs, [ + 'terminal called %s', + 'param1', + ]); + testLogger.critical('critical called %s', 'param1'); + assert.deepStrictEqual(criticalCalledArgs, [ + 'critical called %s', + 'param1', + ]); + testLogger.error('error called %s', 'param1'); + assert.deepStrictEqual(errorCalledArgs, ['error called %s', 'param1']); + testLogger.warn('warn called %s', 'param1'); + assert.deepStrictEqual(warnCalledArgs, ['warn called %s', 'param1']); + testLogger.info('info called %s', 'param1'); + assert.deepStrictEqual(infoCalledArgs, ['info called %s', 'param1']); + testLogger.debug('debug called %s', 'param1'); + assert.deepStrictEqual(debugCalledArgs, ['debug called %s', 'param1']); + testLogger.trace('trace called %s', 'param1'); + assert.deepStrictEqual(traceCalledArgs, ['trace called %s', 'param1']); + testLogger.forcedInfo('forcedInfo called %s', 'param1'); + assert.deepStrictEqual(forcedInfoCalledArgs, [ + 'forcedInfo called %s', + 'param1', + ]); + }); + + it('should log with ALL level', () => { + const testLogger = diagLogLevelFilter(DiagLogLevel.ALL, dummyLogger); + + testLogger.terminal('terminal called %s', 'param1'); + assert.deepStrictEqual(terminalCalledArgs, [ + 'terminal called %s', + 'param1', + ]); + testLogger.critical('critical called %s', 'param1'); + assert.deepStrictEqual(criticalCalledArgs, [ + 'critical called %s', + 'param1', + ]); + testLogger.error('error called %s', 'param1'); + assert.deepStrictEqual(errorCalledArgs, ['error called %s', 'param1']); + testLogger.warn('warn called %s', 'param1'); + assert.deepStrictEqual(warnCalledArgs, ['warn called %s', 'param1']); + testLogger.info('info called %s', 'param1'); + assert.deepStrictEqual(infoCalledArgs, ['info called %s', 'param1']); + testLogger.debug('debug called %s', 'param1'); + assert.deepStrictEqual(debugCalledArgs, ['debug called %s', 'param1']); + testLogger.trace('trace called %s', 'param1'); + assert.deepStrictEqual(traceCalledArgs, ['trace called %s', 'param1']); + testLogger.forcedInfo('forcedInfo called %s', 'param1'); + assert.deepStrictEqual(forcedInfoCalledArgs, [ + 'forcedInfo called %s', + 'param1', + ]); + }); + + it('should log with level greater than ALL', () => { + const testLogger = diagLogLevelFilter(32768, dummyLogger); + + testLogger.terminal('terminal called %s', 'param1'); + assert.deepStrictEqual(terminalCalledArgs, [ + 'terminal called %s', + 'param1', + ]); + testLogger.critical('critical called %s', 'param1'); + assert.deepStrictEqual(criticalCalledArgs, [ + 'critical called %s', + 'param1', + ]); + testLogger.error('error called %s', 'param1'); + assert.deepStrictEqual(errorCalledArgs, ['error called %s', 'param1']); + testLogger.warn('warn called %s', 'param1'); + assert.deepStrictEqual(warnCalledArgs, ['warn called %s', 'param1']); + testLogger.info('info called %s', 'param1'); + assert.deepStrictEqual(infoCalledArgs, ['info called %s', 'param1']); + testLogger.debug('debug called %s', 'param1'); + assert.deepStrictEqual(debugCalledArgs, ['debug called %s', 'param1']); + testLogger.trace('trace called %s', 'param1'); + assert.deepStrictEqual(traceCalledArgs, ['trace called %s', 'param1']); + testLogger.forcedInfo('forcedInfo called %s', 'param1'); + assert.deepStrictEqual(forcedInfoCalledArgs, [ + 'forcedInfo called %s', + 'param1', + ]); + }); + + it('should log with TRACE level', () => { + const testLogger = diagLogLevelFilter(DiagLogLevel.TRACE, dummyLogger); + + testLogger.terminal('terminal called %s', 'param1'); + assert.deepStrictEqual(terminalCalledArgs, [ + 'terminal called %s', + 'param1', + ]); + testLogger.critical('critical called %s', 'param1'); + assert.deepStrictEqual(criticalCalledArgs, [ + 'critical called %s', + 'param1', + ]); + testLogger.error('error called %s', 'param1'); + assert.deepStrictEqual(errorCalledArgs, ['error called %s', 'param1']); + testLogger.warn('warn called %s', 'param1'); + assert.deepStrictEqual(warnCalledArgs, ['warn called %s', 'param1']); + testLogger.info('info called %s', 'param1'); + assert.deepStrictEqual(infoCalledArgs, ['info called %s', 'param1']); + testLogger.debug('debug called %s', 'param1'); + assert.deepStrictEqual(debugCalledArgs, ['debug called %s', 'param1']); + testLogger.trace('trace called %s', 'param1'); + assert.deepStrictEqual(traceCalledArgs, ['trace called %s', 'param1']); + testLogger.forcedInfo('forcedInfo called %s', 'param1'); + assert.deepStrictEqual(forcedInfoCalledArgs, [ + 'forcedInfo called %s', + 'param1', + ]); + }); + + it('should log with debug', () => { + const testLogger = diagLogLevelFilter(DiagLogLevel.DEBUG, dummyLogger); + + testLogger.terminal('terminal called %s', 'param1'); + assert.deepStrictEqual(terminalCalledArgs, [ + 'terminal called %s', + 'param1', + ]); + testLogger.critical('critical called %s', 'param1'); + assert.deepStrictEqual(criticalCalledArgs, [ + 'critical called %s', + 'param1', + ]); + testLogger.error('error called %s', 'param1'); + assert.deepStrictEqual(errorCalledArgs, ['error called %s', 'param1']); + testLogger.warn('warn called %s', 'param1'); + assert.deepStrictEqual(warnCalledArgs, ['warn called %s', 'param1']); + testLogger.info('info called %s', 'param1'); + assert.deepStrictEqual(infoCalledArgs, ['info called %s', 'param1']); + testLogger.debug('debug called %s', 'param1'); + assert.deepStrictEqual(debugCalledArgs, ['debug called %s', 'param1']); + testLogger.trace('trace called %s', 'param1'); + assert.deepStrictEqual(traceCalledArgs, null); + testLogger.forcedInfo('forcedInfo called %s', 'param1'); + assert.deepStrictEqual(forcedInfoCalledArgs, [ + 'forcedInfo called %s', + 'param1', + ]); + }); + + it('should log with info', () => { + const testLogger = diagLogLevelFilter(DiagLogLevel.INFO, dummyLogger); + + testLogger.terminal('terminal called %s', 'param1'); + assert.deepStrictEqual(terminalCalledArgs, [ + 'terminal called %s', + 'param1', + ]); + testLogger.critical('critical called %s', 'param1'); + assert.deepStrictEqual(criticalCalledArgs, [ + 'critical called %s', + 'param1', + ]); + testLogger.error('error called %s', 'param1'); + assert.deepStrictEqual(errorCalledArgs, ['error called %s', 'param1']); + testLogger.warn('warn called %s', 'param1'); + assert.deepStrictEqual(warnCalledArgs, ['warn called %s', 'param1']); + testLogger.info('info called %s', 'param1'); + assert.deepStrictEqual(infoCalledArgs, ['info called %s', 'param1']); + testLogger.debug('debug called %s', 'param1'); + assert.deepStrictEqual(debugCalledArgs, null); + testLogger.trace('trace called %s', 'param1'); + assert.deepStrictEqual(traceCalledArgs, null); + testLogger.forcedInfo('forcedInfo called %s', 'param1'); + assert.deepStrictEqual(forcedInfoCalledArgs, [ + 'forcedInfo called %s', + 'param1', + ]); + }); + + it('should log with warning', () => { + const testLogger = diagLogLevelFilter(DiagLogLevel.WARN, dummyLogger); + + testLogger.terminal('terminal called %s', 'param1'); + assert.deepStrictEqual(terminalCalledArgs, [ + 'terminal called %s', + 'param1', + ]); + testLogger.critical('critical called %s', 'param1'); + assert.deepStrictEqual(criticalCalledArgs, [ + 'critical called %s', + 'param1', + ]); + testLogger.error('error called %s', 'param1'); + assert.deepStrictEqual(errorCalledArgs, ['error called %s', 'param1']); + testLogger.warn('warn called %s', 'param1'); + assert.deepStrictEqual(warnCalledArgs, ['warn called %s', 'param1']); + testLogger.info('info called %s', 'param1'); + assert.deepStrictEqual(infoCalledArgs, null); + testLogger.debug('debug called %s', 'param1'); + assert.deepStrictEqual(debugCalledArgs, null); + testLogger.trace('trace called %s', 'param1'); + assert.deepStrictEqual(traceCalledArgs, null); + testLogger.forcedInfo('forcedInfo called %s', 'param1'); + assert.deepStrictEqual(forcedInfoCalledArgs, [ + 'forcedInfo called %s', + 'param1', + ]); + }); + + it('should log with error', () => { + const testLogger = diagLogLevelFilter(DiagLogLevel.ERROR, dummyLogger); + + testLogger.terminal('terminal called %s', 'param1'); + assert.deepStrictEqual(terminalCalledArgs, [ + 'terminal called %s', + 'param1', + ]); + testLogger.critical('critical called %s', 'param1'); + assert.deepStrictEqual(criticalCalledArgs, [ + 'critical called %s', + 'param1', + ]); + testLogger.error('error called %s', 'param1'); + assert.deepStrictEqual(errorCalledArgs, ['error called %s', 'param1']); + testLogger.warn('warn called %s', 'param1'); + assert.deepStrictEqual(warnCalledArgs, null); + testLogger.info('info called %s', 'param1'); + assert.deepStrictEqual(infoCalledArgs, null); + testLogger.debug('debug called %s', 'param1'); + assert.deepStrictEqual(debugCalledArgs, null); + testLogger.trace('trace called %s', 'param1'); + assert.deepStrictEqual(traceCalledArgs, null); + testLogger.forcedInfo('forcedInfo called %s', 'param1'); + assert.deepStrictEqual(forcedInfoCalledArgs, [ + 'forcedInfo called %s', + 'param1', + ]); + }); + + it('should log with critical', () => { + const testLogger = diagLogLevelFilter(DiagLogLevel.CRITICAL, dummyLogger); + + testLogger.terminal('terminal called %s', 'param1'); + assert.deepStrictEqual(terminalCalledArgs, [ + 'terminal called %s', + 'param1', + ]); + testLogger.critical('critical called %s', 'param1'); + assert.deepStrictEqual(criticalCalledArgs, [ + 'critical called %s', + 'param1', + ]); + testLogger.error('error called %s', 'param1'); + assert.deepStrictEqual(errorCalledArgs, null); + testLogger.warn('warn called %s', 'param1'); + assert.deepStrictEqual(warnCalledArgs, null); + testLogger.info('info called %s', 'param1'); + assert.deepStrictEqual(infoCalledArgs, null); + testLogger.debug('debug called %s', 'param1'); + assert.deepStrictEqual(debugCalledArgs, null); + testLogger.trace('trace called %s', 'param1'); + assert.deepStrictEqual(traceCalledArgs, null); + testLogger.forcedInfo('forcedInfo called %s', 'param1'); + assert.deepStrictEqual(forcedInfoCalledArgs, [ + 'forcedInfo called %s', + 'param1', + ]); + }); + + it('should log with terminal', () => { + const testLogger = diagLogLevelFilter(DiagLogLevel.TERMINAL, dummyLogger); + + testLogger.terminal('terminal called %s', 'param1'); + assert.deepStrictEqual(terminalCalledArgs, [ + 'terminal called %s', + 'param1', + ]); + testLogger.critical('critical called %s', 'param1'); + assert.deepStrictEqual(criticalCalledArgs, null); + testLogger.error('error called %s', 'param1'); + assert.deepStrictEqual(errorCalledArgs, null); + testLogger.warn('warn called %s', 'param1'); + assert.deepStrictEqual(warnCalledArgs, null); + testLogger.info('info called %s', 'param1'); + assert.deepStrictEqual(infoCalledArgs, null); + testLogger.debug('debug called %s', 'param1'); + assert.deepStrictEqual(debugCalledArgs, null); + testLogger.trace('trace called %s', 'param1'); + assert.deepStrictEqual(traceCalledArgs, null); + testLogger.forcedInfo('forcedInfo called %s', 'param1'); + assert.deepStrictEqual(forcedInfoCalledArgs, [ + 'forcedInfo called %s', + 'param1', + ]); + }); + + it('should log with none', () => { + const testLogger = diagLogLevelFilter(DiagLogLevel.NONE, dummyLogger); + + testLogger.terminal('terminal called %s', 'param1'); + assert.deepStrictEqual(terminalCalledArgs, null); + testLogger.critical('critical called %s', 'param1'); + assert.deepStrictEqual(criticalCalledArgs, null); + testLogger.error('error called %s', 'param1'); + assert.deepStrictEqual(errorCalledArgs, null); + testLogger.warn('warn called %s', 'param1'); + assert.deepStrictEqual(warnCalledArgs, null); + testLogger.info('info called %s', 'param1'); + assert.deepStrictEqual(infoCalledArgs, null); + testLogger.debug('debug called %s', 'param1'); + assert.deepStrictEqual(debugCalledArgs, null); + testLogger.trace('trace called %s', 'param1'); + assert.deepStrictEqual(traceCalledArgs, null); + testLogger.forcedInfo('forcedInfo called %s', 'param1'); + assert.deepStrictEqual(forcedInfoCalledArgs, [ + 'forcedInfo called %s', + 'param1', + ]); + }); + + it('should log with value less than NONE', () => { + const testLogger = diagLogLevelFilter(-1000, dummyLogger); + + testLogger.terminal('terminal called %s', 'param1'); + assert.deepStrictEqual(terminalCalledArgs, null); + testLogger.critical('critical called %s', 'param1'); + assert.deepStrictEqual(criticalCalledArgs, null); + testLogger.error('error called %s', 'param1'); + assert.deepStrictEqual(errorCalledArgs, null); + testLogger.warn('warn called %s', 'param1'); + assert.deepStrictEqual(warnCalledArgs, null); + testLogger.info('info called %s', 'param1'); + assert.deepStrictEqual(infoCalledArgs, null); + testLogger.debug('debug called %s', 'param1'); + assert.deepStrictEqual(debugCalledArgs, null); + testLogger.trace('trace called %s', 'param1'); + assert.deepStrictEqual(traceCalledArgs, null); + testLogger.forcedInfo('forcedInfo called %s', 'param1'); + assert.deepStrictEqual(forcedInfoCalledArgs, [ + 'forcedInfo called %s', + 'param1', + ]); + }); + it('legacyLogger should log with ALL level', () => { + const testLogger = diagLogLevelFilter(DiagLogLevel.ALL, incompleteLogger); + + testLogger.terminal('terminal called %s', 'param1'); + assert.deepStrictEqual(terminalCalledArgs, null); + testLogger.critical('critical called %s', 'param1'); + assert.deepStrictEqual(criticalCalledArgs, null); + testLogger.error('error called %s', 'param1'); + assert.deepStrictEqual(errorCalledArgs, ['error called %s', 'param1']); + testLogger.warn('warn called %s', 'param1'); + assert.deepStrictEqual(warnCalledArgs, ['warn called %s', 'param1']); + testLogger.info('info called %s', 'param1'); + assert.deepStrictEqual(infoCalledArgs, ['info called %s', 'param1']); + testLogger.debug('debug called %s', 'param1'); + assert.deepStrictEqual(debugCalledArgs, ['debug called %s', 'param1']); + testLogger.trace('trace called %s', 'param1'); + assert.deepStrictEqual(traceCalledArgs, null); + testLogger.forcedInfo('forcedInfo called %s', 'param1'); + assert.deepStrictEqual(forcedInfoCalledArgs, null); + }); + + it('legacyLogger should log with TRACE level', () => { + const testLogger = diagLogLevelFilter( + DiagLogLevel.TRACE, + incompleteLogger + ); + + testLogger.terminal('terminal called %s', 'param1'); + assert.deepStrictEqual(terminalCalledArgs, null); + testLogger.critical('critical called %s', 'param1'); + assert.deepStrictEqual(criticalCalledArgs, null); + testLogger.error('error called %s', 'param1'); + assert.deepStrictEqual(errorCalledArgs, ['error called %s', 'param1']); + testLogger.warn('warn called %s', 'param1'); + assert.deepStrictEqual(warnCalledArgs, ['warn called %s', 'param1']); + testLogger.info('info called %s', 'param1'); + assert.deepStrictEqual(infoCalledArgs, ['info called %s', 'param1']); + testLogger.debug('debug called %s', 'param1'); + assert.deepStrictEqual(debugCalledArgs, ['debug called %s', 'param1']); + testLogger.trace('trace called %s', 'param1'); + assert.deepStrictEqual(traceCalledArgs, null); + testLogger.forcedInfo('forcedInfo called %s', 'param1'); + assert.deepStrictEqual(forcedInfoCalledArgs, null); + }); + + it('legacyLogger should log with debug', () => { + const testLogger = diagLogLevelFilter( + DiagLogLevel.DEBUG, + incompleteLogger + ); + + testLogger.terminal('terminal called %s', 'param1'); + assert.deepStrictEqual(terminalCalledArgs, null); + testLogger.critical('critical called %s', 'param1'); + assert.deepStrictEqual(criticalCalledArgs, null); + testLogger.error('error called %s', 'param1'); + assert.deepStrictEqual(errorCalledArgs, ['error called %s', 'param1']); + testLogger.warn('warn called %s', 'param1'); + assert.deepStrictEqual(warnCalledArgs, ['warn called %s', 'param1']); + testLogger.info('info called %s', 'param1'); + assert.deepStrictEqual(infoCalledArgs, ['info called %s', 'param1']); + testLogger.debug('debug called %s', 'param1'); + assert.deepStrictEqual(debugCalledArgs, ['debug called %s', 'param1']); + testLogger.trace('trace called %s', 'param1'); + assert.deepStrictEqual(traceCalledArgs, null); + testLogger.forcedInfo('forcedInfo called %s', 'param1'); + assert.deepStrictEqual(forcedInfoCalledArgs, null); + }); + + it('legacyLogger should log with info', () => { + const testLogger = diagLogLevelFilter( + DiagLogLevel.INFO, + incompleteLogger + ); + + testLogger.terminal('terminal called %s', 'param1'); + assert.deepStrictEqual(terminalCalledArgs, null); + testLogger.critical('critical called %s', 'param1'); + assert.deepStrictEqual(criticalCalledArgs, null); + testLogger.error('error called %s', 'param1'); + assert.deepStrictEqual(errorCalledArgs, ['error called %s', 'param1']); + testLogger.warn('warn called %s', 'param1'); + assert.deepStrictEqual(warnCalledArgs, ['warn called %s', 'param1']); + testLogger.info('info called %s', 'param1'); + assert.deepStrictEqual(infoCalledArgs, ['info called %s', 'param1']); + testLogger.debug('debug called %s', 'param1'); + assert.deepStrictEqual(debugCalledArgs, null); + testLogger.trace('trace called %s', 'param1'); + assert.deepStrictEqual(traceCalledArgs, null); + testLogger.forcedInfo('forcedInfo called %s', 'param1'); + assert.deepStrictEqual(forcedInfoCalledArgs, null); + }); + + it('legacyLogger should log with warning', () => { + const testLogger = diagLogLevelFilter( + DiagLogLevel.WARN, + incompleteLogger + ); + + testLogger.terminal('terminal called %s', 'param1'); + assert.deepStrictEqual(terminalCalledArgs, null); + testLogger.critical('critical called %s', 'param1'); + assert.deepStrictEqual(criticalCalledArgs, null); + testLogger.error('error called %s', 'param1'); + assert.deepStrictEqual(errorCalledArgs, ['error called %s', 'param1']); + testLogger.warn('warn called %s', 'param1'); + assert.deepStrictEqual(warnCalledArgs, ['warn called %s', 'param1']); + testLogger.info('info called %s', 'param1'); + assert.deepStrictEqual(infoCalledArgs, null); + testLogger.debug('debug called %s', 'param1'); + assert.deepStrictEqual(debugCalledArgs, null); + testLogger.trace('trace called %s', 'param1'); + assert.deepStrictEqual(traceCalledArgs, null); + testLogger.forcedInfo('forcedInfo called %s', 'param1'); + assert.deepStrictEqual(forcedInfoCalledArgs, null); + }); + + it('legacyLogger should log with error', () => { + const testLogger = diagLogLevelFilter( + DiagLogLevel.ERROR, + incompleteLogger + ); + + testLogger.terminal('terminal called %s', 'param1'); + assert.deepStrictEqual(terminalCalledArgs, null); + testLogger.critical('critical called %s', 'param1'); + assert.deepStrictEqual(criticalCalledArgs, null); + testLogger.error('error called %s', 'param1'); + assert.deepStrictEqual(errorCalledArgs, ['error called %s', 'param1']); + testLogger.warn('warn called %s', 'param1'); + assert.deepStrictEqual(warnCalledArgs, null); + testLogger.info('info called %s', 'param1'); + assert.deepStrictEqual(infoCalledArgs, null); + testLogger.debug('debug called %s', 'param1'); + assert.deepStrictEqual(debugCalledArgs, null); + testLogger.trace('trace called %s', 'param1'); + assert.deepStrictEqual(traceCalledArgs, null); + testLogger.forcedInfo('forcedInfo called %s', 'param1'); + assert.deepStrictEqual(forcedInfoCalledArgs, null); + }); + + it('legacyLogger should log with critical', () => { + const testLogger = diagLogLevelFilter( + DiagLogLevel.CRITICAL, + incompleteLogger + ); + + testLogger.terminal('terminal called %s', 'param1'); + assert.deepStrictEqual(terminalCalledArgs, null); + testLogger.critical('critical called %s', 'param1'); + assert.deepStrictEqual(criticalCalledArgs, null); + testLogger.error('error called %s', 'param1'); + assert.deepStrictEqual(errorCalledArgs, null); + testLogger.warn('warn called %s', 'param1'); + assert.deepStrictEqual(warnCalledArgs, null); + testLogger.info('info called %s', 'param1'); + assert.deepStrictEqual(infoCalledArgs, null); + testLogger.debug('debug called %s', 'param1'); + assert.deepStrictEqual(debugCalledArgs, null); + testLogger.trace('trace called %s', 'param1'); + assert.deepStrictEqual(traceCalledArgs, null); + testLogger.forcedInfo('forcedInfo called %s', 'param1'); + assert.deepStrictEqual(forcedInfoCalledArgs, null); + }); + + it('legacyLogger should log with terminal', () => { + const testLogger = diagLogLevelFilter( + DiagLogLevel.TERMINAL, + incompleteLogger + ); + + testLogger.terminal('terminal called %s', 'param1'); + assert.deepStrictEqual(terminalCalledArgs, null); + testLogger.critical('critical called %s', 'param1'); + assert.deepStrictEqual(criticalCalledArgs, null); + testLogger.error('error called %s', 'param1'); + assert.deepStrictEqual(errorCalledArgs, null); + testLogger.warn('warn called %s', 'param1'); + assert.deepStrictEqual(warnCalledArgs, null); + testLogger.info('info called %s', 'param1'); + assert.deepStrictEqual(infoCalledArgs, null); + testLogger.debug('debug called %s', 'param1'); + assert.deepStrictEqual(debugCalledArgs, null); + testLogger.trace('trace called %s', 'param1'); + assert.deepStrictEqual(traceCalledArgs, null); + testLogger.forcedInfo('forcedInfo called %s', 'param1'); + assert.deepStrictEqual(forcedInfoCalledArgs, null); + }); + + it('legacyLogger should log with none', () => { + const testLogger = diagLogLevelFilter( + DiagLogLevel.NONE, + incompleteLogger + ); + + testLogger.terminal('terminal called %s', 'param1'); + assert.deepStrictEqual(terminalCalledArgs, null); + testLogger.critical('critical called %s', 'param1'); + assert.deepStrictEqual(criticalCalledArgs, null); + testLogger.error('error called %s', 'param1'); + assert.deepStrictEqual(errorCalledArgs, null); + testLogger.warn('warn called %s', 'param1'); + assert.deepStrictEqual(warnCalledArgs, null); + testLogger.info('info called %s', 'param1'); + assert.deepStrictEqual(infoCalledArgs, null); + testLogger.debug('debug called %s', 'param1'); + assert.deepStrictEqual(debugCalledArgs, null); + testLogger.trace('trace called %s', 'param1'); + assert.deepStrictEqual(traceCalledArgs, null); + testLogger.forcedInfo('forcedInfo called %s', 'param1'); + assert.deepStrictEqual(forcedInfoCalledArgs, null); + }); + }); +}); diff --git a/packages/opentelemetry-api/test/diag/logger.test.ts b/packages/opentelemetry-api/test/diag/logger.test.ts new file mode 100644 index 00000000000..bc4b6cf3f43 --- /dev/null +++ b/packages/opentelemetry-api/test/diag/logger.test.ts @@ -0,0 +1,876 @@ +/* + * Copyright The OpenTelemetry Authors + * + * 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 * as assert from 'assert'; +import { Logger } from '../../src'; +import { + DiagLogger, + diagLoggerAdapter, + noopDiagLogger, +} from '../../src/diag/logger'; +import { DiagLogLevel, diagLogLevelFilter } from '../../src/diag/logLevel'; + +describe('LogLevelFilter DiagLogger', () => { + let terminalCalledArgs: unknown; + let criticalCalledArgs: unknown; + let errorCalledArgs: unknown; + let warnCalledArgs: unknown; + let infoCalledArgs: unknown; + let debugCalledArgs: unknown; + let traceCalledArgs: unknown; + let forcedInfoCalledArgs: unknown; + + let dummyLogger: DiagLogger; + + let legacyLogger: Logger; + + beforeEach(() => { + // mock + dummyLogger = { + terminal: (...args: unknown[]) => { + terminalCalledArgs = args; + }, + critical: (...args: unknown[]) => { + criticalCalledArgs = args; + }, + error: (...args: unknown[]) => { + errorCalledArgs = args; + }, + warn: (...args: unknown[]) => { + warnCalledArgs = args; + }, + info: (...args: unknown[]) => { + infoCalledArgs = args; + }, + debug: (...args: unknown[]) => { + debugCalledArgs = args; + }, + trace: (...args: unknown[]) => { + traceCalledArgs = args; + }, + forcedInfo: (...args: unknown[]) => { + forcedInfoCalledArgs = args; + }, + }; + + legacyLogger = { + error: (...args: unknown[]) => { + errorCalledArgs = args; + }, + warn: (...args: unknown[]) => { + warnCalledArgs = args; + }, + info: (...args: unknown[]) => { + infoCalledArgs = args; + }, + debug: (...args: unknown[]) => { + debugCalledArgs = args; + }, + }; + }); + + afterEach(() => { + // restore + terminalCalledArgs = null; + criticalCalledArgs = null; + errorCalledArgs = null; + warnCalledArgs = null; + infoCalledArgs = null; + debugCalledArgs = null; + traceCalledArgs = null; + forcedInfoCalledArgs = null; + }); + + describe('constructor', () => { + it('should log with default level', () => { + const testLogger = dummyLogger; + testLogger.terminal('terminal called %s', 'param1'); + assert.deepStrictEqual(terminalCalledArgs, [ + 'terminal called %s', + 'param1', + ]); + testLogger.critical('critical called %s', 'param1'); + assert.deepStrictEqual(criticalCalledArgs, [ + 'critical called %s', + 'param1', + ]); + testLogger.error('error called %s', 'param1'); + assert.deepStrictEqual(errorCalledArgs, ['error called %s', 'param1']); + testLogger.warn('warn called %s', 'param1'); + assert.deepStrictEqual(warnCalledArgs, ['warn called %s', 'param1']); + testLogger.info('info called %s', 'param1'); + assert.deepStrictEqual(infoCalledArgs, ['info called %s', 'param1']); + testLogger.debug('debug called %s', 'param1'); + assert.deepStrictEqual(debugCalledArgs, ['debug called %s', 'param1']); + testLogger.trace('trace called %s', 'param1'); + assert.deepStrictEqual(traceCalledArgs, ['trace called %s', 'param1']); + testLogger.forcedInfo('forcedInfo called %s', 'param1'); + assert.deepStrictEqual(forcedInfoCalledArgs, [ + 'forcedInfo called %s', + 'param1', + ]); + }); + + it('should log with default level', () => { + const testLogger = diagLogLevelFilter( + DiagLogLevel.ALL, + diagLoggerAdapter(dummyLogger) + ); + + testLogger.terminal('terminal called %s', 'param1'); + assert.deepStrictEqual(terminalCalledArgs, [ + 'terminal called %s', + 'param1', + ]); + testLogger.critical('critical called %s', 'param1'); + assert.deepStrictEqual(criticalCalledArgs, [ + 'critical called %s', + 'param1', + ]); + testLogger.error('error called %s', 'param1'); + assert.deepStrictEqual(errorCalledArgs, ['error called %s', 'param1']); + testLogger.warn('warn called %s', 'param1'); + assert.deepStrictEqual(warnCalledArgs, ['warn called %s', 'param1']); + testLogger.info('info called %s', 'param1'); + assert.deepStrictEqual(infoCalledArgs, ['info called %s', 'param1']); + testLogger.debug('debug called %s', 'param1'); + assert.deepStrictEqual(debugCalledArgs, ['debug called %s', 'param1']); + testLogger.trace('trace called %s', 'param1'); + assert.deepStrictEqual(traceCalledArgs, ['trace called %s', 'param1']); + testLogger.forcedInfo('forcedInfo called %s', 'param1'); + assert.deepStrictEqual(forcedInfoCalledArgs, [ + 'forcedInfo called %s', + 'param1', + ]); + }); + + it('should log with default level', () => { + const testLogger = diagLogLevelFilter( + DiagLogLevel.TRACE, + diagLoggerAdapter(dummyLogger) + ); + + testLogger.terminal('terminal called %s', 'param1'); + assert.deepStrictEqual(terminalCalledArgs, [ + 'terminal called %s', + 'param1', + ]); + testLogger.critical('critical called %s', 'param1'); + assert.deepStrictEqual(criticalCalledArgs, [ + 'critical called %s', + 'param1', + ]); + testLogger.error('error called %s', 'param1'); + assert.deepStrictEqual(errorCalledArgs, ['error called %s', 'param1']); + testLogger.warn('warn called %s', 'param1'); + assert.deepStrictEqual(warnCalledArgs, ['warn called %s', 'param1']); + testLogger.info('info called %s', 'param1'); + assert.deepStrictEqual(infoCalledArgs, ['info called %s', 'param1']); + testLogger.debug('debug called %s', 'param1'); + assert.deepStrictEqual(debugCalledArgs, ['debug called %s', 'param1']); + testLogger.trace('trace called %s', 'param1'); + assert.deepStrictEqual(traceCalledArgs, ['trace called %s', 'param1']); + testLogger.forcedInfo('forcedInfo called %s', 'param1'); + assert.deepStrictEqual(forcedInfoCalledArgs, [ + 'forcedInfo called %s', + 'param1', + ]); + }); + + it('should log with debug', () => { + const testLogger = diagLogLevelFilter( + DiagLogLevel.DEBUG, + diagLoggerAdapter(dummyLogger) + ); + + testLogger.terminal('terminal called %s', 'param1'); + assert.deepStrictEqual(terminalCalledArgs, [ + 'terminal called %s', + 'param1', + ]); + testLogger.critical('critical called %s', 'param1'); + assert.deepStrictEqual(criticalCalledArgs, [ + 'critical called %s', + 'param1', + ]); + testLogger.error('error called %s', 'param1'); + assert.deepStrictEqual(errorCalledArgs, ['error called %s', 'param1']); + testLogger.warn('warn called %s', 'param1'); + assert.deepStrictEqual(warnCalledArgs, ['warn called %s', 'param1']); + testLogger.info('info called %s', 'param1'); + assert.deepStrictEqual(infoCalledArgs, ['info called %s', 'param1']); + testLogger.debug('debug called %s', 'param1'); + assert.deepStrictEqual(debugCalledArgs, ['debug called %s', 'param1']); + testLogger.trace('trace called %s', 'param1'); + assert.deepStrictEqual(traceCalledArgs, null); + testLogger.forcedInfo('forcedInfo called %s', 'param1'); + assert.deepStrictEqual(forcedInfoCalledArgs, [ + 'forcedInfo called %s', + 'param1', + ]); + }); + + it('should log with info', () => { + const testLogger = diagLogLevelFilter( + DiagLogLevel.INFO, + diagLoggerAdapter(dummyLogger) + ); + + testLogger.terminal('terminal called %s', 'param1'); + assert.deepStrictEqual(terminalCalledArgs, [ + 'terminal called %s', + 'param1', + ]); + testLogger.critical('critical called %s', 'param1'); + assert.deepStrictEqual(criticalCalledArgs, [ + 'critical called %s', + 'param1', + ]); + testLogger.error('error called %s', 'param1'); + assert.deepStrictEqual(errorCalledArgs, ['error called %s', 'param1']); + testLogger.warn('warn called %s', 'param1'); + assert.deepStrictEqual(warnCalledArgs, ['warn called %s', 'param1']); + testLogger.info('info called %s', 'param1'); + assert.deepStrictEqual(infoCalledArgs, ['info called %s', 'param1']); + testLogger.debug('debug called %s', 'param1'); + assert.deepStrictEqual(debugCalledArgs, null); + testLogger.trace('trace called %s', 'param1'); + assert.deepStrictEqual(traceCalledArgs, null); + testLogger.forcedInfo('forcedInfo called %s', 'param1'); + assert.deepStrictEqual(forcedInfoCalledArgs, [ + 'forcedInfo called %s', + 'param1', + ]); + }); + + it('should log with warning', () => { + const testLogger = diagLogLevelFilter( + DiagLogLevel.WARN, + diagLoggerAdapter(dummyLogger) + ); + + testLogger.terminal('terminal called %s', 'param1'); + assert.deepStrictEqual(terminalCalledArgs, [ + 'terminal called %s', + 'param1', + ]); + testLogger.critical('critical called %s', 'param1'); + assert.deepStrictEqual(criticalCalledArgs, [ + 'critical called %s', + 'param1', + ]); + testLogger.error('error called %s', 'param1'); + assert.deepStrictEqual(errorCalledArgs, ['error called %s', 'param1']); + testLogger.warn('warn called %s', 'param1'); + assert.deepStrictEqual(warnCalledArgs, ['warn called %s', 'param1']); + testLogger.info('info called %s', 'param1'); + assert.deepStrictEqual(infoCalledArgs, null); + testLogger.debug('debug called %s', 'param1'); + assert.deepStrictEqual(debugCalledArgs, null); + testLogger.trace('trace called %s', 'param1'); + assert.deepStrictEqual(traceCalledArgs, null); + testLogger.forcedInfo('forcedInfo called %s', 'param1'); + assert.deepStrictEqual(forcedInfoCalledArgs, [ + 'forcedInfo called %s', + 'param1', + ]); + }); + + it('should log with error', () => { + const testLogger = diagLogLevelFilter( + DiagLogLevel.ERROR, + diagLoggerAdapter(dummyLogger) + ); + + testLogger.terminal('terminal called %s', 'param1'); + assert.deepStrictEqual(terminalCalledArgs, [ + 'terminal called %s', + 'param1', + ]); + testLogger.critical('critical called %s', 'param1'); + assert.deepStrictEqual(criticalCalledArgs, [ + 'critical called %s', + 'param1', + ]); + testLogger.error('error called %s', 'param1'); + assert.deepStrictEqual(errorCalledArgs, ['error called %s', 'param1']); + testLogger.warn('warn called %s', 'param1'); + assert.deepStrictEqual(warnCalledArgs, null); + testLogger.info('info called %s', 'param1'); + assert.deepStrictEqual(infoCalledArgs, null); + testLogger.debug('debug called %s', 'param1'); + assert.deepStrictEqual(debugCalledArgs, null); + testLogger.trace('trace called %s', 'param1'); + assert.deepStrictEqual(traceCalledArgs, null); + testLogger.forcedInfo('forcedInfo called %s', 'param1'); + assert.deepStrictEqual(forcedInfoCalledArgs, [ + 'forcedInfo called %s', + 'param1', + ]); + }); + + it('should log with critical', () => { + const testLogger = diagLogLevelFilter( + DiagLogLevel.CRITICAL, + diagLoggerAdapter(dummyLogger) + ); + + testLogger.terminal('terminal called %s', 'param1'); + assert.deepStrictEqual(terminalCalledArgs, [ + 'terminal called %s', + 'param1', + ]); + testLogger.critical('critical called %s', 'param1'); + assert.deepStrictEqual(criticalCalledArgs, [ + 'critical called %s', + 'param1', + ]); + testLogger.error('error called %s', 'param1'); + assert.deepStrictEqual(errorCalledArgs, null); + testLogger.warn('warn called %s', 'param1'); + assert.deepStrictEqual(warnCalledArgs, null); + testLogger.info('info called %s', 'param1'); + assert.deepStrictEqual(infoCalledArgs, null); + testLogger.debug('debug called %s', 'param1'); + assert.deepStrictEqual(debugCalledArgs, null); + testLogger.trace('trace called %s', 'param1'); + assert.deepStrictEqual(traceCalledArgs, null); + testLogger.forcedInfo('forcedInfo called %s', 'param1'); + assert.deepStrictEqual(forcedInfoCalledArgs, [ + 'forcedInfo called %s', + 'param1', + ]); + }); + + it('should log with terminal', () => { + const testLogger = diagLogLevelFilter( + DiagLogLevel.TERMINAL, + diagLoggerAdapter(dummyLogger) + ); + + testLogger.terminal('terminal called %s', 'param1'); + assert.deepStrictEqual(terminalCalledArgs, [ + 'terminal called %s', + 'param1', + ]); + testLogger.critical('critical called %s', 'param1'); + assert.deepStrictEqual(criticalCalledArgs, null); + testLogger.error('error called %s', 'param1'); + assert.deepStrictEqual(errorCalledArgs, null); + testLogger.warn('warn called %s', 'param1'); + assert.deepStrictEqual(warnCalledArgs, null); + testLogger.info('info called %s', 'param1'); + assert.deepStrictEqual(infoCalledArgs, null); + testLogger.debug('debug called %s', 'param1'); + assert.deepStrictEqual(debugCalledArgs, null); + testLogger.trace('trace called %s', 'param1'); + assert.deepStrictEqual(traceCalledArgs, null); + testLogger.forcedInfo('forcedInfo called %s', 'param1'); + assert.deepStrictEqual(forcedInfoCalledArgs, [ + 'forcedInfo called %s', + 'param1', + ]); + }); + + it('should log with none', () => { + const testLogger = diagLogLevelFilter( + DiagLogLevel.NONE, + diagLoggerAdapter(dummyLogger) + ); + + testLogger.terminal('terminal called %s', 'param1'); + assert.deepStrictEqual(terminalCalledArgs, null); + testLogger.critical('critical called %s', 'param1'); + assert.deepStrictEqual(criticalCalledArgs, null); + testLogger.error('error called %s', 'param1'); + assert.deepStrictEqual(errorCalledArgs, null); + testLogger.warn('warn called %s', 'param1'); + assert.deepStrictEqual(warnCalledArgs, null); + testLogger.info('info called %s', 'param1'); + assert.deepStrictEqual(infoCalledArgs, null); + testLogger.debug('debug called %s', 'param1'); + assert.deepStrictEqual(debugCalledArgs, null); + testLogger.trace('trace called %s', 'param1'); + assert.deepStrictEqual(traceCalledArgs, null); + testLogger.forcedInfo('forcedInfo called %s', 'param1'); + assert.deepStrictEqual(forcedInfoCalledArgs, [ + 'forcedInfo called %s', + 'param1', + ]); + }); + + it('legacyLogger should log with default level', () => { + const testLogger = diagLogLevelFilter( + DiagLogLevel.ALL, + diagLoggerAdapter(legacyLogger) + ); + + testLogger.terminal('terminal called %s', 'param1'); + assert.deepStrictEqual(terminalCalledArgs, null); + assert.deepStrictEqual(errorCalledArgs, ['terminal called %s', 'param1']); + testLogger.critical('critical called %s', 'param1'); + assert.deepStrictEqual(criticalCalledArgs, null); + assert.deepStrictEqual(errorCalledArgs, ['critical called %s', 'param1']); + testLogger.error('error called %s', 'param1'); + assert.deepStrictEqual(errorCalledArgs, ['error called %s', 'param1']); + testLogger.warn('warn called %s', 'param1'); + assert.deepStrictEqual(warnCalledArgs, ['warn called %s', 'param1']); + testLogger.info('info called %s', 'param1'); + assert.deepStrictEqual(infoCalledArgs, ['info called %s', 'param1']); + testLogger.debug('debug called %s', 'param1'); + assert.deepStrictEqual(debugCalledArgs, ['debug called %s', 'param1']); + testLogger.trace('trace called %s', 'param1'); + assert.deepStrictEqual(traceCalledArgs, null); + assert.deepStrictEqual(debugCalledArgs, ['trace called %s', 'param1']); + testLogger.forcedInfo('forcedInfo called %s', 'param1'); + assert.deepStrictEqual(forcedInfoCalledArgs, null); + assert.deepStrictEqual(infoCalledArgs, [ + 'forcedInfo called %s', + 'param1', + ]); + }); + + it('legacyLogger should log with default level', () => { + const testLogger = diagLogLevelFilter( + DiagLogLevel.TRACE, + diagLoggerAdapter(legacyLogger) + ); + + testLogger.terminal('terminal called %s', 'param1'); + assert.deepStrictEqual(terminalCalledArgs, null); + assert.deepStrictEqual(errorCalledArgs, ['terminal called %s', 'param1']); + testLogger.critical('critical called %s', 'param1'); + assert.deepStrictEqual(criticalCalledArgs, null); + assert.deepStrictEqual(errorCalledArgs, ['critical called %s', 'param1']); + testLogger.error('error called %s', 'param1'); + assert.deepStrictEqual(errorCalledArgs, ['error called %s', 'param1']); + testLogger.warn('warn called %s', 'param1'); + assert.deepStrictEqual(warnCalledArgs, ['warn called %s', 'param1']); + testLogger.info('info called %s', 'param1'); + assert.deepStrictEqual(infoCalledArgs, ['info called %s', 'param1']); + testLogger.debug('debug called %s', 'param1'); + assert.deepStrictEqual(debugCalledArgs, ['debug called %s', 'param1']); + testLogger.trace('trace called %s', 'param1'); + assert.deepStrictEqual(traceCalledArgs, null); + assert.deepStrictEqual(debugCalledArgs, ['trace called %s', 'param1']); + testLogger.forcedInfo('forcedInfo called %s', 'param1'); + assert.deepStrictEqual(forcedInfoCalledArgs, null); + assert.deepStrictEqual(infoCalledArgs, [ + 'forcedInfo called %s', + 'param1', + ]); + }); + + it('legacyLogger should log with debug', () => { + const testLogger = diagLogLevelFilter( + DiagLogLevel.DEBUG, + diagLoggerAdapter(legacyLogger) + ); + + testLogger.terminal('terminal called %s', 'param1'); + assert.deepStrictEqual(terminalCalledArgs, null); + assert.deepStrictEqual(errorCalledArgs, ['terminal called %s', 'param1']); + testLogger.critical('critical called %s', 'param1'); + assert.deepStrictEqual(criticalCalledArgs, null); + assert.deepStrictEqual(errorCalledArgs, ['critical called %s', 'param1']); + testLogger.error('error called %s', 'param1'); + assert.deepStrictEqual(errorCalledArgs, ['error called %s', 'param1']); + testLogger.warn('warn called %s', 'param1'); + assert.deepStrictEqual(warnCalledArgs, ['warn called %s', 'param1']); + testLogger.info('info called %s', 'param1'); + assert.deepStrictEqual(infoCalledArgs, ['info called %s', 'param1']); + testLogger.debug('debug called %s', 'param1'); + assert.deepStrictEqual(debugCalledArgs, ['debug called %s', 'param1']); + testLogger.trace('trace called %s', 'param1'); + assert.deepStrictEqual(traceCalledArgs, null); + testLogger.forcedInfo('forcedInfo called %s', 'param1'); + assert.deepStrictEqual(forcedInfoCalledArgs, null); + assert.deepStrictEqual(infoCalledArgs, [ + 'forcedInfo called %s', + 'param1', + ]); + }); + + it('legacyLogger should log with info', () => { + const testLogger = diagLogLevelFilter( + DiagLogLevel.INFO, + diagLoggerAdapter(legacyLogger) + ); + + testLogger.terminal('terminal called %s', 'param1'); + assert.deepStrictEqual(terminalCalledArgs, null); + assert.deepStrictEqual(errorCalledArgs, ['terminal called %s', 'param1']); + testLogger.critical('critical called %s', 'param1'); + assert.deepStrictEqual(criticalCalledArgs, null); + assert.deepStrictEqual(errorCalledArgs, ['critical called %s', 'param1']); + testLogger.error('error called %s', 'param1'); + assert.deepStrictEqual(errorCalledArgs, ['error called %s', 'param1']); + testLogger.warn('warn called %s', 'param1'); + assert.deepStrictEqual(warnCalledArgs, ['warn called %s', 'param1']); + testLogger.info('info called %s', 'param1'); + assert.deepStrictEqual(infoCalledArgs, ['info called %s', 'param1']); + testLogger.debug('debug called %s', 'param1'); + assert.deepStrictEqual(debugCalledArgs, null); + testLogger.trace('trace called %s', 'param1'); + assert.deepStrictEqual(traceCalledArgs, null); + testLogger.forcedInfo('forcedInfo called %s', 'param1'); + assert.deepStrictEqual(forcedInfoCalledArgs, null); + assert.deepStrictEqual(infoCalledArgs, [ + 'forcedInfo called %s', + 'param1', + ]); + }); + + it('legacyLogger should log with warning', () => { + const testLogger = diagLogLevelFilter( + DiagLogLevel.WARN, + diagLoggerAdapter(legacyLogger) + ); + + testLogger.terminal('terminal called %s', 'param1'); + assert.deepStrictEqual(terminalCalledArgs, null); + assert.deepStrictEqual(errorCalledArgs, ['terminal called %s', 'param1']); + testLogger.critical('critical called %s', 'param1'); + assert.deepStrictEqual(criticalCalledArgs, null); + assert.deepStrictEqual(errorCalledArgs, ['critical called %s', 'param1']); + testLogger.error('error called %s', 'param1'); + assert.deepStrictEqual(errorCalledArgs, ['error called %s', 'param1']); + testLogger.warn('warn called %s', 'param1'); + assert.deepStrictEqual(warnCalledArgs, ['warn called %s', 'param1']); + testLogger.info('info called %s', 'param1'); + assert.deepStrictEqual(infoCalledArgs, null); + testLogger.debug('debug called %s', 'param1'); + assert.deepStrictEqual(debugCalledArgs, null); + testLogger.trace('trace called %s', 'param1'); + assert.deepStrictEqual(traceCalledArgs, null); + testLogger.forcedInfo('forcedInfo called %s', 'param1'); + assert.deepStrictEqual(forcedInfoCalledArgs, null); + assert.deepStrictEqual(infoCalledArgs, [ + 'forcedInfo called %s', + 'param1', + ]); + }); + + it('legacyLogger should log with error', () => { + const testLogger = diagLogLevelFilter( + DiagLogLevel.ERROR, + diagLoggerAdapter(legacyLogger) + ); + + testLogger.terminal('terminal called %s', 'param1'); + assert.deepStrictEqual(terminalCalledArgs, null); + assert.deepStrictEqual(errorCalledArgs, ['terminal called %s', 'param1']); + testLogger.critical('critical called %s', 'param1'); + assert.deepStrictEqual(criticalCalledArgs, null); + assert.deepStrictEqual(errorCalledArgs, ['critical called %s', 'param1']); + testLogger.error('error called %s', 'param1'); + assert.deepStrictEqual(errorCalledArgs, ['error called %s', 'param1']); + testLogger.warn('warn called %s', 'param1'); + assert.deepStrictEqual(warnCalledArgs, null); + testLogger.info('info called %s', 'param1'); + assert.deepStrictEqual(infoCalledArgs, null); + testLogger.debug('debug called %s', 'param1'); + assert.deepStrictEqual(debugCalledArgs, null); + testLogger.trace('trace called %s', 'param1'); + assert.deepStrictEqual(traceCalledArgs, null); + testLogger.forcedInfo('forcedInfo called %s', 'param1'); + assert.deepStrictEqual(forcedInfoCalledArgs, null); + assert.deepStrictEqual(infoCalledArgs, [ + 'forcedInfo called %s', + 'param1', + ]); + }); + + it('legacyLogger should log with critical', () => { + const testLogger = diagLogLevelFilter( + DiagLogLevel.CRITICAL, + diagLoggerAdapter(legacyLogger) + ); + + testLogger.terminal('terminal called %s', 'param1'); + assert.deepStrictEqual(terminalCalledArgs, null); + assert.deepStrictEqual(errorCalledArgs, ['terminal called %s', 'param1']); + testLogger.critical('critical called %s', 'param1'); + assert.deepStrictEqual(criticalCalledArgs, null); + assert.deepStrictEqual(errorCalledArgs, ['critical called %s', 'param1']); + testLogger.error('error called %s', 'param1'); + assert.deepStrictEqual(errorCalledArgs, ['critical called %s', 'param1']); + testLogger.warn('warn called %s', 'param1'); + assert.deepStrictEqual(warnCalledArgs, null); + testLogger.info('info called %s', 'param1'); + assert.deepStrictEqual(infoCalledArgs, null); + testLogger.debug('debug called %s', 'param1'); + assert.deepStrictEqual(debugCalledArgs, null); + testLogger.trace('trace called %s', 'param1'); + assert.deepStrictEqual(traceCalledArgs, null); + testLogger.forcedInfo('forcedInfo called %s', 'param1'); + assert.deepStrictEqual(forcedInfoCalledArgs, null); + assert.deepStrictEqual(infoCalledArgs, [ + 'forcedInfo called %s', + 'param1', + ]); + }); + + it('legacyLogger should log with terminal', () => { + const testLogger = diagLogLevelFilter( + DiagLogLevel.TERMINAL, + diagLoggerAdapter(legacyLogger) + ); + + testLogger.terminal('terminal called %s', 'param1'); + assert.deepStrictEqual(terminalCalledArgs, null); + assert.deepStrictEqual(errorCalledArgs, ['terminal called %s', 'param1']); + testLogger.critical('critical called %s', 'param1'); + assert.deepStrictEqual(criticalCalledArgs, null); + testLogger.error('error called %s', 'param1'); + assert.deepStrictEqual(errorCalledArgs, ['terminal called %s', 'param1']); + testLogger.warn('warn called %s', 'param1'); + assert.deepStrictEqual(warnCalledArgs, null); + testLogger.info('info called %s', 'param1'); + assert.deepStrictEqual(infoCalledArgs, null); + testLogger.debug('debug called %s', 'param1'); + assert.deepStrictEqual(debugCalledArgs, null); + testLogger.trace('trace called %s', 'param1'); + assert.deepStrictEqual(traceCalledArgs, null); + testLogger.forcedInfo('forcedInfo called %s', 'param1'); + assert.deepStrictEqual(forcedInfoCalledArgs, null); + assert.deepStrictEqual(infoCalledArgs, [ + 'forcedInfo called %s', + 'param1', + ]); + }); + + it('legacyLogger should log with none', () => { + const testLogger = diagLogLevelFilter( + DiagLogLevel.NONE, + diagLoggerAdapter(legacyLogger) + ); + + testLogger.terminal('terminal called %s', 'param1'); + assert.deepStrictEqual(terminalCalledArgs, null); + testLogger.critical('critical called %s', 'param1'); + assert.deepStrictEqual(criticalCalledArgs, null); + testLogger.error('error called %s', 'param1'); + assert.deepStrictEqual(errorCalledArgs, null); + testLogger.warn('warn called %s', 'param1'); + assert.deepStrictEqual(warnCalledArgs, null); + testLogger.info('info called %s', 'param1'); + assert.deepStrictEqual(infoCalledArgs, null); + testLogger.debug('debug called %s', 'param1'); + assert.deepStrictEqual(debugCalledArgs, null); + testLogger.trace('trace called %s', 'param1'); + assert.deepStrictEqual(traceCalledArgs, null); + testLogger.forcedInfo('forcedInfo called %s', 'param1'); + assert.deepStrictEqual(forcedInfoCalledArgs, null); + assert.deepStrictEqual(infoCalledArgs, [ + 'forcedInfo called %s', + 'param1', + ]); + }); + + it("validate adapter with null doesn't throw", () => { + const testLogger = diagLoggerAdapter(null); + assert.strictEqual(testLogger, null); + }); + + it("validate adapter with undefined doesn't throw", () => { + const testLogger = diagLoggerAdapter(undefined); + assert.strictEqual(testLogger, null); + }); + + it("validate adapter with null doesn't throw", () => { + const testLogger = diagLogLevelFilter( + DiagLogLevel.ALL, + diagLoggerAdapter(null) + ); + + testLogger.terminal('terminal called %s', 'param1'); + assert.deepStrictEqual(terminalCalledArgs, null); + testLogger.critical('critical called %s', 'param1'); + assert.deepStrictEqual(criticalCalledArgs, null); + testLogger.error('error called %s', 'param1'); + assert.deepStrictEqual(errorCalledArgs, null); + testLogger.warn('warn called %s', 'param1'); + assert.deepStrictEqual(warnCalledArgs, null); + testLogger.info('info called %s', 'param1'); + assert.deepStrictEqual(infoCalledArgs, null); + testLogger.debug('debug called %s', 'param1'); + assert.deepStrictEqual(debugCalledArgs, null); + testLogger.trace('trace called %s', 'param1'); + assert.deepStrictEqual(traceCalledArgs, null); + testLogger.forcedInfo('forcedInfo called %s', 'param1'); + assert.deepStrictEqual(forcedInfoCalledArgs, null); + assert.deepStrictEqual(infoCalledArgs, null); + }); + + it("validate with null doesn't throw", () => { + const testLogger = diagLogLevelFilter(DiagLogLevel.ALL, null); + + testLogger.terminal('terminal called %s', 'param1'); + assert.deepStrictEqual(terminalCalledArgs, null); + testLogger.critical('critical called %s', 'param1'); + assert.deepStrictEqual(criticalCalledArgs, null); + testLogger.error('error called %s', 'param1'); + assert.deepStrictEqual(errorCalledArgs, null); + testLogger.warn('warn called %s', 'param1'); + assert.deepStrictEqual(warnCalledArgs, null); + testLogger.info('info called %s', 'param1'); + assert.deepStrictEqual(infoCalledArgs, null); + testLogger.debug('debug called %s', 'param1'); + assert.deepStrictEqual(debugCalledArgs, null); + testLogger.trace('trace called %s', 'param1'); + assert.deepStrictEqual(traceCalledArgs, null); + testLogger.forcedInfo('forcedInfo called %s', 'param1'); + assert.deepStrictEqual(forcedInfoCalledArgs, null); + assert.deepStrictEqual(infoCalledArgs, null); + }); + it("validate adapter with undefined doesn't throw", () => { + const testLogger = diagLogLevelFilter( + DiagLogLevel.ALL, + diagLoggerAdapter(undefined) + ); + + testLogger.terminal('terminal called %s', 'param1'); + assert.deepStrictEqual(terminalCalledArgs, null); + testLogger.critical('critical called %s', 'param1'); + assert.deepStrictEqual(criticalCalledArgs, null); + testLogger.error('error called %s', 'param1'); + assert.deepStrictEqual(errorCalledArgs, null); + testLogger.warn('warn called %s', 'param1'); + assert.deepStrictEqual(warnCalledArgs, null); + testLogger.info('info called %s', 'param1'); + assert.deepStrictEqual(infoCalledArgs, null); + testLogger.debug('debug called %s', 'param1'); + assert.deepStrictEqual(debugCalledArgs, null); + testLogger.trace('trace called %s', 'param1'); + assert.deepStrictEqual(traceCalledArgs, null); + testLogger.forcedInfo('forcedInfo called %s', 'param1'); + assert.deepStrictEqual(forcedInfoCalledArgs, null); + assert.deepStrictEqual(infoCalledArgs, null); + }); + + it("validate with undefined doesn't throw", () => { + const testLogger = diagLogLevelFilter(DiagLogLevel.ALL, undefined); + + testLogger.terminal('terminal called %s', 'param1'); + assert.deepStrictEqual(terminalCalledArgs, null); + testLogger.critical('critical called %s', 'param1'); + assert.deepStrictEqual(criticalCalledArgs, null); + testLogger.error('error called %s', 'param1'); + assert.deepStrictEqual(errorCalledArgs, null); + testLogger.warn('warn called %s', 'param1'); + assert.deepStrictEqual(warnCalledArgs, null); + testLogger.info('info called %s', 'param1'); + assert.deepStrictEqual(infoCalledArgs, null); + testLogger.debug('debug called %s', 'param1'); + assert.deepStrictEqual(debugCalledArgs, null); + testLogger.trace('trace called %s', 'param1'); + assert.deepStrictEqual(traceCalledArgs, null); + testLogger.forcedInfo('forcedInfo called %s', 'param1'); + assert.deepStrictEqual(forcedInfoCalledArgs, null); + assert.deepStrictEqual(infoCalledArgs, null); + }); + + it('should not throw even when legacy logger is invalid', () => { + const invalidConsole = { + debug: 1, + warn: 2, + error: 3, + trace: 4, + info: 5, + log: 6, + }; + + const testLogger = diagLogLevelFilter( + DiagLogLevel.ALL, + diagLoggerAdapter(invalidConsole as any) + ); + + testLogger.terminal('terminal called %s', 'param1'); + assert.deepStrictEqual(terminalCalledArgs, null); + testLogger.critical('critical called %s', 'param1'); + assert.deepStrictEqual(criticalCalledArgs, null); + testLogger.error('error called %s', 'param1'); + assert.deepStrictEqual(errorCalledArgs, null); + testLogger.warn('warn called %s', 'param1'); + assert.deepStrictEqual(warnCalledArgs, null); + testLogger.info('info called %s', 'param1'); + assert.deepStrictEqual(infoCalledArgs, null); + testLogger.debug('debug called %s', 'param1'); + assert.deepStrictEqual(debugCalledArgs, null); + testLogger.trace('trace called %s', 'param1'); + assert.deepStrictEqual(traceCalledArgs, null); + testLogger.forcedInfo('forcedInfo called %s', 'param1'); + assert.deepStrictEqual(forcedInfoCalledArgs, null); + assert.deepStrictEqual(infoCalledArgs, null); + }); + + it('should not throw even when DiagLogger is invalid', () => { + const invalidConsole = { + debug: 1, + warn: 2, + error: 3, + trace: 4, + info: 5, + log: 6, + }; + + const testLogger = diagLogLevelFilter( + DiagLogLevel.ALL, + invalidConsole as any + ); + + testLogger.terminal('terminal called %s', 'param1'); + assert.deepStrictEqual(terminalCalledArgs, null); + testLogger.critical('critical called %s', 'param1'); + assert.deepStrictEqual(criticalCalledArgs, null); + testLogger.error('error called %s', 'param1'); + assert.deepStrictEqual(errorCalledArgs, null); + testLogger.warn('warn called %s', 'param1'); + assert.deepStrictEqual(warnCalledArgs, null); + testLogger.info('info called %s', 'param1'); + assert.deepStrictEqual(infoCalledArgs, null); + testLogger.debug('debug called %s', 'param1'); + assert.deepStrictEqual(debugCalledArgs, null); + testLogger.trace('trace called %s', 'param1'); + assert.deepStrictEqual(traceCalledArgs, null); + testLogger.forcedInfo('forcedInfo called %s', 'param1'); + assert.deepStrictEqual(forcedInfoCalledArgs, null); + assert.deepStrictEqual(infoCalledArgs, null); + }); + + it('A Noop logger should implement all functions and not throw when called', () => { + const testLogger = noopDiagLogger(); + + assert.ok(typeof testLogger.terminal, 'function'); + testLogger.terminal('terminal called %s', 'param1'); + assert.ok(typeof testLogger.critical, 'function'); + testLogger.critical('critical called %s', 'param1'); + assert.ok(typeof testLogger.error, 'function'); + testLogger.error('error called %s', 'param1'); + assert.ok(typeof testLogger.warn, 'function'); + testLogger.warn('warn called %s', 'param1'); + assert.ok(typeof testLogger.info, 'function'); + testLogger.info('info called %s', 'param1'); + assert.ok(typeof testLogger.debug, 'function'); + testLogger.debug('debug called %s', 'param1'); + assert.ok(typeof testLogger.trace, 'function'); + testLogger.trace('trace called %s', 'param1'); + assert.ok(typeof testLogger.forcedInfo, 'function'); + testLogger.forcedInfo('forcedInfo called %s', 'param1'); + }); + }); +}); diff --git a/packages/opentelemetry-core/src/common/ConsoleLogger.ts b/packages/opentelemetry-core/src/common/ConsoleLogger.ts index 5dfe9e59882..ec430363af1 100644 --- a/packages/opentelemetry-core/src/common/ConsoleLogger.ts +++ b/packages/opentelemetry-core/src/common/ConsoleLogger.ts @@ -18,6 +18,10 @@ import { Logger } from '@opentelemetry/api'; import { LogLevel } from './types'; import { getEnv } from '../platform'; +/** + * @deprecated This class will be removed prior to v1.0, use {@link DiagConsoleLogger} from the api. + * @see {@link DiagLogLevel} {@link diagLogLevelFilter} {@link DiagConsoleLogger} from the api + */ export class ConsoleLogger implements Logger { constructor(level: LogLevel = getEnv().OTEL_LOG_LEVEL) { if (level >= LogLevel.DEBUG) { diff --git a/packages/opentelemetry-core/src/common/logging-error-handler.ts b/packages/opentelemetry-core/src/common/logging-error-handler.ts index 5925f4510bb..d89055803d5 100644 --- a/packages/opentelemetry-core/src/common/logging-error-handler.ts +++ b/packages/opentelemetry-core/src/common/logging-error-handler.ts @@ -14,9 +14,14 @@ * limitations under the License. */ -import { Logger, Exception } from '@opentelemetry/api'; -import { ConsoleLogger } from './ConsoleLogger'; -import { ErrorHandler, LogLevel } from './types'; +import { + Logger, + Exception, + DiagLogLevel, + DiagConsoleLogger, + diagLogLevelFilter, +} from '@opentelemetry/api'; +import { ErrorHandler } from './types'; /** * Returns a function that logs an error using the provided logger, or a @@ -24,7 +29,8 @@ import { ErrorHandler, LogLevel } from './types'; * @param {Logger} logger */ export function loggingErrorHandler(logger?: Logger): ErrorHandler { - logger = logger ?? new ConsoleLogger(LogLevel.ERROR); + logger = + logger ?? diagLogLevelFilter(DiagLogLevel.ERROR, new DiagConsoleLogger()); return (ex: Exception) => { logger!.error(stringifyException(ex)); }; diff --git a/packages/opentelemetry-core/src/common/types.ts b/packages/opentelemetry-core/src/common/types.ts index 6e973c6f806..8b543c4f0ba 100644 --- a/packages/opentelemetry-core/src/common/types.ts +++ b/packages/opentelemetry-core/src/common/types.ts @@ -16,11 +16,14 @@ import { Exception } from '@opentelemetry/api'; +/** @deprecated This enum will be removed prior to v1.0, use the {@link DiagLogLevel} + * @see {@link DiagLogLevel} from the api + */ export enum LogLevel { - ERROR, - WARN, - INFO, - DEBUG, + ERROR = 0, + WARN = 1, + INFO = 2, + DEBUG = 3, } /** From f26614ed530f4b637be4e3e551dea0b715eb9271 Mon Sep 17 00:00:00 2001 From: Nev Wylie <54870357+MSNev@users.noreply.github.com> Date: Wed, 27 Jan 2021 17:08:46 -0800 Subject: [PATCH 2/5] fix(test): ci environment doesn't handle replacing console with a mock --- .../test/diag/consoleLogger.test.ts | 224 ++++++++++-------- 1 file changed, 122 insertions(+), 102 deletions(-) diff --git a/packages/opentelemetry-api/test/diag/consoleLogger.test.ts b/packages/opentelemetry-api/test/diag/consoleLogger.test.ts index d3ba79de55e..5bad3b0c02e 100644 --- a/packages/opentelemetry-api/test/diag/consoleLogger.test.ts +++ b/packages/opentelemetry-api/test/diag/consoleLogger.test.ts @@ -32,6 +32,16 @@ describe('DiagConsoleLogger', () => { let errorCalledArgs: unknown; let logCalledArgs: unknown; + let canMockConsole = true; + + try { + // eslint-disable-next-line no-global-assign + console = origConsole; + } catch (ex) { + // Not supported on CI pipeline (works locally) + canMockConsole = false; + } + beforeEach(() => { // mock console.debug = (...args: unknown[]) => { @@ -62,8 +72,16 @@ describe('DiagConsoleLogger', () => { errorCalledArgs = null; logCalledArgs = null; traceCalledArgs = null; - // eslint-disable-next-line no-global-assign - console = origConsole; + + if (canMockConsole) { + try { + // eslint-disable-next-line no-global-assign + console = origConsole; + } catch (ex) { + // Not supported on CI pipeline + canMockConsole = false; + } + } console.debug = origDebug; console.info = origInfo; console.warn = origWarn; @@ -221,110 +239,112 @@ describe('DiagConsoleLogger', () => { ]); }); - it('should not throw even when console is not supported', () => { - (console as any) = undefined; - const consoleLogger = new DiagConsoleLogger(); - consoleLogger.terminal('terminal called %s', 'param1'); - assert.deepStrictEqual(errorCalledArgs, null); - consoleLogger.critical('critical called %s', 'param1'); - assert.deepStrictEqual(errorCalledArgs, null); - consoleLogger.error('error called %s', 'param1'); - assert.deepStrictEqual(errorCalledArgs, null); - consoleLogger.warn('warn called %s', 'param1'); - assert.deepStrictEqual(warnCalledArgs, null); - consoleLogger.info('info called %s', 'param1'); - assert.deepStrictEqual(infoCalledArgs, null); - consoleLogger.debug('debug called %s', 'param1'); - assert.deepStrictEqual(debugCalledArgs, null); - consoleLogger.trace('trace called %s', 'param1'); - assert.deepStrictEqual(traceCalledArgs, null); - assert.deepStrictEqual(logCalledArgs, null); - consoleLogger.forcedInfo('forcedInfo called %s', 'param1'); - assert.deepStrictEqual(infoCalledArgs, null); - }); + if (canMockConsole) { + it('should not throw even when console is not supported', () => { + (console as any) = undefined; + const consoleLogger = new DiagConsoleLogger(); + consoleLogger.terminal('terminal called %s', 'param1'); + assert.deepStrictEqual(errorCalledArgs, null); + consoleLogger.critical('critical called %s', 'param1'); + assert.deepStrictEqual(errorCalledArgs, null); + consoleLogger.error('error called %s', 'param1'); + assert.deepStrictEqual(errorCalledArgs, null); + consoleLogger.warn('warn called %s', 'param1'); + assert.deepStrictEqual(warnCalledArgs, null); + consoleLogger.info('info called %s', 'param1'); + assert.deepStrictEqual(infoCalledArgs, null); + consoleLogger.debug('debug called %s', 'param1'); + assert.deepStrictEqual(debugCalledArgs, null); + consoleLogger.trace('trace called %s', 'param1'); + assert.deepStrictEqual(traceCalledArgs, null); + assert.deepStrictEqual(logCalledArgs, null); + consoleLogger.forcedInfo('forcedInfo called %s', 'param1'); + assert.deepStrictEqual(infoCalledArgs, null); + }); - it('should not throw even when console is disabled after construction', () => { - const consoleLogger = new DiagConsoleLogger(); - (console as any) = undefined; - consoleLogger.terminal('terminal called %s', 'param1'); - assert.deepStrictEqual(errorCalledArgs, null); - consoleLogger.critical('critical called %s', 'param1'); - assert.deepStrictEqual(errorCalledArgs, null); - consoleLogger.error('error called %s', 'param1'); - assert.deepStrictEqual(errorCalledArgs, null); - consoleLogger.warn('warn called %s', 'param1'); - assert.deepStrictEqual(warnCalledArgs, null); - consoleLogger.info('info called %s', 'param1'); - assert.deepStrictEqual(infoCalledArgs, null); - consoleLogger.debug('debug called %s', 'param1'); - assert.deepStrictEqual(debugCalledArgs, null); - consoleLogger.trace('trace called %s', 'param1'); - assert.deepStrictEqual(traceCalledArgs, null); - assert.deepStrictEqual(logCalledArgs, null); - consoleLogger.forcedInfo('forcedInfo called %s', 'param1'); - assert.deepStrictEqual(infoCalledArgs, null); - }); + it('should not throw even when console is disabled after construction', () => { + const consoleLogger = new DiagConsoleLogger(); + (console as any) = undefined; + consoleLogger.terminal('terminal called %s', 'param1'); + assert.deepStrictEqual(errorCalledArgs, null); + consoleLogger.critical('critical called %s', 'param1'); + assert.deepStrictEqual(errorCalledArgs, null); + consoleLogger.error('error called %s', 'param1'); + assert.deepStrictEqual(errorCalledArgs, null); + consoleLogger.warn('warn called %s', 'param1'); + assert.deepStrictEqual(warnCalledArgs, null); + consoleLogger.info('info called %s', 'param1'); + assert.deepStrictEqual(infoCalledArgs, null); + consoleLogger.debug('debug called %s', 'param1'); + assert.deepStrictEqual(debugCalledArgs, null); + consoleLogger.trace('trace called %s', 'param1'); + assert.deepStrictEqual(traceCalledArgs, null); + assert.deepStrictEqual(logCalledArgs, null); + consoleLogger.forcedInfo('forcedInfo called %s', 'param1'); + assert.deepStrictEqual(infoCalledArgs, null); + }); - it('should not throw even when console is invalid after construction', () => { - const invalidConsole = { - debug: 1, - warn: 2, - error: 3, - trace: 4, - info: 5, - log: 6, - }; + it('should not throw even when console is invalid after construction', () => { + const invalidConsole = { + debug: 1, + warn: 2, + error: 3, + trace: 4, + info: 5, + log: 6, + }; - const consoleLogger = new DiagConsoleLogger(); - (console as any) = invalidConsole; - consoleLogger.terminal('terminal called %s', 'param1'); - assert.deepStrictEqual(errorCalledArgs, null); - consoleLogger.critical('critical called %s', 'param1'); - assert.deepStrictEqual(errorCalledArgs, null); - consoleLogger.error('error called %s', 'param1'); - assert.deepStrictEqual(errorCalledArgs, null); - consoleLogger.warn('warn called %s', 'param1'); - assert.deepStrictEqual(warnCalledArgs, null); - consoleLogger.info('info called %s', 'param1'); - assert.deepStrictEqual(infoCalledArgs, null); - consoleLogger.debug('debug called %s', 'param1'); - assert.deepStrictEqual(debugCalledArgs, null); - consoleLogger.trace('trace called %s', 'param1'); - assert.deepStrictEqual(traceCalledArgs, null); - assert.deepStrictEqual(logCalledArgs, null); - consoleLogger.forcedInfo('forcedInfo called %s', 'param1'); - assert.deepStrictEqual(infoCalledArgs, null); - }); + const consoleLogger = new DiagConsoleLogger(); + (console as any) = invalidConsole; + consoleLogger.terminal('terminal called %s', 'param1'); + assert.deepStrictEqual(errorCalledArgs, null); + consoleLogger.critical('critical called %s', 'param1'); + assert.deepStrictEqual(errorCalledArgs, null); + consoleLogger.error('error called %s', 'param1'); + assert.deepStrictEqual(errorCalledArgs, null); + consoleLogger.warn('warn called %s', 'param1'); + assert.deepStrictEqual(warnCalledArgs, null); + consoleLogger.info('info called %s', 'param1'); + assert.deepStrictEqual(infoCalledArgs, null); + consoleLogger.debug('debug called %s', 'param1'); + assert.deepStrictEqual(debugCalledArgs, null); + consoleLogger.trace('trace called %s', 'param1'); + assert.deepStrictEqual(traceCalledArgs, null); + assert.deepStrictEqual(logCalledArgs, null); + consoleLogger.forcedInfo('forcedInfo called %s', 'param1'); + assert.deepStrictEqual(infoCalledArgs, null); + }); - it('should not throw even when console is invalid before construction', () => { - const invalidConsole = { - debug: 1, - warn: 2, - error: 3, - trace: 4, - info: 5, - log: 6, - }; + it('should not throw even when console is invalid before construction', () => { + const invalidConsole = { + debug: 1, + warn: 2, + error: 3, + trace: 4, + info: 5, + log: 6, + }; - (console as any) = invalidConsole; - const consoleLogger = new DiagConsoleLogger(); - consoleLogger.terminal('terminal called %s', 'param1'); - assert.deepStrictEqual(errorCalledArgs, null); - consoleLogger.critical('critical called %s', 'param1'); - assert.deepStrictEqual(errorCalledArgs, null); - consoleLogger.error('error called %s', 'param1'); - assert.deepStrictEqual(errorCalledArgs, null); - consoleLogger.warn('warn called %s', 'param1'); - assert.deepStrictEqual(warnCalledArgs, null); - consoleLogger.info('info called %s', 'param1'); - assert.deepStrictEqual(infoCalledArgs, null); - consoleLogger.debug('debug called %s', 'param1'); - assert.deepStrictEqual(debugCalledArgs, null); - consoleLogger.trace('trace called %s', 'param1'); - assert.deepStrictEqual(traceCalledArgs, null); - assert.deepStrictEqual(logCalledArgs, null); - consoleLogger.forcedInfo('forcedInfo called %s', 'param1'); - assert.deepStrictEqual(infoCalledArgs, null); - }); + (console as any) = invalidConsole; + const consoleLogger = new DiagConsoleLogger(); + consoleLogger.terminal('terminal called %s', 'param1'); + assert.deepStrictEqual(errorCalledArgs, null); + consoleLogger.critical('critical called %s', 'param1'); + assert.deepStrictEqual(errorCalledArgs, null); + consoleLogger.error('error called %s', 'param1'); + assert.deepStrictEqual(errorCalledArgs, null); + consoleLogger.warn('warn called %s', 'param1'); + assert.deepStrictEqual(warnCalledArgs, null); + consoleLogger.info('info called %s', 'param1'); + assert.deepStrictEqual(infoCalledArgs, null); + consoleLogger.debug('debug called %s', 'param1'); + assert.deepStrictEqual(debugCalledArgs, null); + consoleLogger.trace('trace called %s', 'param1'); + assert.deepStrictEqual(traceCalledArgs, null); + assert.deepStrictEqual(logCalledArgs, null); + consoleLogger.forcedInfo('forcedInfo called %s', 'param1'); + assert.deepStrictEqual(infoCalledArgs, null); + }); + } }); }); From 7c834ef218167808dacf415668e9f9dc670bc1ca Mon Sep 17 00:00:00 2001 From: Nev Wylie <54870357+MSNev@users.noreply.github.com> Date: Wed, 3 Feb 2021 15:52:00 -0800 Subject: [PATCH 3/5] fix: address review comments summary of changes - rename trace -> verbose - make log level NONE block all logging - use factory name for Noop logger - refactor tests to use arrays -- reducing test size - remove diagLogAdapterfix: address review changes summary - rename trace -> verbose - make log level NONE block all logging - use factory name for Noop logger - refactor tests to use arrays -- reducing test size - remove diagLogAdapter --- benchmark/tracer.js | 2 +- packages/opentelemetry-api/src/api/diag.ts | 52 +- .../src/diag/consoleLogger.ts | 38 +- .../opentelemetry-api/src/diag/logLevel.ts | 70 +- packages/opentelemetry-api/src/diag/logger.ts | 121 +-- packages/opentelemetry-api/src/index.ts | 5 +- .../opentelemetry-api/src/trace/NoopLogger.ts | 2 +- .../test/diag/consoleLogger.test.ts | 444 +++------ .../test/diag/logLevel.test.ts | 894 ++++++----------- .../test/diag/logger.test.ts | 901 ++---------------- .../src/common/logging-error-handler.ts | 5 +- 11 files changed, 635 insertions(+), 1899 deletions(-) diff --git a/benchmark/tracer.js b/benchmark/tracer.js index a792d19260c..27ba3520c63 100644 --- a/benchmark/tracer.js +++ b/benchmark/tracer.js @@ -4,7 +4,7 @@ const benchmark = require('./benchmark'); const opentelemetry = require('../packages/opentelemetry-api'); const { BasicTracerProvider, BatchSpanProcessor, InMemorySpanExporter, SimpleSpanProcessor } = require('../packages/opentelemetry-tracing'); -const diagLogger = opentelemetry.noopDiagLogger(); +const diagLogger = opentelemetry.createNoopDiagLogger(); const setups = [ { diff --git a/packages/opentelemetry-api/src/api/diag.ts b/packages/opentelemetry-api/src/api/diag.ts index 1b4ebc5470b..d55a5caba56 100644 --- a/packages/opentelemetry-api/src/api/diag.ts +++ b/packages/opentelemetry-api/src/api/diag.ts @@ -14,8 +14,13 @@ * limitations under the License. */ -import { DiagLogger, DiagLogFunction, noopDiagLogger } from '../diag/logger'; -import { DiagLogLevel, diagLogLevelFilter } from '../diag/logLevel'; +import { + DiagLogger, + DiagLogFunction, + createNoopDiagLogger, + diagLoggerFunctions, +} from '../diag/logger'; +import { DiagLogLevel, createLogLevelDiagLogger } from '../diag/logLevel'; import { API_BACKWARDS_COMPATIBILITY_VERSION, GLOBAL_DIAG_LOGGER_API_KEY, @@ -25,7 +30,7 @@ import { /** Internal simple Noop Diag API that returns a noop logger and does not allow any changes */ function noopDiagApi(): DiagAPI { - const noopApi = noopDiagLogger() as DiagAPI; + const noopApi = createNoopDiagLogger() as DiagAPI; noopApi.getLogger = () => noopApi; noopApi.setLogger = noopApi.getLogger; @@ -40,7 +45,7 @@ function noopDiagApi(): DiagAPI { */ export class DiagAPI implements DiagLogger { /** Get the singleton instance of the DiagAPI API */ - public static inst(): DiagAPI { + public static instance(): DiagAPI { let theInst = null; if (_global[GLOBAL_DIAG_LOGGER_API_KEY]) { // Looks like a previous instance was set, so try and fetch it @@ -61,19 +66,21 @@ export class DiagAPI implements DiagLogger { return theInst; } - /** Private internal constructor - * @private */ + /** + * Private internal constructor + * @private + */ private constructor() { let _logLevel: DiagLogLevel = DiagLogLevel.INFO; let _filteredLogger: DiagLogger | null; - let _logger: DiagLogger = noopDiagLogger(); + let _logger: DiagLogger = createNoopDiagLogger(); function _logProxy(funcName: keyof DiagLogger): DiagLogFunction { return function () { const orgArguments = arguments as unknown; const theLogger = _filteredLogger || _logger; const theFunc = theLogger[funcName]; - if (theFunc && typeof theFunc === 'function') { + if (typeof theFunc === 'function') { return theFunc.apply( theLogger, orgArguments as Parameters @@ -96,8 +103,8 @@ export class DiagAPI implements DiagLogger { const prevLogger = _logger; if (prevLogger !== logger && logger !== self) { // Simple special case to avoid any possible infinite recursion on the logging functions - _logger = logger || noopDiagLogger(); - _filteredLogger = diagLogLevelFilter(_logLevel, _logger); + _logger = logger || createNoopDiagLogger(); + _filteredLogger = createLogLevelDiagLogger(_logLevel, _logger); } return prevLogger; @@ -107,34 +114,25 @@ export class DiagAPI implements DiagLogger { if (maxLogLevel !== _logLevel) { _logLevel = maxLogLevel; if (_logger) { - _filteredLogger = diagLogLevelFilter(maxLogLevel, _logger); + _filteredLogger = createLogLevelDiagLogger(maxLogLevel, _logger); } } }; - // DiagLogger implementation - const theFuncs: Array = [ - 'trace', - 'debug', - 'info', - 'warn', - 'error', - 'critical', - 'terminal', - 'forcedInfo', - ]; - for (let lp = 0; lp < theFuncs.length; lp++) { - const name = theFuncs[lp]; + for (let i = 0; i < diagLoggerFunctions.length; i++) { + const name = diagLoggerFunctions[i]; self[name] = _logProxy(name); } } - /** Return the currently configured logger instance, if no logger has been configured + /** + * Return the currently configured logger instance, if no logger has been configured * it will return itself so any log level filtering will still be applied in this case. */ public getLogger!: () => DiagLogger; - /** Set the DiagLogger instance + /** + * Set the DiagLogger instance * @param logger - The DiagLogger instance to set as the default logger * @returns The previously registered DiagLogger */ @@ -144,7 +142,7 @@ export class DiagAPI implements DiagLogger { public setLogLevel!: (maxLogLevel: DiagLogLevel) => void; // DiagLogger implementation - public trace!: DiagLogFunction; + public verbose!: DiagLogFunction; public debug!: DiagLogFunction; public info!: DiagLogFunction; public warn!: DiagLogFunction; diff --git a/packages/opentelemetry-api/src/diag/consoleLogger.ts b/packages/opentelemetry-api/src/diag/consoleLogger.ts index 877b4a5fa3f..e720dcf84b4 100644 --- a/packages/opentelemetry-api/src/diag/consoleLogger.ts +++ b/packages/opentelemetry-api/src/diag/consoleLogger.ts @@ -23,7 +23,7 @@ const consoleMap: { n: keyof DiagLogger; c: keyof Console }[] = [ { n: 'warn', c: 'warn' }, { n: 'info', c: 'info' }, { n: 'debug', c: 'debug' }, - { n: 'trace', c: 'trace' }, + { n: 'verbose', c: 'trace' }, { n: 'forcedInfo', c: 'info' }, ]; @@ -40,35 +40,32 @@ export class DiagConsoleLogger implements DiagLogger { if (console) { // Some environments only expose the console when the F12 developer console is open let theFunc = console[funcName]; - if (!theFunc) { + if (typeof theFunc !== 'function') { // Not all environments support all functions theFunc = console.log; } // One last final check - if (theFunc && typeof theFunc === 'function') { + if (typeof theFunc === 'function') { return theFunc.apply(console, orgArguments); } } }; } - for (let lp = 0; lp < consoleMap.length; lp++) { - const name = consoleMap[lp].n; - let consoleFunc = consoleMap[lp].c; - if (console && !console[consoleFunc]) { - consoleFunc = 'log'; - } - this[name] = _consoleFunc(consoleFunc); + for (let i = 0; i < consoleMap.length; i++) { + this[consoleMap[i].n] = _consoleFunc(consoleMap[i].c); } } - /** Log a terminal situation that would cause the API to completely fail to initialize, + /** + * Log a terminal situation that would cause the API to completely fail to initialize, * if this type of message is logged functionality of the API is not expected to be functional. */ public terminal!: DiagLogFunction; - /** Log a critical error that NEEDS to be addressed, functionality of the component that emits + /** + * Log a critical error that NEEDS to be addressed, functionality of the component that emits * this log detail may non-functional. While the overall API may be. */ public critical!: DiagLogFunction; @@ -76,33 +73,38 @@ export class DiagConsoleLogger implements DiagLogger { /** Log an error scenario that was not expected and caused the requested operation to fail. */ public error!: DiagLogFunction; - /** Log a warning scenario to inform the developer of an issues that should be investigated. + /** + * Log a warning scenario to inform the developer of an issues that should be investigated. * The requested operation may or may not have succeeded or completed. */ public warn!: DiagLogFunction; - /** Log a general informational message, this should not affect functionality. + /** + * Log a general informational message, this should not affect functionality. * This is also the default logging level so this should NOT be used for logging * debugging level information. */ public info!: DiagLogFunction; - /** Log a general debug message that can be useful for identifying a failure. + /** + * Log a general debug message that can be useful for identifying a failure. * Information logged at this level may include diagnostic details that would * help identify a failure scenario. Useful scenarios would be to log the execution * order of async operations */ public debug!: DiagLogFunction; - /** Log a detailed (verbose) trace level logging that can be used to identify failures + /** + * Log a detailed (verbose) trace level logging that can be used to identify failures * where debug level logging would be insufficient, this level of tracing can include * input and output parameters and as such may include PII information passing through * the API. As such it is recommended that this level of tracing should not be enabled * in a production environment. */ - public trace!: DiagLogFunction; + public verbose!: DiagLogFunction; - /** Log a general informational message that should always be logged regardless of the + /** + * Log a general informational message that should always be logged regardless of the * current {@Link DiagLogLevel) and configured filtering level. This type of logging is * useful for logging component startup and version information without causing additional * general informational messages when the logging level is set to DiagLogLevel.WARN or lower. diff --git a/packages/opentelemetry-api/src/diag/logLevel.ts b/packages/opentelemetry-api/src/diag/logLevel.ts index 06d3aba8e97..7ac5eb17774 100644 --- a/packages/opentelemetry-api/src/diag/logLevel.ts +++ b/packages/opentelemetry-api/src/diag/logLevel.ts @@ -15,7 +15,8 @@ */ import { DiagAPI } from '../api/diag'; -import { DiagLogger, DiagLogFunction } from './logger'; +import { Logger } from '../common/Logger'; +import { DiagLogger, DiagLogFunction, createNoopDiagLogger } from './logger'; /** * Defines the available internal logging levels for the diagnostic logger, the numeric values @@ -26,12 +27,14 @@ export enum DiagLogLevel { /** DIagnostic Logging level setting to disable all logging (except and forced logs) */ NONE = -99, - /** Identifies a terminal situation that would cause the API to completely fail to initialize, + /** + * Identifies a terminal situation that would cause the API to completely fail to initialize, * if this type of error is logged functionality of the API is not expected to be functional. */ TERMINAL = -2, - /** Identifies a critical error that needs to be addressed, functionality of the component + /** + * Identifies a critical error that needs to be addressed, functionality of the component * that emits this log detail may non-functional. */ CRITICAL = -1, @@ -48,10 +51,11 @@ export enum DiagLogLevel { /** General debug log message */ DEBUG = 3, - /** Detailed trace level logging should only be used for development, should only be set + /** + * Detailed trace level logging should only be used for development, should only be set * in a development environment. */ - TRACE = 4, + VERBOSE = 4, /** Used to set the logging level to include all logging */ ALL = 9999, @@ -59,13 +63,26 @@ export enum DiagLogLevel { /** * This is equivalent to: - * type LogLevelString = 'NONE' | TERMINAL' | 'CRITICAL' | 'ERROR' | 'WARN' | 'INFO' | 'DEBUG' | 'TRACE' | 'ALL'; + * type LogLevelString = 'NONE' | TERMINAL' | 'CRITICAL' | 'ERROR' | 'WARN' | 'INFO' | 'DEBUG' | 'VERBOSE' | 'ALL'; */ export type DiagLogLevelString = keyof typeof DiagLogLevel; /** - * Mapping from DiagLogger function name to logging level + * Mapping from DiagLogger function name to Legacy Logger function used if + * the logger instance doesn't have the DiagLogger function */ +const fallbackLoggerFuncMap: { [n: string]: keyof Logger } = { + terminal: 'error', + critical: 'error', + error: 'error', + warn: 'warn', + info: 'info', + debug: 'debug', + verbose: 'debug', + forcedInfo: 'info', +}; + +/** Mapping from DiagLogger function name to logging level. */ const levelMap: { n: keyof DiagLogger; l: DiagLogLevel; f?: boolean }[] = [ { n: 'terminal', l: DiagLogLevel.TERMINAL }, { n: 'critical', l: DiagLogLevel.CRITICAL }, @@ -73,21 +90,15 @@ const levelMap: { n: keyof DiagLogger; l: DiagLogLevel; f?: boolean }[] = [ { n: 'warn', l: DiagLogLevel.WARN }, { n: 'info', l: DiagLogLevel.INFO }, { n: 'debug', l: DiagLogLevel.DEBUG }, - { n: 'trace', l: DiagLogLevel.TRACE }, + { n: 'verbose', l: DiagLogLevel.VERBOSE }, { n: 'forcedInfo', l: DiagLogLevel.INFO, f: true }, ]; /** - * An Immutable Diagnostic logger that limits the reported diagnostic log messages to those at the - * maximum logging level or lower. - * This can be useful to reduce the amount of logging used for a specific component based on any - * local configuration - */ - -/** - * Create a Diagnostic filter logger which limits the logged messages to the defined provided maximum - * logging level or lower. This can be useful to reduce the amount of logging used for the system or - * for a specific component based on any local configuration. + * Create a Diagnostic logger which limits the messages that are logged via the wrapped logger based on whether the + * message has a {@link DiagLogLevel} equal to the maximum logging level or lower, unless the {@link DiagLogLevel} is + * NONE which will return a noop logger instance. This can be useful to reduce the amount of logging used for the + * system or for a specific component based on any local configuration. * If you don't supply a logger it will use the global api.diag as the destination which will use the * current logger and any filtering it may have applied. * To avoid / bypass any global level filtering you should pass the current logger returned via @@ -98,20 +109,24 @@ const levelMap: { n: keyof DiagLogger; l: DiagLogLevel; f?: boolean }[] = [ * @returns {DiagLogger} */ -export function diagLogLevelFilter( +export function createLogLevelDiagLogger( maxLevel: DiagLogLevel, logger?: DiagLogger | null ): DiagLogger { - if (!logger) { - logger = DiagAPI.inst() as DiagLogger; - } - if (maxLevel < DiagLogLevel.NONE) { maxLevel = DiagLogLevel.NONE; } else if (maxLevel > DiagLogLevel.ALL) { maxLevel = DiagLogLevel.ALL; } + if (maxLevel === DiagLogLevel.NONE) { + return createNoopDiagLogger(); + } + + if (!logger) { + logger = DiagAPI.instance().getLogger(); + } + function _filterFunc( theLogger: DiagLogger, funcName: keyof DiagLogger, @@ -121,7 +136,8 @@ export function diagLogLevelFilter( if (isForced || maxLevel >= theLevel) { return function () { const orgArguments = arguments as unknown; - const theFunc = theLogger[funcName]; + const theFunc = + theLogger[funcName] || theLogger[fallbackLoggerFuncMap[funcName]]; if (theFunc && typeof theFunc === 'function') { return theFunc.apply( logger, @@ -134,9 +150,9 @@ export function diagLogLevelFilter( } const newLogger = {} as DiagLogger; - for (let lp = 0; lp < levelMap.length; lp++) { - const name = levelMap[lp].n; - newLogger[name] = _filterFunc(logger, name, levelMap[lp].l, levelMap[lp].f); + for (let i = 0; i < levelMap.length; i++) { + const name = levelMap[i].n; + newLogger[name] = _filterFunc(logger, name, levelMap[i].l, levelMap[i].f); } return newLogger; diff --git a/packages/opentelemetry-api/src/diag/logger.ts b/packages/opentelemetry-api/src/diag/logger.ts index aff46a4fb09..79d31317ccd 100644 --- a/packages/opentelemetry-api/src/diag/logger.ts +++ b/packages/opentelemetry-api/src/diag/logger.ts @@ -16,7 +16,8 @@ import { Logger } from '../common/Logger'; -/** Defines a type which can be used for as a parameter without breaking backward +/** + * Defines a type which can be used for as a parameter without breaking backward * compatibility. The {@link Logger} reference will be removed with the removal * of the Logger definition, this can be used as a replacement for functions * that are currently passing Logger references during migration to minimize @@ -26,70 +27,82 @@ export type OptionalDiagLogger = Logger | DiagLogger | null | undefined; export type DiagLogFunction = (message: string, ...args: unknown[]) => void; -/** Defines an internal diagnostic logger interface which is used to log internal diagnostic +/** + * Defines an internal diagnostic logger interface which is used to log internal diagnostic * messages, you can set the default diagnostic logger via the {@link DiagAPI} setLogger function. * API provided implementations include :- - * - a No-Op {@link noopDiagLogger} + * - a No-Op {@link createNoopDiagLogger} * - a {@link DiagLogLevel} filtering wrapper {@link diagLogLevelFilter} * - a general Console {@link DiagConsoleLogger} version. */ export interface DiagLogger { - /** Log a terminal situation that would cause the API to completely fail to initialize, + /** + * Log a terminal situation that would cause the API to completely fail to initialize, * if this type of message is logged functionality of the API is not expected to be functional. */ terminal: DiagLogFunction; - /** Log a critical error that NEEDS to be addressed, functionality of the component that emits - * this log detail may non-functional. While the overall API may be. + /** + * Log a critical error that NEEDS to be addressed, functionality of the component that emits + * this log detail may be limited or non-functional depending on when this message is emitted. + * Unlike terminal message, it is expected that the overall API may still be functional, again + * depending on what component and when this message is emitted. */ critical: DiagLogFunction; /** Log an error scenario that was not expected and caused the requested operation to fail. */ error: DiagLogFunction; - /** Log a warning scenario to inform the developer of an issues that should be investigated. + /** + * Log a warning scenario to inform the developer of an issues that should be investigated. * The requested operation may or may not have succeeded or completed. */ warn: DiagLogFunction; - /** Log a general informational message, this should not affect functionality. + /** + * Log a general informational message, this should not affect functionality. * This is also the default logging level so this should NOT be used for logging * debugging level information. */ info: DiagLogFunction; - /** Log a general debug message that can be useful for identifying a failure. + /** + * Log a general debug message that can be useful for identifying a failure. * Information logged at this level may include diagnostic details that would - * help identify a failure scenario. Useful scenarios would be to log the execution - * order of async operations + * help identify a failure scenario. + * For example: Logging the order of execution of async operations. */ debug: DiagLogFunction; - /** Log a detailed (verbose) trace level logging that can be used to identify failures + /** + * Log a detailed (verbose) trace level logging that can be used to identify failures * where debug level logging would be insufficient, this level of tracing can include * input and output parameters and as such may include PII information passing through * the API. As such it is recommended that this level of tracing should not be enabled * in a production environment. */ - trace: DiagLogFunction; - - /** Log a general informational message that should always be logged regardless of the - * current {@Link DiagLogLevel) and configured filtering level. This type of logging is - * useful for logging component startup and version information without causing additional - * general informational messages when the logging level is set to DiagLogLevel.WARN or lower. + verbose: DiagLogFunction; + + /** + * Log a general informational message that should always be logged regardless of the + * current or configured logging level {@Link DiagLogLevel} except when the level is set + * to {@Link DiagLogLevel.NONE). This type of logging is useful for logging component + * startup and version information without causing additional general informational messages + * when the logging level is set to DiagLogLevel.WARN or lower. */ forcedInfo: DiagLogFunction; } -const loggerMapFuncs: { d: keyof DiagLogger; l: keyof Logger }[] = [ - { d: 'trace', l: 'debug' }, - { d: 'debug', l: 'debug' }, - { d: 'info', l: 'info' }, - { d: 'warn', l: 'warn' }, - { d: 'error', l: 'error' }, - { d: 'critical', l: 'error' }, - { d: 'terminal', l: 'error' }, - { d: 'forcedInfo', l: 'info' }, +// DiagLogger implementation +export const diagLoggerFunctions: Array = [ + 'verbose', + 'debug', + 'info', + 'warn', + 'error', + 'critical', + 'terminal', + 'forcedInfo', ]; function noopLogFunction() {} @@ -99,59 +112,11 @@ function noopLogFunction() {} * @implements {@link DiagLogger} * @returns {DiagLogger} */ -export function noopDiagLogger(): DiagLogger { - const diagLogger = {} as DiagLogger; - - for (let lp = 0; lp < loggerMapFuncs.length; lp++) { - const map = loggerMapFuncs[lp]; - diagLogger[map.d] = noopLogFunction; - } - - return diagLogger; -} - -/** - * @deprecated This helper will return either the original passed logger if it implements {@link DiagLogger} a - * wrapped instance if it only implements {@link Logger} or null if it's null, undefined. - * This helper will be removed as part of the {@link Logger} deprecation, please use {@link DiagLogger} from the api. - * @see {@link DiagLogLevel} and {@link DiagLogger} - * @returns The passed Logger wrapped as a DiagLogger or null if no Logger was supplied. - */ -export function diagLoggerAdapter( - logger?: OptionalDiagLogger -): DiagLogger | null | undefined { - if (!logger) { - return null; - } - - if (typeof (logger as DiagLogger).forcedInfo === 'function') { - // already looks like a DiagLogger; - return logger as DiagLogger; - } - - function _mapToLogger( - theLogger: Logger, - funcName: keyof Logger - ): DiagLogFunction { - const theFunc = theLogger[funcName]; - if (theFunc && typeof theFunc === 'function') { - return function () { - const orgArguments = arguments as unknown; - return theFunc.apply( - theLogger, - orgArguments as Parameters - ); - }; - } - - return noopLogFunction; - } - +export function createNoopDiagLogger(): DiagLogger { const diagLogger = {} as DiagLogger; - for (let lp = 0; lp < loggerMapFuncs.length; lp++) { - const map = loggerMapFuncs[lp]; - diagLogger[map.d] = _mapToLogger(logger, map.l); + for (let i = 0; i < diagLoggerFunctions.length; i++) { + diagLogger[diagLoggerFunctions[i]] = noopLogFunction; } return diagLogger; diff --git a/packages/opentelemetry-api/src/index.ts b/packages/opentelemetry-api/src/index.ts index 34425bc360b..fec995fa64a 100644 --- a/packages/opentelemetry-api/src/index.ts +++ b/packages/opentelemetry-api/src/index.ts @@ -81,12 +81,13 @@ export const propagation = PropagationAPI.getInstance(); import { DiagAPI } from './api/diag'; export type { DiagAPI } from './api/diag'; -/** Entrypoint for Diag API. +/** + * Entrypoint for Diag API. * Defines Diagnostic handler used for internal diagnostic logging operations. * The default provides a Noop DiagLogger implementation which may be changed via the * diag.setLogger(logger: DiagLogger) function. */ -export const diag = DiagAPI.inst(); +export const diag = DiagAPI.instance(); export default { trace, diff --git a/packages/opentelemetry-api/src/trace/NoopLogger.ts b/packages/opentelemetry-api/src/trace/NoopLogger.ts index 06a52724749..4dea9a5d393 100644 --- a/packages/opentelemetry-api/src/trace/NoopLogger.ts +++ b/packages/opentelemetry-api/src/trace/NoopLogger.ts @@ -18,7 +18,7 @@ import { Logger } from '../common/Logger'; /** No-op implementation of Logger * @deprecated This class will be removed prior to v1.0, use the api.diag - * @see {@link DiagAPI}, {@link DiagLogger} and {@link noopDiagLogger} + * @see {@link DiagAPI}, {@link DiagLogger} and {@link createNoopDiagLogger} */ export class NoopLogger implements Logger { // By default does nothing diff --git a/packages/opentelemetry-api/test/diag/consoleLogger.test.ts b/packages/opentelemetry-api/test/diag/consoleLogger.test.ts index 5bad3b0c02e..9a79265022c 100644 --- a/packages/opentelemetry-api/test/diag/consoleLogger.test.ts +++ b/packages/opentelemetry-api/test/diag/consoleLogger.test.ts @@ -16,21 +16,38 @@ import * as assert from 'assert'; import { DiagConsoleLogger } from '../../src/diag/consoleLogger'; +import { diagLoggerFunctions } from '../../src/diag/logger'; + +const consoleFuncs: Array = [ + 'debug', + 'info', + 'warn', + 'error', + 'log', + 'trace', +]; + +const expectedConsoleMap: { [n: string]: keyof Console } = { + terminal: 'error', + critical: 'error', + error: 'error', + warn: 'warn', + info: 'info', + debug: 'debug', + verbose: 'trace', + forcedInfo: 'info', +}; describe('DiagConsoleLogger', () => { const origConsole = console; - const origDebug = console.debug; - const origInfo = console.info; - const origWarn = console.warn; - const origError = console.error; - const origTrace = console.trace; - const origLog = console.log; - let traceCalledArgs: unknown; - let debugCalledArgs: unknown; - let infoCalledArgs: unknown; - let warnCalledArgs: unknown; - let errorCalledArgs: unknown; - let logCalledArgs: unknown; + const orig: any = {}; + const calledArgs: any = {}; + + // Save original functions + consoleFuncs.forEach(fName => { + orig[fName] = console[fName]; + calledArgs[fName] = null; + }); let canMockConsole = true; @@ -43,36 +60,16 @@ describe('DiagConsoleLogger', () => { } beforeEach(() => { - // mock - console.debug = (...args: unknown[]) => { - debugCalledArgs = args; - }; - console.info = (...args: unknown[]) => { - infoCalledArgs = args; - }; - console.warn = (...args: unknown[]) => { - warnCalledArgs = args; - }; - console.error = (...args: unknown[]) => { - errorCalledArgs = args; - }; - console.log = (...args: unknown[]) => { - logCalledArgs = args; - }; - console.trace = (...args: unknown[]) => { - traceCalledArgs = args; - }; + // mock Console + consoleFuncs.forEach(fName => { + console[fName] = (...args: unknown[]) => { + calledArgs[fName] = args; + }; + }); }); afterEach(() => { // restore - debugCalledArgs = null; - infoCalledArgs = null; - warnCalledArgs = null; - errorCalledArgs = null; - logCalledArgs = null; - traceCalledArgs = null; - if (canMockConsole) { try { // eslint-disable-next-line no-global-assign @@ -82,268 +79,133 @@ describe('DiagConsoleLogger', () => { canMockConsole = false; } } - console.debug = origDebug; - console.info = origInfo; - console.warn = origWarn; - console.error = origError; - console.log = origLog; - console.trace = origTrace; - }); - - describe('constructor', () => { - it('should log with each call', () => { - const consoleLogger = new DiagConsoleLogger(); - consoleLogger.terminal('terminal called %s', 'param1'); - assert.deepStrictEqual(errorCalledArgs, ['terminal called %s', 'param1']); - consoleLogger.critical('critical called %s', 'param1'); - assert.deepStrictEqual(errorCalledArgs, ['critical called %s', 'param1']); - consoleLogger.error('error called %s', 'param1'); - assert.deepStrictEqual(errorCalledArgs, ['error called %s', 'param1']); - consoleLogger.warn('warn called %s', 'param1'); - assert.deepStrictEqual(warnCalledArgs, ['warn called %s', 'param1']); - consoleLogger.info('info called %s', 'param1'); - assert.deepStrictEqual(infoCalledArgs, ['info called %s', 'param1']); - consoleLogger.debug('debug called %s', 'param1'); - assert.deepStrictEqual(debugCalledArgs, ['debug called %s', 'param1']); - consoleLogger.trace('trace called %s', 'param1'); - assert.deepStrictEqual(traceCalledArgs, ['trace called %s', 'param1']); - consoleLogger.forcedInfo('forcedInfo called %s', 'param1'); - assert.deepStrictEqual(infoCalledArgs, [ - 'forcedInfo called %s', - 'param1', - ]); - }); - - it("should log even of console doesn't support debug", () => { - (console as any).debug = undefined; - const consoleLogger = new DiagConsoleLogger(); - consoleLogger.terminal('terminal called %s', 'param1'); - assert.deepStrictEqual(errorCalledArgs, ['terminal called %s', 'param1']); - consoleLogger.critical('critical called %s', 'param1'); - assert.deepStrictEqual(errorCalledArgs, ['critical called %s', 'param1']); - consoleLogger.error('error called %s', 'param1'); - assert.deepStrictEqual(errorCalledArgs, ['error called %s', 'param1']); - consoleLogger.warn('warn called %s', 'param1'); - assert.deepStrictEqual(warnCalledArgs, ['warn called %s', 'param1']); - consoleLogger.info('info called %s', 'param1'); - assert.deepStrictEqual(infoCalledArgs, ['info called %s', 'param1']); - consoleLogger.debug('debug called %s', 'param1'); - assert.deepStrictEqual(debugCalledArgs, null); - assert.deepStrictEqual(logCalledArgs, ['debug called %s', 'param1']); - consoleLogger.trace('trace called %s', 'param1'); - assert.deepStrictEqual(traceCalledArgs, ['trace called %s', 'param1']); - consoleLogger.forcedInfo('forcedInfo called %s', 'param1'); - assert.deepStrictEqual(infoCalledArgs, [ - 'forcedInfo called %s', - 'param1', - ]); - }); - - it('should log even if console removes debug after initialization', () => { - const consoleLogger = new DiagConsoleLogger(); - (console as any).debug = undefined; - consoleLogger.terminal('terminal called %s', 'param1'); - assert.deepStrictEqual(errorCalledArgs, ['terminal called %s', 'param1']); - consoleLogger.critical('critical called %s', 'param1'); - assert.deepStrictEqual(errorCalledArgs, ['critical called %s', 'param1']); - consoleLogger.error('error called %s', 'param1'); - assert.deepStrictEqual(errorCalledArgs, ['error called %s', 'param1']); - consoleLogger.warn('warn called %s', 'param1'); - assert.deepStrictEqual(warnCalledArgs, ['warn called %s', 'param1']); - consoleLogger.info('info called %s', 'param1'); - assert.deepStrictEqual(infoCalledArgs, ['info called %s', 'param1']); - consoleLogger.debug('debug called %s', 'param1'); - assert.deepStrictEqual(debugCalledArgs, null); - assert.deepStrictEqual(logCalledArgs, ['debug called %s', 'param1']); - consoleLogger.trace('trace called %s', 'param1'); - assert.deepStrictEqual(traceCalledArgs, ['trace called %s', 'param1']); - consoleLogger.forcedInfo('forcedInfo called %s', 'param1'); - assert.deepStrictEqual(infoCalledArgs, [ - 'forcedInfo called %s', - 'param1', - ]); - }); - it("should log even of console doesn't support trace", () => { - (console as any).trace = undefined; - const consoleLogger = new DiagConsoleLogger(); - consoleLogger.terminal('terminal called %s', 'param1'); - assert.deepStrictEqual(errorCalledArgs, ['terminal called %s', 'param1']); - consoleLogger.critical('critical called %s', 'param1'); - assert.deepStrictEqual(errorCalledArgs, ['critical called %s', 'param1']); - consoleLogger.error('error called %s', 'param1'); - assert.deepStrictEqual(errorCalledArgs, ['error called %s', 'param1']); - consoleLogger.warn('warn called %s', 'param1'); - assert.deepStrictEqual(warnCalledArgs, ['warn called %s', 'param1']); - consoleLogger.info('info called %s', 'param1'); - assert.deepStrictEqual(infoCalledArgs, ['info called %s', 'param1']); - consoleLogger.debug('debug called %s', 'param1'); - assert.deepStrictEqual(debugCalledArgs, ['debug called %s', 'param1']); - consoleLogger.trace('trace called %s', 'param1'); - assert.deepStrictEqual(traceCalledArgs, null); - assert.deepStrictEqual(logCalledArgs, ['trace called %s', 'param1']); - consoleLogger.forcedInfo('forcedInfo called %s', 'param1'); - assert.deepStrictEqual(infoCalledArgs, [ - 'forcedInfo called %s', - 'param1', - ]); - }); - - it('should log even if console removes trace after initialization', () => { - const consoleLogger = new DiagConsoleLogger(); - (console as any).trace = undefined; - consoleLogger.terminal('terminal called %s', 'param1'); - assert.deepStrictEqual(errorCalledArgs, ['terminal called %s', 'param1']); - consoleLogger.critical('critical called %s', 'param1'); - assert.deepStrictEqual(errorCalledArgs, ['critical called %s', 'param1']); - consoleLogger.error('error called %s', 'param1'); - assert.deepStrictEqual(errorCalledArgs, ['error called %s', 'param1']); - consoleLogger.warn('warn called %s', 'param1'); - assert.deepStrictEqual(warnCalledArgs, ['warn called %s', 'param1']); - consoleLogger.info('info called %s', 'param1'); - assert.deepStrictEqual(infoCalledArgs, ['info called %s', 'param1']); - consoleLogger.debug('debug called %s', 'param1'); - assert.deepStrictEqual(debugCalledArgs, ['debug called %s', 'param1']); - consoleLogger.trace('trace called %s', 'param1'); - assert.deepStrictEqual(traceCalledArgs, null); - assert.deepStrictEqual(logCalledArgs, ['trace called %s', 'param1']); - consoleLogger.forcedInfo('forcedInfo called %s', 'param1'); - assert.deepStrictEqual(infoCalledArgs, [ - 'forcedInfo called %s', - 'param1', - ]); - }); - - it('should log even if console removes trace and log after initialization', () => { - const consoleLogger = new DiagConsoleLogger(); - (console as any).trace = undefined; - consoleLogger.terminal('terminal called %s', 'param1'); - assert.deepStrictEqual(errorCalledArgs, ['terminal called %s', 'param1']); - consoleLogger.critical('critical called %s', 'param1'); - assert.deepStrictEqual(errorCalledArgs, ['critical called %s', 'param1']); - consoleLogger.error('error called %s', 'param1'); - assert.deepStrictEqual(errorCalledArgs, ['error called %s', 'param1']); - consoleLogger.warn('warn called %s', 'param1'); - assert.deepStrictEqual(warnCalledArgs, ['warn called %s', 'param1']); - consoleLogger.info('info called %s', 'param1'); - assert.deepStrictEqual(infoCalledArgs, ['info called %s', 'param1']); - consoleLogger.debug('debug called %s', 'param1'); - assert.deepStrictEqual(debugCalledArgs, ['debug called %s', 'param1']); - consoleLogger.trace('trace called %s', 'param1'); - assert.deepStrictEqual(traceCalledArgs, null); - assert.deepStrictEqual(logCalledArgs, ['trace called %s', 'param1']); - consoleLogger.forcedInfo('forcedInfo called %s', 'param1'); - assert.deepStrictEqual(infoCalledArgs, [ - 'forcedInfo called %s', - 'param1', - ]); + consoleFuncs.forEach(fName => { + calledArgs[fName] = null; + console[fName] = orig[fName]; }); + }); - if (canMockConsole) { - it('should not throw even when console is not supported', () => { - (console as any) = undefined; - const consoleLogger = new DiagConsoleLogger(); - consoleLogger.terminal('terminal called %s', 'param1'); - assert.deepStrictEqual(errorCalledArgs, null); - consoleLogger.critical('critical called %s', 'param1'); - assert.deepStrictEqual(errorCalledArgs, null); - consoleLogger.error('error called %s', 'param1'); - assert.deepStrictEqual(errorCalledArgs, null); - consoleLogger.warn('warn called %s', 'param1'); - assert.deepStrictEqual(warnCalledArgs, null); - consoleLogger.info('info called %s', 'param1'); - assert.deepStrictEqual(infoCalledArgs, null); - consoleLogger.debug('debug called %s', 'param1'); - assert.deepStrictEqual(debugCalledArgs, null); - consoleLogger.trace('trace called %s', 'param1'); - assert.deepStrictEqual(traceCalledArgs, null); - assert.deepStrictEqual(logCalledArgs, null); - consoleLogger.forcedInfo('forcedInfo called %s', 'param1'); - assert.deepStrictEqual(infoCalledArgs, null); + describe('constructor', () => { + diagLoggerFunctions.forEach(fName => { + it(`console logger should provide ${fName} function`, () => { + const consoleLogger: any = new DiagConsoleLogger(); + consoleLogger[fName](`${fName} called %s`, 'param1'); + assert.ok( + typeof consoleLogger[fName] === 'function', + `Must have a ${fName} function` + ); }); - it('should not throw even when console is disabled after construction', () => { - const consoleLogger = new DiagConsoleLogger(); - (console as any) = undefined; - consoleLogger.terminal('terminal called %s', 'param1'); - assert.deepStrictEqual(errorCalledArgs, null); - consoleLogger.critical('critical called %s', 'param1'); - assert.deepStrictEqual(errorCalledArgs, null); - consoleLogger.error('error called %s', 'param1'); - assert.deepStrictEqual(errorCalledArgs, null); - consoleLogger.warn('warn called %s', 'param1'); - assert.deepStrictEqual(warnCalledArgs, null); - consoleLogger.info('info called %s', 'param1'); - assert.deepStrictEqual(infoCalledArgs, null); - consoleLogger.debug('debug called %s', 'param1'); - assert.deepStrictEqual(debugCalledArgs, null); - consoleLogger.trace('trace called %s', 'param1'); - assert.deepStrictEqual(traceCalledArgs, null); - assert.deepStrictEqual(logCalledArgs, null); - consoleLogger.forcedInfo('forcedInfo called %s', 'param1'); - assert.deepStrictEqual(infoCalledArgs, null); + it(`should log ${expectedConsoleMap[fName]} message with ${fName} call only`, () => { + const consoleLogger: any = new DiagConsoleLogger(); + consoleLogger[fName](`${fName} called %s`, 'param1'); + + // Make sure only gets logged once + let matches = 0; + consoleFuncs.forEach(cName => { + if (cName !== expectedConsoleMap[fName]) { + assert.deepStrictEqual(calledArgs[cName], null); + } else { + assert.deepStrictEqual(calledArgs[expectedConsoleMap[fName]], [ + `${fName} called %s`, + 'param1', + ]); + matches++; + } + }); + + assert.deepStrictEqual(calledArgs.log, null); + assert.strictEqual(matches, 1, 'should log at least once'); }); - it('should not throw even when console is invalid after construction', () => { - const invalidConsole = { - debug: 1, - warn: 2, - error: 3, - trace: 4, - info: 5, - log: 6, - }; - - const consoleLogger = new DiagConsoleLogger(); - (console as any) = invalidConsole; - consoleLogger.terminal('terminal called %s', 'param1'); - assert.deepStrictEqual(errorCalledArgs, null); - consoleLogger.critical('critical called %s', 'param1'); - assert.deepStrictEqual(errorCalledArgs, null); - consoleLogger.error('error called %s', 'param1'); - assert.deepStrictEqual(errorCalledArgs, null); - consoleLogger.warn('warn called %s', 'param1'); - assert.deepStrictEqual(warnCalledArgs, null); - consoleLogger.info('info called %s', 'param1'); - assert.deepStrictEqual(infoCalledArgs, null); - consoleLogger.debug('debug called %s', 'param1'); - assert.deepStrictEqual(debugCalledArgs, null); - consoleLogger.trace('trace called %s', 'param1'); - assert.deepStrictEqual(traceCalledArgs, null); - assert.deepStrictEqual(logCalledArgs, null); - consoleLogger.forcedInfo('forcedInfo called %s', 'param1'); - assert.deepStrictEqual(infoCalledArgs, null); + consoleFuncs.forEach(cName => { + it(`should log ${fName} message even when console doesn't support ${cName} call before construction`, () => { + console[cName] = undefined; + const consoleLogger: any = new DiagConsoleLogger(); + consoleLogger[fName](`${fName} called %s`, 'param1'); + if (cName !== expectedConsoleMap[fName]) { + assert.deepStrictEqual(calledArgs[cName], null); + } else { + assert.deepStrictEqual(calledArgs.log, [ + `${fName} called %s`, + 'param1', + ]); + } + }); + + it(`should log ${fName} message even when console doesn't support ${cName} call after construction`, () => { + const consoleLogger: any = new DiagConsoleLogger(); + console[cName] = undefined; + consoleLogger[fName](`${fName} called %s`, 'param1'); + if (cName !== expectedConsoleMap[fName]) { + assert.deepStrictEqual(calledArgs[cName], null); + } else { + assert.deepStrictEqual(calledArgs.log, [ + `${fName} called %s`, + 'param1', + ]); + } + }); }); + }); - it('should not throw even when console is invalid before construction', () => { - const invalidConsole = { - debug: 1, - warn: 2, - error: 3, - trace: 4, - info: 5, - log: 6, - }; - - (console as any) = invalidConsole; - const consoleLogger = new DiagConsoleLogger(); - consoleLogger.terminal('terminal called %s', 'param1'); - assert.deepStrictEqual(errorCalledArgs, null); - consoleLogger.critical('critical called %s', 'param1'); - assert.deepStrictEqual(errorCalledArgs, null); - consoleLogger.error('error called %s', 'param1'); - assert.deepStrictEqual(errorCalledArgs, null); - consoleLogger.warn('warn called %s', 'param1'); - assert.deepStrictEqual(warnCalledArgs, null); - consoleLogger.info('info called %s', 'param1'); - assert.deepStrictEqual(infoCalledArgs, null); - consoleLogger.debug('debug called %s', 'param1'); - assert.deepStrictEqual(debugCalledArgs, null); - consoleLogger.trace('trace called %s', 'param1'); - assert.deepStrictEqual(traceCalledArgs, null); - assert.deepStrictEqual(logCalledArgs, null); - consoleLogger.forcedInfo('forcedInfo called %s', 'param1'); - assert.deepStrictEqual(infoCalledArgs, null); + if (canMockConsole) { + diagLoggerFunctions.forEach(fName => { + const cName = expectedConsoleMap[fName]; + it(`should not throw even when console is not supported for ${fName} call`, () => { + // eslint-disable-next-line no-global-assign + (console as any) = undefined; + const consoleLogger: any = new DiagConsoleLogger(); + consoleLogger[fName](`${fName} called %s`, 'param1'); + assert.deepStrictEqual(calledArgs[cName], null); + assert.deepStrictEqual(calledArgs.log, null); + }); + + it(`should not throw even when console is disabled after construction for ${fName} call`, () => { + const consoleLogger: any = new DiagConsoleLogger(); + // eslint-disable-next-line no-global-assign + (console as any) = undefined; + consoleLogger[fName](`${fName} called %s`, 'param1'); + assert.deepStrictEqual(calledArgs[expectedConsoleMap[fName]], null); + assert.deepStrictEqual(calledArgs.log, null); + }); + + it(`should not throw even when console is invalid after construction for ${fName} call`, () => { + const invalidConsole = { + debug: 1, + warn: 2, + error: 3, + trace: 4, + info: 5, + log: 6, + }; + + const consoleLogger = new DiagConsoleLogger(); + // eslint-disable-next-line no-global-assign + (console as any) = invalidConsole; + consoleLogger[fName](`${fName} called %s`, 'param1'); + assert.deepStrictEqual(calledArgs[expectedConsoleMap[fName]], null); + assert.deepStrictEqual(calledArgs.log, null); + }); + + it(`should not throw even when console is invalid before construction for ${fName} call`, () => { + const invalidConsole = { + debug: 1, + warn: 2, + error: 3, + trace: 4, + info: 5, + log: 6, + }; + + // eslint-disable-next-line no-global-assign + (console as any) = invalidConsole; + const consoleLogger = new DiagConsoleLogger(); + consoleLogger[fName](`${fName} called %s`, 'param1'); + assert.deepStrictEqual(calledArgs[expectedConsoleMap[fName]], null); + assert.deepStrictEqual(calledArgs.log, null); + }); }); } }); diff --git a/packages/opentelemetry-api/test/diag/logLevel.test.ts b/packages/opentelemetry-api/test/diag/logLevel.test.ts index 4fefc121fdb..a8a16f1c1b9 100644 --- a/packages/opentelemetry-api/test/diag/logLevel.test.ts +++ b/packages/opentelemetry-api/test/diag/logLevel.test.ts @@ -15,18 +15,47 @@ */ import * as assert from 'assert'; -import { DiagLogger } from '../../src/diag/logger'; -import { DiagLogLevel, diagLogLevelFilter } from '../../src/diag/logLevel'; +import { diag } from '../../src'; +import { Logger } from '../../src/common/Logger'; +import { + createNoopDiagLogger, + DiagLogger, + diagLoggerFunctions, +} from '../../src/diag/logger'; +import { + DiagLogLevel, + createLogLevelDiagLogger, +} from '../../src/diag/logLevel'; + +const incompleteLoggerFuncs: Array = [ + 'debug', + 'info', + 'warn', + 'error', +]; + +const expectedIncompleteMap: { [n: string]: keyof Console } = { + terminal: 'error', + critical: 'error', + error: 'error', + warn: 'warn', + info: 'info', + debug: 'debug', + verbose: 'debug', + forcedInfo: 'info', +}; describe('LogLevelFilter DiagLogger', () => { - let terminalCalledArgs: unknown; - let criticalCalledArgs: unknown; - let errorCalledArgs: unknown; - let warnCalledArgs: unknown; - let infoCalledArgs: unknown; - let debugCalledArgs: unknown; - let traceCalledArgs: unknown; - let forcedInfoCalledArgs: unknown; + const calledArgs: any = { + terminal: null, + critical: null, + error: null, + warn: null, + info: null, + debug: null, + verbose: null, + forcedInfo: null, + }; let dummyLogger: DiagLogger; @@ -34,617 +63,258 @@ describe('LogLevelFilter DiagLogger', () => { let incompleteLogger: DiagLogger; beforeEach(() => { + // set no logger + diag.setLogger(null as any); + // mock - dummyLogger = { - terminal: (...args: unknown[]) => { - terminalCalledArgs = args; - }, - critical: (...args: unknown[]) => { - criticalCalledArgs = args; - }, - error: (...args: unknown[]) => { - errorCalledArgs = args; - }, - warn: (...args: unknown[]) => { - warnCalledArgs = args; - }, - info: (...args: unknown[]) => { - infoCalledArgs = args; - }, - debug: (...args: unknown[]) => { - debugCalledArgs = args; - }, - trace: (...args: unknown[]) => { - traceCalledArgs = args; - }, - forcedInfo: (...args: unknown[]) => { - forcedInfoCalledArgs = args; - }, - }; + dummyLogger = {} as DiagLogger; + diagLoggerFunctions.forEach(fName => { + dummyLogger[fName] = (...args: unknown[]) => { + calledArgs[fName] = args; + }; + }); - incompleteLogger = { - error: (...args: unknown[]) => { - errorCalledArgs = args; - }, - warn: (...args: unknown[]) => { - warnCalledArgs = args; - }, - info: (...args: unknown[]) => { - infoCalledArgs = args; - }, - debug: (...args: unknown[]) => { - debugCalledArgs = args; - }, - } as DiagLogger; + incompleteLogger = {} as DiagLogger; + incompleteLoggerFuncs.forEach(fName => { + incompleteLogger[fName] = (...args: unknown[]) => { + calledArgs[fName] = args; + }; + }); }); afterEach(() => { // restore - terminalCalledArgs = null; - criticalCalledArgs = null; - errorCalledArgs = null; - warnCalledArgs = null; - infoCalledArgs = null; - debugCalledArgs = null; - traceCalledArgs = null; - forcedInfoCalledArgs = null; + diagLoggerFunctions.forEach(fName => { + calledArgs[fName] = null; + }); }); describe('constructor', () => { - it('should log all calls', () => { - const testLogger = dummyLogger; - testLogger.terminal('terminal called %s', 'param1'); - assert.deepStrictEqual(terminalCalledArgs, [ - 'terminal called %s', - 'param1', - ]); - testLogger.critical('critical called %s', 'param1'); - assert.deepStrictEqual(criticalCalledArgs, [ - 'critical called %s', - 'param1', - ]); - testLogger.error('error called %s', 'param1'); - assert.deepStrictEqual(errorCalledArgs, ['error called %s', 'param1']); - testLogger.warn('warn called %s', 'param1'); - assert.deepStrictEqual(warnCalledArgs, ['warn called %s', 'param1']); - testLogger.info('info called %s', 'param1'); - assert.deepStrictEqual(infoCalledArgs, ['info called %s', 'param1']); - testLogger.debug('debug called %s', 'param1'); - assert.deepStrictEqual(debugCalledArgs, ['debug called %s', 'param1']); - testLogger.trace('trace called %s', 'param1'); - assert.deepStrictEqual(traceCalledArgs, ['trace called %s', 'param1']); - testLogger.forcedInfo('forcedInfo called %s', 'param1'); - assert.deepStrictEqual(forcedInfoCalledArgs, [ - 'forcedInfo called %s', - 'param1', - ]); - }); - - it('should log with ALL level', () => { - const testLogger = diagLogLevelFilter(DiagLogLevel.ALL, dummyLogger); - - testLogger.terminal('terminal called %s', 'param1'); - assert.deepStrictEqual(terminalCalledArgs, [ - 'terminal called %s', - 'param1', - ]); - testLogger.critical('critical called %s', 'param1'); - assert.deepStrictEqual(criticalCalledArgs, [ - 'critical called %s', - 'param1', - ]); - testLogger.error('error called %s', 'param1'); - assert.deepStrictEqual(errorCalledArgs, ['error called %s', 'param1']); - testLogger.warn('warn called %s', 'param1'); - assert.deepStrictEqual(warnCalledArgs, ['warn called %s', 'param1']); - testLogger.info('info called %s', 'param1'); - assert.deepStrictEqual(infoCalledArgs, ['info called %s', 'param1']); - testLogger.debug('debug called %s', 'param1'); - assert.deepStrictEqual(debugCalledArgs, ['debug called %s', 'param1']); - testLogger.trace('trace called %s', 'param1'); - assert.deepStrictEqual(traceCalledArgs, ['trace called %s', 'param1']); - testLogger.forcedInfo('forcedInfo called %s', 'param1'); - assert.deepStrictEqual(forcedInfoCalledArgs, [ - 'forcedInfo called %s', - 'param1', - ]); - }); - - it('should log with level greater than ALL', () => { - const testLogger = diagLogLevelFilter(32768, dummyLogger); - - testLogger.terminal('terminal called %s', 'param1'); - assert.deepStrictEqual(terminalCalledArgs, [ - 'terminal called %s', - 'param1', - ]); - testLogger.critical('critical called %s', 'param1'); - assert.deepStrictEqual(criticalCalledArgs, [ - 'critical called %s', - 'param1', - ]); - testLogger.error('error called %s', 'param1'); - assert.deepStrictEqual(errorCalledArgs, ['error called %s', 'param1']); - testLogger.warn('warn called %s', 'param1'); - assert.deepStrictEqual(warnCalledArgs, ['warn called %s', 'param1']); - testLogger.info('info called %s', 'param1'); - assert.deepStrictEqual(infoCalledArgs, ['info called %s', 'param1']); - testLogger.debug('debug called %s', 'param1'); - assert.deepStrictEqual(debugCalledArgs, ['debug called %s', 'param1']); - testLogger.trace('trace called %s', 'param1'); - assert.deepStrictEqual(traceCalledArgs, ['trace called %s', 'param1']); - testLogger.forcedInfo('forcedInfo called %s', 'param1'); - assert.deepStrictEqual(forcedInfoCalledArgs, [ - 'forcedInfo called %s', - 'param1', - ]); - }); - - it('should log with TRACE level', () => { - const testLogger = diagLogLevelFilter(DiagLogLevel.TRACE, dummyLogger); - - testLogger.terminal('terminal called %s', 'param1'); - assert.deepStrictEqual(terminalCalledArgs, [ - 'terminal called %s', - 'param1', - ]); - testLogger.critical('critical called %s', 'param1'); - assert.deepStrictEqual(criticalCalledArgs, [ - 'critical called %s', - 'param1', - ]); - testLogger.error('error called %s', 'param1'); - assert.deepStrictEqual(errorCalledArgs, ['error called %s', 'param1']); - testLogger.warn('warn called %s', 'param1'); - assert.deepStrictEqual(warnCalledArgs, ['warn called %s', 'param1']); - testLogger.info('info called %s', 'param1'); - assert.deepStrictEqual(infoCalledArgs, ['info called %s', 'param1']); - testLogger.debug('debug called %s', 'param1'); - assert.deepStrictEqual(debugCalledArgs, ['debug called %s', 'param1']); - testLogger.trace('trace called %s', 'param1'); - assert.deepStrictEqual(traceCalledArgs, ['trace called %s', 'param1']); - testLogger.forcedInfo('forcedInfo called %s', 'param1'); - assert.deepStrictEqual(forcedInfoCalledArgs, [ - 'forcedInfo called %s', - 'param1', - ]); - }); - - it('should log with debug', () => { - const testLogger = diagLogLevelFilter(DiagLogLevel.DEBUG, dummyLogger); - - testLogger.terminal('terminal called %s', 'param1'); - assert.deepStrictEqual(terminalCalledArgs, [ - 'terminal called %s', - 'param1', - ]); - testLogger.critical('critical called %s', 'param1'); - assert.deepStrictEqual(criticalCalledArgs, [ - 'critical called %s', - 'param1', - ]); - testLogger.error('error called %s', 'param1'); - assert.deepStrictEqual(errorCalledArgs, ['error called %s', 'param1']); - testLogger.warn('warn called %s', 'param1'); - assert.deepStrictEqual(warnCalledArgs, ['warn called %s', 'param1']); - testLogger.info('info called %s', 'param1'); - assert.deepStrictEqual(infoCalledArgs, ['info called %s', 'param1']); - testLogger.debug('debug called %s', 'param1'); - assert.deepStrictEqual(debugCalledArgs, ['debug called %s', 'param1']); - testLogger.trace('trace called %s', 'param1'); - assert.deepStrictEqual(traceCalledArgs, null); - testLogger.forcedInfo('forcedInfo called %s', 'param1'); - assert.deepStrictEqual(forcedInfoCalledArgs, [ - 'forcedInfo called %s', - 'param1', - ]); - }); - - it('should log with info', () => { - const testLogger = diagLogLevelFilter(DiagLogLevel.INFO, dummyLogger); - - testLogger.terminal('terminal called %s', 'param1'); - assert.deepStrictEqual(terminalCalledArgs, [ - 'terminal called %s', - 'param1', - ]); - testLogger.critical('critical called %s', 'param1'); - assert.deepStrictEqual(criticalCalledArgs, [ - 'critical called %s', - 'param1', - ]); - testLogger.error('error called %s', 'param1'); - assert.deepStrictEqual(errorCalledArgs, ['error called %s', 'param1']); - testLogger.warn('warn called %s', 'param1'); - assert.deepStrictEqual(warnCalledArgs, ['warn called %s', 'param1']); - testLogger.info('info called %s', 'param1'); - assert.deepStrictEqual(infoCalledArgs, ['info called %s', 'param1']); - testLogger.debug('debug called %s', 'param1'); - assert.deepStrictEqual(debugCalledArgs, null); - testLogger.trace('trace called %s', 'param1'); - assert.deepStrictEqual(traceCalledArgs, null); - testLogger.forcedInfo('forcedInfo called %s', 'param1'); - assert.deepStrictEqual(forcedInfoCalledArgs, [ - 'forcedInfo called %s', - 'param1', - ]); - }); - - it('should log with warning', () => { - const testLogger = diagLogLevelFilter(DiagLogLevel.WARN, dummyLogger); - - testLogger.terminal('terminal called %s', 'param1'); - assert.deepStrictEqual(terminalCalledArgs, [ - 'terminal called %s', - 'param1', - ]); - testLogger.critical('critical called %s', 'param1'); - assert.deepStrictEqual(criticalCalledArgs, [ - 'critical called %s', - 'param1', - ]); - testLogger.error('error called %s', 'param1'); - assert.deepStrictEqual(errorCalledArgs, ['error called %s', 'param1']); - testLogger.warn('warn called %s', 'param1'); - assert.deepStrictEqual(warnCalledArgs, ['warn called %s', 'param1']); - testLogger.info('info called %s', 'param1'); - assert.deepStrictEqual(infoCalledArgs, null); - testLogger.debug('debug called %s', 'param1'); - assert.deepStrictEqual(debugCalledArgs, null); - testLogger.trace('trace called %s', 'param1'); - assert.deepStrictEqual(traceCalledArgs, null); - testLogger.forcedInfo('forcedInfo called %s', 'param1'); - assert.deepStrictEqual(forcedInfoCalledArgs, [ - 'forcedInfo called %s', - 'param1', - ]); - }); - - it('should log with error', () => { - const testLogger = diagLogLevelFilter(DiagLogLevel.ERROR, dummyLogger); - - testLogger.terminal('terminal called %s', 'param1'); - assert.deepStrictEqual(terminalCalledArgs, [ - 'terminal called %s', - 'param1', - ]); - testLogger.critical('critical called %s', 'param1'); - assert.deepStrictEqual(criticalCalledArgs, [ - 'critical called %s', - 'param1', - ]); - testLogger.error('error called %s', 'param1'); - assert.deepStrictEqual(errorCalledArgs, ['error called %s', 'param1']); - testLogger.warn('warn called %s', 'param1'); - assert.deepStrictEqual(warnCalledArgs, null); - testLogger.info('info called %s', 'param1'); - assert.deepStrictEqual(infoCalledArgs, null); - testLogger.debug('debug called %s', 'param1'); - assert.deepStrictEqual(debugCalledArgs, null); - testLogger.trace('trace called %s', 'param1'); - assert.deepStrictEqual(traceCalledArgs, null); - testLogger.forcedInfo('forcedInfo called %s', 'param1'); - assert.deepStrictEqual(forcedInfoCalledArgs, [ - 'forcedInfo called %s', - 'param1', - ]); - }); - - it('should log with critical', () => { - const testLogger = diagLogLevelFilter(DiagLogLevel.CRITICAL, dummyLogger); - - testLogger.terminal('terminal called %s', 'param1'); - assert.deepStrictEqual(terminalCalledArgs, [ - 'terminal called %s', - 'param1', - ]); - testLogger.critical('critical called %s', 'param1'); - assert.deepStrictEqual(criticalCalledArgs, [ - 'critical called %s', - 'param1', - ]); - testLogger.error('error called %s', 'param1'); - assert.deepStrictEqual(errorCalledArgs, null); - testLogger.warn('warn called %s', 'param1'); - assert.deepStrictEqual(warnCalledArgs, null); - testLogger.info('info called %s', 'param1'); - assert.deepStrictEqual(infoCalledArgs, null); - testLogger.debug('debug called %s', 'param1'); - assert.deepStrictEqual(debugCalledArgs, null); - testLogger.trace('trace called %s', 'param1'); - assert.deepStrictEqual(traceCalledArgs, null); - testLogger.forcedInfo('forcedInfo called %s', 'param1'); - assert.deepStrictEqual(forcedInfoCalledArgs, [ - 'forcedInfo called %s', - 'param1', - ]); - }); - - it('should log with terminal', () => { - const testLogger = diagLogLevelFilter(DiagLogLevel.TERMINAL, dummyLogger); - - testLogger.terminal('terminal called %s', 'param1'); - assert.deepStrictEqual(terminalCalledArgs, [ - 'terminal called %s', - 'param1', - ]); - testLogger.critical('critical called %s', 'param1'); - assert.deepStrictEqual(criticalCalledArgs, null); - testLogger.error('error called %s', 'param1'); - assert.deepStrictEqual(errorCalledArgs, null); - testLogger.warn('warn called %s', 'param1'); - assert.deepStrictEqual(warnCalledArgs, null); - testLogger.info('info called %s', 'param1'); - assert.deepStrictEqual(infoCalledArgs, null); - testLogger.debug('debug called %s', 'param1'); - assert.deepStrictEqual(debugCalledArgs, null); - testLogger.trace('trace called %s', 'param1'); - assert.deepStrictEqual(traceCalledArgs, null); - testLogger.forcedInfo('forcedInfo called %s', 'param1'); - assert.deepStrictEqual(forcedInfoCalledArgs, [ - 'forcedInfo called %s', - 'param1', - ]); - }); - - it('should log with none', () => { - const testLogger = diagLogLevelFilter(DiagLogLevel.NONE, dummyLogger); - - testLogger.terminal('terminal called %s', 'param1'); - assert.deepStrictEqual(terminalCalledArgs, null); - testLogger.critical('critical called %s', 'param1'); - assert.deepStrictEqual(criticalCalledArgs, null); - testLogger.error('error called %s', 'param1'); - assert.deepStrictEqual(errorCalledArgs, null); - testLogger.warn('warn called %s', 'param1'); - assert.deepStrictEqual(warnCalledArgs, null); - testLogger.info('info called %s', 'param1'); - assert.deepStrictEqual(infoCalledArgs, null); - testLogger.debug('debug called %s', 'param1'); - assert.deepStrictEqual(debugCalledArgs, null); - testLogger.trace('trace called %s', 'param1'); - assert.deepStrictEqual(traceCalledArgs, null); - testLogger.forcedInfo('forcedInfo called %s', 'param1'); - assert.deepStrictEqual(forcedInfoCalledArgs, [ - 'forcedInfo called %s', - 'param1', - ]); - }); - - it('should log with value less than NONE', () => { - const testLogger = diagLogLevelFilter(-1000, dummyLogger); - - testLogger.terminal('terminal called %s', 'param1'); - assert.deepStrictEqual(terminalCalledArgs, null); - testLogger.critical('critical called %s', 'param1'); - assert.deepStrictEqual(criticalCalledArgs, null); - testLogger.error('error called %s', 'param1'); - assert.deepStrictEqual(errorCalledArgs, null); - testLogger.warn('warn called %s', 'param1'); - assert.deepStrictEqual(warnCalledArgs, null); - testLogger.info('info called %s', 'param1'); - assert.deepStrictEqual(infoCalledArgs, null); - testLogger.debug('debug called %s', 'param1'); - assert.deepStrictEqual(debugCalledArgs, null); - testLogger.trace('trace called %s', 'param1'); - assert.deepStrictEqual(traceCalledArgs, null); - testLogger.forcedInfo('forcedInfo called %s', 'param1'); - assert.deepStrictEqual(forcedInfoCalledArgs, [ - 'forcedInfo called %s', - 'param1', - ]); - }); - it('legacyLogger should log with ALL level', () => { - const testLogger = diagLogLevelFilter(DiagLogLevel.ALL, incompleteLogger); - - testLogger.terminal('terminal called %s', 'param1'); - assert.deepStrictEqual(terminalCalledArgs, null); - testLogger.critical('critical called %s', 'param1'); - assert.deepStrictEqual(criticalCalledArgs, null); - testLogger.error('error called %s', 'param1'); - assert.deepStrictEqual(errorCalledArgs, ['error called %s', 'param1']); - testLogger.warn('warn called %s', 'param1'); - assert.deepStrictEqual(warnCalledArgs, ['warn called %s', 'param1']); - testLogger.info('info called %s', 'param1'); - assert.deepStrictEqual(infoCalledArgs, ['info called %s', 'param1']); - testLogger.debug('debug called %s', 'param1'); - assert.deepStrictEqual(debugCalledArgs, ['debug called %s', 'param1']); - testLogger.trace('trace called %s', 'param1'); - assert.deepStrictEqual(traceCalledArgs, null); - testLogger.forcedInfo('forcedInfo called %s', 'param1'); - assert.deepStrictEqual(forcedInfoCalledArgs, null); - }); - - it('legacyLogger should log with TRACE level', () => { - const testLogger = diagLogLevelFilter( - DiagLogLevel.TRACE, - incompleteLogger - ); - - testLogger.terminal('terminal called %s', 'param1'); - assert.deepStrictEqual(terminalCalledArgs, null); - testLogger.critical('critical called %s', 'param1'); - assert.deepStrictEqual(criticalCalledArgs, null); - testLogger.error('error called %s', 'param1'); - assert.deepStrictEqual(errorCalledArgs, ['error called %s', 'param1']); - testLogger.warn('warn called %s', 'param1'); - assert.deepStrictEqual(warnCalledArgs, ['warn called %s', 'param1']); - testLogger.info('info called %s', 'param1'); - assert.deepStrictEqual(infoCalledArgs, ['info called %s', 'param1']); - testLogger.debug('debug called %s', 'param1'); - assert.deepStrictEqual(debugCalledArgs, ['debug called %s', 'param1']); - testLogger.trace('trace called %s', 'param1'); - assert.deepStrictEqual(traceCalledArgs, null); - testLogger.forcedInfo('forcedInfo called %s', 'param1'); - assert.deepStrictEqual(forcedInfoCalledArgs, null); - }); - - it('legacyLogger should log with debug', () => { - const testLogger = diagLogLevelFilter( - DiagLogLevel.DEBUG, - incompleteLogger - ); - - testLogger.terminal('terminal called %s', 'param1'); - assert.deepStrictEqual(terminalCalledArgs, null); - testLogger.critical('critical called %s', 'param1'); - assert.deepStrictEqual(criticalCalledArgs, null); - testLogger.error('error called %s', 'param1'); - assert.deepStrictEqual(errorCalledArgs, ['error called %s', 'param1']); - testLogger.warn('warn called %s', 'param1'); - assert.deepStrictEqual(warnCalledArgs, ['warn called %s', 'param1']); - testLogger.info('info called %s', 'param1'); - assert.deepStrictEqual(infoCalledArgs, ['info called %s', 'param1']); - testLogger.debug('debug called %s', 'param1'); - assert.deepStrictEqual(debugCalledArgs, ['debug called %s', 'param1']); - testLogger.trace('trace called %s', 'param1'); - assert.deepStrictEqual(traceCalledArgs, null); - testLogger.forcedInfo('forcedInfo called %s', 'param1'); - assert.deepStrictEqual(forcedInfoCalledArgs, null); - }); - - it('legacyLogger should log with info', () => { - const testLogger = diagLogLevelFilter( - DiagLogLevel.INFO, - incompleteLogger - ); - - testLogger.terminal('terminal called %s', 'param1'); - assert.deepStrictEqual(terminalCalledArgs, null); - testLogger.critical('critical called %s', 'param1'); - assert.deepStrictEqual(criticalCalledArgs, null); - testLogger.error('error called %s', 'param1'); - assert.deepStrictEqual(errorCalledArgs, ['error called %s', 'param1']); - testLogger.warn('warn called %s', 'param1'); - assert.deepStrictEqual(warnCalledArgs, ['warn called %s', 'param1']); - testLogger.info('info called %s', 'param1'); - assert.deepStrictEqual(infoCalledArgs, ['info called %s', 'param1']); - testLogger.debug('debug called %s', 'param1'); - assert.deepStrictEqual(debugCalledArgs, null); - testLogger.trace('trace called %s', 'param1'); - assert.deepStrictEqual(traceCalledArgs, null); - testLogger.forcedInfo('forcedInfo called %s', 'param1'); - assert.deepStrictEqual(forcedInfoCalledArgs, null); - }); - - it('legacyLogger should log with warning', () => { - const testLogger = diagLogLevelFilter( - DiagLogLevel.WARN, - incompleteLogger - ); - - testLogger.terminal('terminal called %s', 'param1'); - assert.deepStrictEqual(terminalCalledArgs, null); - testLogger.critical('critical called %s', 'param1'); - assert.deepStrictEqual(criticalCalledArgs, null); - testLogger.error('error called %s', 'param1'); - assert.deepStrictEqual(errorCalledArgs, ['error called %s', 'param1']); - testLogger.warn('warn called %s', 'param1'); - assert.deepStrictEqual(warnCalledArgs, ['warn called %s', 'param1']); - testLogger.info('info called %s', 'param1'); - assert.deepStrictEqual(infoCalledArgs, null); - testLogger.debug('debug called %s', 'param1'); - assert.deepStrictEqual(debugCalledArgs, null); - testLogger.trace('trace called %s', 'param1'); - assert.deepStrictEqual(traceCalledArgs, null); - testLogger.forcedInfo('forcedInfo called %s', 'param1'); - assert.deepStrictEqual(forcedInfoCalledArgs, null); - }); - - it('legacyLogger should log with error', () => { - const testLogger = diagLogLevelFilter( - DiagLogLevel.ERROR, - incompleteLogger - ); - - testLogger.terminal('terminal called %s', 'param1'); - assert.deepStrictEqual(terminalCalledArgs, null); - testLogger.critical('critical called %s', 'param1'); - assert.deepStrictEqual(criticalCalledArgs, null); - testLogger.error('error called %s', 'param1'); - assert.deepStrictEqual(errorCalledArgs, ['error called %s', 'param1']); - testLogger.warn('warn called %s', 'param1'); - assert.deepStrictEqual(warnCalledArgs, null); - testLogger.info('info called %s', 'param1'); - assert.deepStrictEqual(infoCalledArgs, null); - testLogger.debug('debug called %s', 'param1'); - assert.deepStrictEqual(debugCalledArgs, null); - testLogger.trace('trace called %s', 'param1'); - assert.deepStrictEqual(traceCalledArgs, null); - testLogger.forcedInfo('forcedInfo called %s', 'param1'); - assert.deepStrictEqual(forcedInfoCalledArgs, null); - }); - - it('legacyLogger should log with critical', () => { - const testLogger = diagLogLevelFilter( - DiagLogLevel.CRITICAL, - incompleteLogger - ); - - testLogger.terminal('terminal called %s', 'param1'); - assert.deepStrictEqual(terminalCalledArgs, null); - testLogger.critical('critical called %s', 'param1'); - assert.deepStrictEqual(criticalCalledArgs, null); - testLogger.error('error called %s', 'param1'); - assert.deepStrictEqual(errorCalledArgs, null); - testLogger.warn('warn called %s', 'param1'); - assert.deepStrictEqual(warnCalledArgs, null); - testLogger.info('info called %s', 'param1'); - assert.deepStrictEqual(infoCalledArgs, null); - testLogger.debug('debug called %s', 'param1'); - assert.deepStrictEqual(debugCalledArgs, null); - testLogger.trace('trace called %s', 'param1'); - assert.deepStrictEqual(traceCalledArgs, null); - testLogger.forcedInfo('forcedInfo called %s', 'param1'); - assert.deepStrictEqual(forcedInfoCalledArgs, null); - }); - - it('legacyLogger should log with terminal', () => { - const testLogger = diagLogLevelFilter( - DiagLogLevel.TERMINAL, - incompleteLogger - ); - - testLogger.terminal('terminal called %s', 'param1'); - assert.deepStrictEqual(terminalCalledArgs, null); - testLogger.critical('critical called %s', 'param1'); - assert.deepStrictEqual(criticalCalledArgs, null); - testLogger.error('error called %s', 'param1'); - assert.deepStrictEqual(errorCalledArgs, null); - testLogger.warn('warn called %s', 'param1'); - assert.deepStrictEqual(warnCalledArgs, null); - testLogger.info('info called %s', 'param1'); - assert.deepStrictEqual(infoCalledArgs, null); - testLogger.debug('debug called %s', 'param1'); - assert.deepStrictEqual(debugCalledArgs, null); - testLogger.trace('trace called %s', 'param1'); - assert.deepStrictEqual(traceCalledArgs, null); - testLogger.forcedInfo('forcedInfo called %s', 'param1'); - assert.deepStrictEqual(forcedInfoCalledArgs, null); - }); - - it('legacyLogger should log with none', () => { - const testLogger = diagLogLevelFilter( - DiagLogLevel.NONE, - incompleteLogger - ); - - testLogger.terminal('terminal called %s', 'param1'); - assert.deepStrictEqual(terminalCalledArgs, null); - testLogger.critical('critical called %s', 'param1'); - assert.deepStrictEqual(criticalCalledArgs, null); - testLogger.error('error called %s', 'param1'); - assert.deepStrictEqual(errorCalledArgs, null); - testLogger.warn('warn called %s', 'param1'); - assert.deepStrictEqual(warnCalledArgs, null); - testLogger.info('info called %s', 'param1'); - assert.deepStrictEqual(infoCalledArgs, null); - testLogger.debug('debug called %s', 'param1'); - assert.deepStrictEqual(debugCalledArgs, null); - testLogger.trace('trace called %s', 'param1'); - assert.deepStrictEqual(traceCalledArgs, null); - testLogger.forcedInfo('forcedInfo called %s', 'param1'); - assert.deepStrictEqual(forcedInfoCalledArgs, null); + const levelMap: Array<{ + message: string; + level: DiagLogLevel; + ignoreFuncs: Array; + }> = [ + { message: 'ALL', level: DiagLogLevel.ALL, ignoreFuncs: [] }, + { message: 'greater than ALL', level: 32768, ignoreFuncs: [] }, + { message: 'VERBOSE', level: DiagLogLevel.VERBOSE, ignoreFuncs: [] }, + { message: 'DEBUG', level: DiagLogLevel.DEBUG, ignoreFuncs: ['verbose'] }, + { + message: 'INFO', + level: DiagLogLevel.INFO, + ignoreFuncs: ['verbose', 'debug'], + }, + { + message: 'WARN', + level: DiagLogLevel.WARN, + ignoreFuncs: ['verbose', 'debug', 'info'], + }, + { + message: 'ERROR', + level: DiagLogLevel.ERROR, + ignoreFuncs: ['verbose', 'debug', 'info', 'warn'], + }, + { + message: 'CRITICAL', + level: DiagLogLevel.CRITICAL, + ignoreFuncs: ['verbose', 'debug', 'info', 'warn', 'error'], + }, + { + message: 'TERMINAL', + level: DiagLogLevel.TERMINAL, + ignoreFuncs: ['verbose', 'debug', 'info', 'warn', 'error', 'critical'], + }, + { + message: 'between TERMINAL and NONE', + level: -10, + ignoreFuncs: [ + 'verbose', + 'debug', + 'info', + 'warn', + 'error', + 'critical', + 'terminal', + ], + }, + { + message: 'NONE', + level: DiagLogLevel.NONE, + ignoreFuncs: [ + 'verbose', + 'debug', + 'info', + 'warn', + 'error', + 'critical', + 'terminal', + 'forcedInfo', + ], + }, + { + message: 'less than NONE', + level: -1000, + ignoreFuncs: [ + 'verbose', + 'debug', + 'info', + 'warn', + 'error', + 'critical', + 'terminal', + 'forcedInfo', + ], + }, + ]; + + levelMap.forEach(map => { + diagLoggerFunctions.forEach(fName => { + it(`should log ${fName} message with ${map.message} level`, () => { + const testLogger = createLogLevelDiagLogger(map.level, dummyLogger); + testLogger[fName](`${fName} called %s`, 'param1'); + diagLoggerFunctions.forEach(lName => { + if (fName === lName && map.ignoreFuncs.indexOf(lName) === -1) { + assert.deepStrictEqual(calledArgs[lName], [ + `${fName} called %s`, + 'param1', + ]); + } else { + assert.strictEqual(calledArgs[lName], null); + } + }); + }); + + it(`should be noop for null with explicit noop Logger log ${fName} message with ${map.message} level`, () => { + const testLogger = createLogLevelDiagLogger( + map.level, + createNoopDiagLogger() + ); + testLogger[fName](`${fName} called %s`, 'param1'); + diagLoggerFunctions.forEach(lName => { + assert.strictEqual(calledArgs[lName], null); + }); + }); + + it(`should be noop and not throw for null and no default Logger log ${fName} message with ${map.message} level`, () => { + const testLogger = createLogLevelDiagLogger(map.level, null); + testLogger[fName](`${fName} called %s`, 'param1'); + diagLoggerFunctions.forEach(lName => { + assert.strictEqual(calledArgs[lName], null); + }); + }); + + it(`should be noop and not throw for undefined and no default Logger log ${fName} message with ${map.message} level`, () => { + const testLogger = createLogLevelDiagLogger(map.level, undefined); + testLogger[fName](`${fName} called %s`, 'param1'); + diagLoggerFunctions.forEach(lName => { + assert.strictEqual(calledArgs[lName], null); + }); + }); + + it(`should use default logger for undefined and log ${fName} message with ${map.message} level`, () => { + diag.setLogger(dummyLogger); + const testLogger = createLogLevelDiagLogger(map.level, undefined); + testLogger[fName](`${fName} called %s`, 'param1'); + diagLoggerFunctions.forEach(lName => { + if (fName === lName && map.ignoreFuncs.indexOf(lName) === -1) { + assert.deepStrictEqual(calledArgs[lName], [ + `${fName} called %s`, + 'param1', + ]); + } else { + assert.strictEqual(calledArgs[lName], null); + } + }); + }); + + it(`should use default logger for null and log ${fName} message with ${map.message} level`, () => { + diag.setLogger(dummyLogger); + const testLogger = createLogLevelDiagLogger(map.level, null); + testLogger[fName](`${fName} called %s`, 'param1'); + diagLoggerFunctions.forEach(lName => { + if (fName === lName && map.ignoreFuncs.indexOf(lName) === -1) { + assert.deepStrictEqual(calledArgs[lName], [ + `${fName} called %s`, + 'param1', + ]); + } else { + assert.strictEqual(calledArgs[lName], null); + } + }); + }); + + it(`incomplete (legacy) logger should log ${fName} message to ${expectedIncompleteMap[fName]} with ${map.message} level`, () => { + const testLogger = createLogLevelDiagLogger( + map.level, + incompleteLogger + ); + testLogger[fName](`${fName} called %s`, 'param1'); + diagLoggerFunctions.forEach(lName => { + const expectedLog = expectedIncompleteMap[lName]; + if (fName === lName && map.ignoreFuncs.indexOf(lName) === -1) { + assert.deepStrictEqual(calledArgs[expectedLog], [ + `${fName} called %s`, + 'param1', + ]); + } + }); + }); + + it(`diag setLogLevel is ignored for specific logLevel logger and should log ${fName} message with ${map.message} level`, () => { + diag.setLogger(dummyLogger); + diag.setLogLevel(DiagLogLevel.NONE); + + const testLogger = createLogLevelDiagLogger(map.level); + testLogger[fName](`${fName} called %s`, 'param1'); + diagLoggerFunctions.forEach(lName => { + if (fName === lName && map.ignoreFuncs.indexOf(lName) === -1) { + assert.deepStrictEqual(calledArgs[lName], [ + `${fName} called %s`, + 'param1', + ]); + } else { + assert.strictEqual(calledArgs[lName], null); + } + }); + }); + + it(`diag setLogLevel and logger should log ${fName} message with ${map.message} level`, () => { + diag.setLogger(dummyLogger); + diag.setLogLevel(map.level); + diag[fName](`${fName} called %s`, 'param1'); + diagLoggerFunctions.forEach(lName => { + if (fName === lName && map.ignoreFuncs.indexOf(lName) === -1) { + assert.deepStrictEqual(calledArgs[lName], [ + `${fName} called %s`, + 'param1', + ]); + } else { + assert.strictEqual(calledArgs[lName], null); + } + }); + }); + + it(`should not throw with an invalid DiagLogger calling ${fName} with ${map.message} level`, () => { + const invalidLogger = { + debug: 1, + warn: 2, + error: 3, + trace: 4, + info: 5, + log: 6, + }; + + const testLogger = createLogLevelDiagLogger( + map.level, + invalidLogger as any + ); + + testLogger[fName](`${fName} called %s`, 'param1'); + diagLoggerFunctions.forEach(lName => { + assert.strictEqual(calledArgs[lName], null); + }); + }); + }); }); }); }); diff --git a/packages/opentelemetry-api/test/diag/logger.test.ts b/packages/opentelemetry-api/test/diag/logger.test.ts index bc4b6cf3f43..2242908f040 100644 --- a/packages/opentelemetry-api/test/diag/logger.test.ts +++ b/packages/opentelemetry-api/test/diag/logger.test.ts @@ -15,862 +15,83 @@ */ import * as assert from 'assert'; -import { Logger } from '../../src'; +import { diag, DiagLogLevel } from '../../src'; import { DiagLogger, - diagLoggerAdapter, - noopDiagLogger, + createNoopDiagLogger, + diagLoggerFunctions, } from '../../src/diag/logger'; -import { DiagLogLevel, diagLogLevelFilter } from '../../src/diag/logLevel'; -describe('LogLevelFilter DiagLogger', () => { - let terminalCalledArgs: unknown; - let criticalCalledArgs: unknown; - let errorCalledArgs: unknown; - let warnCalledArgs: unknown; - let infoCalledArgs: unknown; - let debugCalledArgs: unknown; - let traceCalledArgs: unknown; - let forcedInfoCalledArgs: unknown; +describe('DiagLogger functions', () => { + const calledArgs: any = { + terminal: null, + critical: null, + error: null, + warn: null, + info: null, + debug: null, + verbose: null, + forcedInfo: null, + }; let dummyLogger: DiagLogger; - let legacyLogger: Logger; - beforeEach(() => { // mock - dummyLogger = { - terminal: (...args: unknown[]) => { - terminalCalledArgs = args; - }, - critical: (...args: unknown[]) => { - criticalCalledArgs = args; - }, - error: (...args: unknown[]) => { - errorCalledArgs = args; - }, - warn: (...args: unknown[]) => { - warnCalledArgs = args; - }, - info: (...args: unknown[]) => { - infoCalledArgs = args; - }, - debug: (...args: unknown[]) => { - debugCalledArgs = args; - }, - trace: (...args: unknown[]) => { - traceCalledArgs = args; - }, - forcedInfo: (...args: unknown[]) => { - forcedInfoCalledArgs = args; - }, - }; - - legacyLogger = { - error: (...args: unknown[]) => { - errorCalledArgs = args; - }, - warn: (...args: unknown[]) => { - warnCalledArgs = args; - }, - info: (...args: unknown[]) => { - infoCalledArgs = args; - }, - debug: (...args: unknown[]) => { - debugCalledArgs = args; - }, - }; + dummyLogger = {} as DiagLogger; + diagLoggerFunctions.forEach(fName => { + dummyLogger[fName] = (...args: unknown[]) => { + calledArgs[fName] = args; + }; + }); }); afterEach(() => { // restore - terminalCalledArgs = null; - criticalCalledArgs = null; - errorCalledArgs = null; - warnCalledArgs = null; - infoCalledArgs = null; - debugCalledArgs = null; - traceCalledArgs = null; - forcedInfoCalledArgs = null; + diagLoggerFunctions.forEach(fName => { + calledArgs[fName] = null; + }); }); describe('constructor', () => { - it('should log with default level', () => { - const testLogger = dummyLogger; - testLogger.terminal('terminal called %s', 'param1'); - assert.deepStrictEqual(terminalCalledArgs, [ - 'terminal called %s', - 'param1', - ]); - testLogger.critical('critical called %s', 'param1'); - assert.deepStrictEqual(criticalCalledArgs, [ - 'critical called %s', - 'param1', - ]); - testLogger.error('error called %s', 'param1'); - assert.deepStrictEqual(errorCalledArgs, ['error called %s', 'param1']); - testLogger.warn('warn called %s', 'param1'); - assert.deepStrictEqual(warnCalledArgs, ['warn called %s', 'param1']); - testLogger.info('info called %s', 'param1'); - assert.deepStrictEqual(infoCalledArgs, ['info called %s', 'param1']); - testLogger.debug('debug called %s', 'param1'); - assert.deepStrictEqual(debugCalledArgs, ['debug called %s', 'param1']); - testLogger.trace('trace called %s', 'param1'); - assert.deepStrictEqual(traceCalledArgs, ['trace called %s', 'param1']); - testLogger.forcedInfo('forcedInfo called %s', 'param1'); - assert.deepStrictEqual(forcedInfoCalledArgs, [ - 'forcedInfo called %s', - 'param1', - ]); - }); - - it('should log with default level', () => { - const testLogger = diagLogLevelFilter( - DiagLogLevel.ALL, - diagLoggerAdapter(dummyLogger) - ); - - testLogger.terminal('terminal called %s', 'param1'); - assert.deepStrictEqual(terminalCalledArgs, [ - 'terminal called %s', - 'param1', - ]); - testLogger.critical('critical called %s', 'param1'); - assert.deepStrictEqual(criticalCalledArgs, [ - 'critical called %s', - 'param1', - ]); - testLogger.error('error called %s', 'param1'); - assert.deepStrictEqual(errorCalledArgs, ['error called %s', 'param1']); - testLogger.warn('warn called %s', 'param1'); - assert.deepStrictEqual(warnCalledArgs, ['warn called %s', 'param1']); - testLogger.info('info called %s', 'param1'); - assert.deepStrictEqual(infoCalledArgs, ['info called %s', 'param1']); - testLogger.debug('debug called %s', 'param1'); - assert.deepStrictEqual(debugCalledArgs, ['debug called %s', 'param1']); - testLogger.trace('trace called %s', 'param1'); - assert.deepStrictEqual(traceCalledArgs, ['trace called %s', 'param1']); - testLogger.forcedInfo('forcedInfo called %s', 'param1'); - assert.deepStrictEqual(forcedInfoCalledArgs, [ - 'forcedInfo called %s', - 'param1', - ]); - }); - - it('should log with default level', () => { - const testLogger = diagLogLevelFilter( - DiagLogLevel.TRACE, - diagLoggerAdapter(dummyLogger) - ); - - testLogger.terminal('terminal called %s', 'param1'); - assert.deepStrictEqual(terminalCalledArgs, [ - 'terminal called %s', - 'param1', - ]); - testLogger.critical('critical called %s', 'param1'); - assert.deepStrictEqual(criticalCalledArgs, [ - 'critical called %s', - 'param1', - ]); - testLogger.error('error called %s', 'param1'); - assert.deepStrictEqual(errorCalledArgs, ['error called %s', 'param1']); - testLogger.warn('warn called %s', 'param1'); - assert.deepStrictEqual(warnCalledArgs, ['warn called %s', 'param1']); - testLogger.info('info called %s', 'param1'); - assert.deepStrictEqual(infoCalledArgs, ['info called %s', 'param1']); - testLogger.debug('debug called %s', 'param1'); - assert.deepStrictEqual(debugCalledArgs, ['debug called %s', 'param1']); - testLogger.trace('trace called %s', 'param1'); - assert.deepStrictEqual(traceCalledArgs, ['trace called %s', 'param1']); - testLogger.forcedInfo('forcedInfo called %s', 'param1'); - assert.deepStrictEqual(forcedInfoCalledArgs, [ - 'forcedInfo called %s', - 'param1', - ]); - }); - - it('should log with debug', () => { - const testLogger = diagLogLevelFilter( - DiagLogLevel.DEBUG, - diagLoggerAdapter(dummyLogger) - ); - - testLogger.terminal('terminal called %s', 'param1'); - assert.deepStrictEqual(terminalCalledArgs, [ - 'terminal called %s', - 'param1', - ]); - testLogger.critical('critical called %s', 'param1'); - assert.deepStrictEqual(criticalCalledArgs, [ - 'critical called %s', - 'param1', - ]); - testLogger.error('error called %s', 'param1'); - assert.deepStrictEqual(errorCalledArgs, ['error called %s', 'param1']); - testLogger.warn('warn called %s', 'param1'); - assert.deepStrictEqual(warnCalledArgs, ['warn called %s', 'param1']); - testLogger.info('info called %s', 'param1'); - assert.deepStrictEqual(infoCalledArgs, ['info called %s', 'param1']); - testLogger.debug('debug called %s', 'param1'); - assert.deepStrictEqual(debugCalledArgs, ['debug called %s', 'param1']); - testLogger.trace('trace called %s', 'param1'); - assert.deepStrictEqual(traceCalledArgs, null); - testLogger.forcedInfo('forcedInfo called %s', 'param1'); - assert.deepStrictEqual(forcedInfoCalledArgs, [ - 'forcedInfo called %s', - 'param1', - ]); - }); - - it('should log with info', () => { - const testLogger = diagLogLevelFilter( - DiagLogLevel.INFO, - diagLoggerAdapter(dummyLogger) - ); - - testLogger.terminal('terminal called %s', 'param1'); - assert.deepStrictEqual(terminalCalledArgs, [ - 'terminal called %s', - 'param1', - ]); - testLogger.critical('critical called %s', 'param1'); - assert.deepStrictEqual(criticalCalledArgs, [ - 'critical called %s', - 'param1', - ]); - testLogger.error('error called %s', 'param1'); - assert.deepStrictEqual(errorCalledArgs, ['error called %s', 'param1']); - testLogger.warn('warn called %s', 'param1'); - assert.deepStrictEqual(warnCalledArgs, ['warn called %s', 'param1']); - testLogger.info('info called %s', 'param1'); - assert.deepStrictEqual(infoCalledArgs, ['info called %s', 'param1']); - testLogger.debug('debug called %s', 'param1'); - assert.deepStrictEqual(debugCalledArgs, null); - testLogger.trace('trace called %s', 'param1'); - assert.deepStrictEqual(traceCalledArgs, null); - testLogger.forcedInfo('forcedInfo called %s', 'param1'); - assert.deepStrictEqual(forcedInfoCalledArgs, [ - 'forcedInfo called %s', - 'param1', - ]); - }); - - it('should log with warning', () => { - const testLogger = diagLogLevelFilter( - DiagLogLevel.WARN, - diagLoggerAdapter(dummyLogger) - ); - - testLogger.terminal('terminal called %s', 'param1'); - assert.deepStrictEqual(terminalCalledArgs, [ - 'terminal called %s', - 'param1', - ]); - testLogger.critical('critical called %s', 'param1'); - assert.deepStrictEqual(criticalCalledArgs, [ - 'critical called %s', - 'param1', - ]); - testLogger.error('error called %s', 'param1'); - assert.deepStrictEqual(errorCalledArgs, ['error called %s', 'param1']); - testLogger.warn('warn called %s', 'param1'); - assert.deepStrictEqual(warnCalledArgs, ['warn called %s', 'param1']); - testLogger.info('info called %s', 'param1'); - assert.deepStrictEqual(infoCalledArgs, null); - testLogger.debug('debug called %s', 'param1'); - assert.deepStrictEqual(debugCalledArgs, null); - testLogger.trace('trace called %s', 'param1'); - assert.deepStrictEqual(traceCalledArgs, null); - testLogger.forcedInfo('forcedInfo called %s', 'param1'); - assert.deepStrictEqual(forcedInfoCalledArgs, [ - 'forcedInfo called %s', - 'param1', - ]); - }); - - it('should log with error', () => { - const testLogger = diagLogLevelFilter( - DiagLogLevel.ERROR, - diagLoggerAdapter(dummyLogger) - ); - - testLogger.terminal('terminal called %s', 'param1'); - assert.deepStrictEqual(terminalCalledArgs, [ - 'terminal called %s', - 'param1', - ]); - testLogger.critical('critical called %s', 'param1'); - assert.deepStrictEqual(criticalCalledArgs, [ - 'critical called %s', - 'param1', - ]); - testLogger.error('error called %s', 'param1'); - assert.deepStrictEqual(errorCalledArgs, ['error called %s', 'param1']); - testLogger.warn('warn called %s', 'param1'); - assert.deepStrictEqual(warnCalledArgs, null); - testLogger.info('info called %s', 'param1'); - assert.deepStrictEqual(infoCalledArgs, null); - testLogger.debug('debug called %s', 'param1'); - assert.deepStrictEqual(debugCalledArgs, null); - testLogger.trace('trace called %s', 'param1'); - assert.deepStrictEqual(traceCalledArgs, null); - testLogger.forcedInfo('forcedInfo called %s', 'param1'); - assert.deepStrictEqual(forcedInfoCalledArgs, [ - 'forcedInfo called %s', - 'param1', - ]); - }); - - it('should log with critical', () => { - const testLogger = diagLogLevelFilter( - DiagLogLevel.CRITICAL, - diagLoggerAdapter(dummyLogger) - ); - - testLogger.terminal('terminal called %s', 'param1'); - assert.deepStrictEqual(terminalCalledArgs, [ - 'terminal called %s', - 'param1', - ]); - testLogger.critical('critical called %s', 'param1'); - assert.deepStrictEqual(criticalCalledArgs, [ - 'critical called %s', - 'param1', - ]); - testLogger.error('error called %s', 'param1'); - assert.deepStrictEqual(errorCalledArgs, null); - testLogger.warn('warn called %s', 'param1'); - assert.deepStrictEqual(warnCalledArgs, null); - testLogger.info('info called %s', 'param1'); - assert.deepStrictEqual(infoCalledArgs, null); - testLogger.debug('debug called %s', 'param1'); - assert.deepStrictEqual(debugCalledArgs, null); - testLogger.trace('trace called %s', 'param1'); - assert.deepStrictEqual(traceCalledArgs, null); - testLogger.forcedInfo('forcedInfo called %s', 'param1'); - assert.deepStrictEqual(forcedInfoCalledArgs, [ - 'forcedInfo called %s', - 'param1', - ]); - }); - - it('should log with terminal', () => { - const testLogger = diagLogLevelFilter( - DiagLogLevel.TERMINAL, - diagLoggerAdapter(dummyLogger) - ); - - testLogger.terminal('terminal called %s', 'param1'); - assert.deepStrictEqual(terminalCalledArgs, [ - 'terminal called %s', - 'param1', - ]); - testLogger.critical('critical called %s', 'param1'); - assert.deepStrictEqual(criticalCalledArgs, null); - testLogger.error('error called %s', 'param1'); - assert.deepStrictEqual(errorCalledArgs, null); - testLogger.warn('warn called %s', 'param1'); - assert.deepStrictEqual(warnCalledArgs, null); - testLogger.info('info called %s', 'param1'); - assert.deepStrictEqual(infoCalledArgs, null); - testLogger.debug('debug called %s', 'param1'); - assert.deepStrictEqual(debugCalledArgs, null); - testLogger.trace('trace called %s', 'param1'); - assert.deepStrictEqual(traceCalledArgs, null); - testLogger.forcedInfo('forcedInfo called %s', 'param1'); - assert.deepStrictEqual(forcedInfoCalledArgs, [ - 'forcedInfo called %s', - 'param1', - ]); - }); - - it('should log with none', () => { - const testLogger = diagLogLevelFilter( - DiagLogLevel.NONE, - diagLoggerAdapter(dummyLogger) - ); - - testLogger.terminal('terminal called %s', 'param1'); - assert.deepStrictEqual(terminalCalledArgs, null); - testLogger.critical('critical called %s', 'param1'); - assert.deepStrictEqual(criticalCalledArgs, null); - testLogger.error('error called %s', 'param1'); - assert.deepStrictEqual(errorCalledArgs, null); - testLogger.warn('warn called %s', 'param1'); - assert.deepStrictEqual(warnCalledArgs, null); - testLogger.info('info called %s', 'param1'); - assert.deepStrictEqual(infoCalledArgs, null); - testLogger.debug('debug called %s', 'param1'); - assert.deepStrictEqual(debugCalledArgs, null); - testLogger.trace('trace called %s', 'param1'); - assert.deepStrictEqual(traceCalledArgs, null); - testLogger.forcedInfo('forcedInfo called %s', 'param1'); - assert.deepStrictEqual(forcedInfoCalledArgs, [ - 'forcedInfo called %s', - 'param1', - ]); - }); - - it('legacyLogger should log with default level', () => { - const testLogger = diagLogLevelFilter( - DiagLogLevel.ALL, - diagLoggerAdapter(legacyLogger) - ); - - testLogger.terminal('terminal called %s', 'param1'); - assert.deepStrictEqual(terminalCalledArgs, null); - assert.deepStrictEqual(errorCalledArgs, ['terminal called %s', 'param1']); - testLogger.critical('critical called %s', 'param1'); - assert.deepStrictEqual(criticalCalledArgs, null); - assert.deepStrictEqual(errorCalledArgs, ['critical called %s', 'param1']); - testLogger.error('error called %s', 'param1'); - assert.deepStrictEqual(errorCalledArgs, ['error called %s', 'param1']); - testLogger.warn('warn called %s', 'param1'); - assert.deepStrictEqual(warnCalledArgs, ['warn called %s', 'param1']); - testLogger.info('info called %s', 'param1'); - assert.deepStrictEqual(infoCalledArgs, ['info called %s', 'param1']); - testLogger.debug('debug called %s', 'param1'); - assert.deepStrictEqual(debugCalledArgs, ['debug called %s', 'param1']); - testLogger.trace('trace called %s', 'param1'); - assert.deepStrictEqual(traceCalledArgs, null); - assert.deepStrictEqual(debugCalledArgs, ['trace called %s', 'param1']); - testLogger.forcedInfo('forcedInfo called %s', 'param1'); - assert.deepStrictEqual(forcedInfoCalledArgs, null); - assert.deepStrictEqual(infoCalledArgs, [ - 'forcedInfo called %s', - 'param1', - ]); - }); - - it('legacyLogger should log with default level', () => { - const testLogger = diagLogLevelFilter( - DiagLogLevel.TRACE, - diagLoggerAdapter(legacyLogger) - ); - - testLogger.terminal('terminal called %s', 'param1'); - assert.deepStrictEqual(terminalCalledArgs, null); - assert.deepStrictEqual(errorCalledArgs, ['terminal called %s', 'param1']); - testLogger.critical('critical called %s', 'param1'); - assert.deepStrictEqual(criticalCalledArgs, null); - assert.deepStrictEqual(errorCalledArgs, ['critical called %s', 'param1']); - testLogger.error('error called %s', 'param1'); - assert.deepStrictEqual(errorCalledArgs, ['error called %s', 'param1']); - testLogger.warn('warn called %s', 'param1'); - assert.deepStrictEqual(warnCalledArgs, ['warn called %s', 'param1']); - testLogger.info('info called %s', 'param1'); - assert.deepStrictEqual(infoCalledArgs, ['info called %s', 'param1']); - testLogger.debug('debug called %s', 'param1'); - assert.deepStrictEqual(debugCalledArgs, ['debug called %s', 'param1']); - testLogger.trace('trace called %s', 'param1'); - assert.deepStrictEqual(traceCalledArgs, null); - assert.deepStrictEqual(debugCalledArgs, ['trace called %s', 'param1']); - testLogger.forcedInfo('forcedInfo called %s', 'param1'); - assert.deepStrictEqual(forcedInfoCalledArgs, null); - assert.deepStrictEqual(infoCalledArgs, [ - 'forcedInfo called %s', - 'param1', - ]); - }); - - it('legacyLogger should log with debug', () => { - const testLogger = diagLogLevelFilter( - DiagLogLevel.DEBUG, - diagLoggerAdapter(legacyLogger) - ); - - testLogger.terminal('terminal called %s', 'param1'); - assert.deepStrictEqual(terminalCalledArgs, null); - assert.deepStrictEqual(errorCalledArgs, ['terminal called %s', 'param1']); - testLogger.critical('critical called %s', 'param1'); - assert.deepStrictEqual(criticalCalledArgs, null); - assert.deepStrictEqual(errorCalledArgs, ['critical called %s', 'param1']); - testLogger.error('error called %s', 'param1'); - assert.deepStrictEqual(errorCalledArgs, ['error called %s', 'param1']); - testLogger.warn('warn called %s', 'param1'); - assert.deepStrictEqual(warnCalledArgs, ['warn called %s', 'param1']); - testLogger.info('info called %s', 'param1'); - assert.deepStrictEqual(infoCalledArgs, ['info called %s', 'param1']); - testLogger.debug('debug called %s', 'param1'); - assert.deepStrictEqual(debugCalledArgs, ['debug called %s', 'param1']); - testLogger.trace('trace called %s', 'param1'); - assert.deepStrictEqual(traceCalledArgs, null); - testLogger.forcedInfo('forcedInfo called %s', 'param1'); - assert.deepStrictEqual(forcedInfoCalledArgs, null); - assert.deepStrictEqual(infoCalledArgs, [ - 'forcedInfo called %s', - 'param1', - ]); - }); - - it('legacyLogger should log with info', () => { - const testLogger = diagLogLevelFilter( - DiagLogLevel.INFO, - diagLoggerAdapter(legacyLogger) - ); - - testLogger.terminal('terminal called %s', 'param1'); - assert.deepStrictEqual(terminalCalledArgs, null); - assert.deepStrictEqual(errorCalledArgs, ['terminal called %s', 'param1']); - testLogger.critical('critical called %s', 'param1'); - assert.deepStrictEqual(criticalCalledArgs, null); - assert.deepStrictEqual(errorCalledArgs, ['critical called %s', 'param1']); - testLogger.error('error called %s', 'param1'); - assert.deepStrictEqual(errorCalledArgs, ['error called %s', 'param1']); - testLogger.warn('warn called %s', 'param1'); - assert.deepStrictEqual(warnCalledArgs, ['warn called %s', 'param1']); - testLogger.info('info called %s', 'param1'); - assert.deepStrictEqual(infoCalledArgs, ['info called %s', 'param1']); - testLogger.debug('debug called %s', 'param1'); - assert.deepStrictEqual(debugCalledArgs, null); - testLogger.trace('trace called %s', 'param1'); - assert.deepStrictEqual(traceCalledArgs, null); - testLogger.forcedInfo('forcedInfo called %s', 'param1'); - assert.deepStrictEqual(forcedInfoCalledArgs, null); - assert.deepStrictEqual(infoCalledArgs, [ - 'forcedInfo called %s', - 'param1', - ]); - }); - - it('legacyLogger should log with warning', () => { - const testLogger = diagLogLevelFilter( - DiagLogLevel.WARN, - diagLoggerAdapter(legacyLogger) - ); - - testLogger.terminal('terminal called %s', 'param1'); - assert.deepStrictEqual(terminalCalledArgs, null); - assert.deepStrictEqual(errorCalledArgs, ['terminal called %s', 'param1']); - testLogger.critical('critical called %s', 'param1'); - assert.deepStrictEqual(criticalCalledArgs, null); - assert.deepStrictEqual(errorCalledArgs, ['critical called %s', 'param1']); - testLogger.error('error called %s', 'param1'); - assert.deepStrictEqual(errorCalledArgs, ['error called %s', 'param1']); - testLogger.warn('warn called %s', 'param1'); - assert.deepStrictEqual(warnCalledArgs, ['warn called %s', 'param1']); - testLogger.info('info called %s', 'param1'); - assert.deepStrictEqual(infoCalledArgs, null); - testLogger.debug('debug called %s', 'param1'); - assert.deepStrictEqual(debugCalledArgs, null); - testLogger.trace('trace called %s', 'param1'); - assert.deepStrictEqual(traceCalledArgs, null); - testLogger.forcedInfo('forcedInfo called %s', 'param1'); - assert.deepStrictEqual(forcedInfoCalledArgs, null); - assert.deepStrictEqual(infoCalledArgs, [ - 'forcedInfo called %s', - 'param1', - ]); - }); - - it('legacyLogger should log with error', () => { - const testLogger = diagLogLevelFilter( - DiagLogLevel.ERROR, - diagLoggerAdapter(legacyLogger) - ); - - testLogger.terminal('terminal called %s', 'param1'); - assert.deepStrictEqual(terminalCalledArgs, null); - assert.deepStrictEqual(errorCalledArgs, ['terminal called %s', 'param1']); - testLogger.critical('critical called %s', 'param1'); - assert.deepStrictEqual(criticalCalledArgs, null); - assert.deepStrictEqual(errorCalledArgs, ['critical called %s', 'param1']); - testLogger.error('error called %s', 'param1'); - assert.deepStrictEqual(errorCalledArgs, ['error called %s', 'param1']); - testLogger.warn('warn called %s', 'param1'); - assert.deepStrictEqual(warnCalledArgs, null); - testLogger.info('info called %s', 'param1'); - assert.deepStrictEqual(infoCalledArgs, null); - testLogger.debug('debug called %s', 'param1'); - assert.deepStrictEqual(debugCalledArgs, null); - testLogger.trace('trace called %s', 'param1'); - assert.deepStrictEqual(traceCalledArgs, null); - testLogger.forcedInfo('forcedInfo called %s', 'param1'); - assert.deepStrictEqual(forcedInfoCalledArgs, null); - assert.deepStrictEqual(infoCalledArgs, [ - 'forcedInfo called %s', - 'param1', - ]); - }); - - it('legacyLogger should log with critical', () => { - const testLogger = diagLogLevelFilter( - DiagLogLevel.CRITICAL, - diagLoggerAdapter(legacyLogger) - ); - - testLogger.terminal('terminal called %s', 'param1'); - assert.deepStrictEqual(terminalCalledArgs, null); - assert.deepStrictEqual(errorCalledArgs, ['terminal called %s', 'param1']); - testLogger.critical('critical called %s', 'param1'); - assert.deepStrictEqual(criticalCalledArgs, null); - assert.deepStrictEqual(errorCalledArgs, ['critical called %s', 'param1']); - testLogger.error('error called %s', 'param1'); - assert.deepStrictEqual(errorCalledArgs, ['critical called %s', 'param1']); - testLogger.warn('warn called %s', 'param1'); - assert.deepStrictEqual(warnCalledArgs, null); - testLogger.info('info called %s', 'param1'); - assert.deepStrictEqual(infoCalledArgs, null); - testLogger.debug('debug called %s', 'param1'); - assert.deepStrictEqual(debugCalledArgs, null); - testLogger.trace('trace called %s', 'param1'); - assert.deepStrictEqual(traceCalledArgs, null); - testLogger.forcedInfo('forcedInfo called %s', 'param1'); - assert.deepStrictEqual(forcedInfoCalledArgs, null); - assert.deepStrictEqual(infoCalledArgs, [ - 'forcedInfo called %s', - 'param1', - ]); - }); - - it('legacyLogger should log with terminal', () => { - const testLogger = diagLogLevelFilter( - DiagLogLevel.TERMINAL, - diagLoggerAdapter(legacyLogger) - ); - - testLogger.terminal('terminal called %s', 'param1'); - assert.deepStrictEqual(terminalCalledArgs, null); - assert.deepStrictEqual(errorCalledArgs, ['terminal called %s', 'param1']); - testLogger.critical('critical called %s', 'param1'); - assert.deepStrictEqual(criticalCalledArgs, null); - testLogger.error('error called %s', 'param1'); - assert.deepStrictEqual(errorCalledArgs, ['terminal called %s', 'param1']); - testLogger.warn('warn called %s', 'param1'); - assert.deepStrictEqual(warnCalledArgs, null); - testLogger.info('info called %s', 'param1'); - assert.deepStrictEqual(infoCalledArgs, null); - testLogger.debug('debug called %s', 'param1'); - assert.deepStrictEqual(debugCalledArgs, null); - testLogger.trace('trace called %s', 'param1'); - assert.deepStrictEqual(traceCalledArgs, null); - testLogger.forcedInfo('forcedInfo called %s', 'param1'); - assert.deepStrictEqual(forcedInfoCalledArgs, null); - assert.deepStrictEqual(infoCalledArgs, [ - 'forcedInfo called %s', - 'param1', - ]); - }); - - it('legacyLogger should log with none', () => { - const testLogger = diagLogLevelFilter( - DiagLogLevel.NONE, - diagLoggerAdapter(legacyLogger) - ); - - testLogger.terminal('terminal called %s', 'param1'); - assert.deepStrictEqual(terminalCalledArgs, null); - testLogger.critical('critical called %s', 'param1'); - assert.deepStrictEqual(criticalCalledArgs, null); - testLogger.error('error called %s', 'param1'); - assert.deepStrictEqual(errorCalledArgs, null); - testLogger.warn('warn called %s', 'param1'); - assert.deepStrictEqual(warnCalledArgs, null); - testLogger.info('info called %s', 'param1'); - assert.deepStrictEqual(infoCalledArgs, null); - testLogger.debug('debug called %s', 'param1'); - assert.deepStrictEqual(debugCalledArgs, null); - testLogger.trace('trace called %s', 'param1'); - assert.deepStrictEqual(traceCalledArgs, null); - testLogger.forcedInfo('forcedInfo called %s', 'param1'); - assert.deepStrictEqual(forcedInfoCalledArgs, null); - assert.deepStrictEqual(infoCalledArgs, [ - 'forcedInfo called %s', - 'param1', - ]); - }); - - it("validate adapter with null doesn't throw", () => { - const testLogger = diagLoggerAdapter(null); - assert.strictEqual(testLogger, null); - }); - - it("validate adapter with undefined doesn't throw", () => { - const testLogger = diagLoggerAdapter(undefined); - assert.strictEqual(testLogger, null); - }); - - it("validate adapter with null doesn't throw", () => { - const testLogger = diagLogLevelFilter( - DiagLogLevel.ALL, - diagLoggerAdapter(null) - ); - - testLogger.terminal('terminal called %s', 'param1'); - assert.deepStrictEqual(terminalCalledArgs, null); - testLogger.critical('critical called %s', 'param1'); - assert.deepStrictEqual(criticalCalledArgs, null); - testLogger.error('error called %s', 'param1'); - assert.deepStrictEqual(errorCalledArgs, null); - testLogger.warn('warn called %s', 'param1'); - assert.deepStrictEqual(warnCalledArgs, null); - testLogger.info('info called %s', 'param1'); - assert.deepStrictEqual(infoCalledArgs, null); - testLogger.debug('debug called %s', 'param1'); - assert.deepStrictEqual(debugCalledArgs, null); - testLogger.trace('trace called %s', 'param1'); - assert.deepStrictEqual(traceCalledArgs, null); - testLogger.forcedInfo('forcedInfo called %s', 'param1'); - assert.deepStrictEqual(forcedInfoCalledArgs, null); - assert.deepStrictEqual(infoCalledArgs, null); - }); - - it("validate with null doesn't throw", () => { - const testLogger = diagLogLevelFilter(DiagLogLevel.ALL, null); - - testLogger.terminal('terminal called %s', 'param1'); - assert.deepStrictEqual(terminalCalledArgs, null); - testLogger.critical('critical called %s', 'param1'); - assert.deepStrictEqual(criticalCalledArgs, null); - testLogger.error('error called %s', 'param1'); - assert.deepStrictEqual(errorCalledArgs, null); - testLogger.warn('warn called %s', 'param1'); - assert.deepStrictEqual(warnCalledArgs, null); - testLogger.info('info called %s', 'param1'); - assert.deepStrictEqual(infoCalledArgs, null); - testLogger.debug('debug called %s', 'param1'); - assert.deepStrictEqual(debugCalledArgs, null); - testLogger.trace('trace called %s', 'param1'); - assert.deepStrictEqual(traceCalledArgs, null); - testLogger.forcedInfo('forcedInfo called %s', 'param1'); - assert.deepStrictEqual(forcedInfoCalledArgs, null); - assert.deepStrictEqual(infoCalledArgs, null); - }); - it("validate adapter with undefined doesn't throw", () => { - const testLogger = diagLogLevelFilter( - DiagLogLevel.ALL, - diagLoggerAdapter(undefined) - ); - - testLogger.terminal('terminal called %s', 'param1'); - assert.deepStrictEqual(terminalCalledArgs, null); - testLogger.critical('critical called %s', 'param1'); - assert.deepStrictEqual(criticalCalledArgs, null); - testLogger.error('error called %s', 'param1'); - assert.deepStrictEqual(errorCalledArgs, null); - testLogger.warn('warn called %s', 'param1'); - assert.deepStrictEqual(warnCalledArgs, null); - testLogger.info('info called %s', 'param1'); - assert.deepStrictEqual(infoCalledArgs, null); - testLogger.debug('debug called %s', 'param1'); - assert.deepStrictEqual(debugCalledArgs, null); - testLogger.trace('trace called %s', 'param1'); - assert.deepStrictEqual(traceCalledArgs, null); - testLogger.forcedInfo('forcedInfo called %s', 'param1'); - assert.deepStrictEqual(forcedInfoCalledArgs, null); - assert.deepStrictEqual(infoCalledArgs, null); - }); - - it("validate with undefined doesn't throw", () => { - const testLogger = diagLogLevelFilter(DiagLogLevel.ALL, undefined); - - testLogger.terminal('terminal called %s', 'param1'); - assert.deepStrictEqual(terminalCalledArgs, null); - testLogger.critical('critical called %s', 'param1'); - assert.deepStrictEqual(criticalCalledArgs, null); - testLogger.error('error called %s', 'param1'); - assert.deepStrictEqual(errorCalledArgs, null); - testLogger.warn('warn called %s', 'param1'); - assert.deepStrictEqual(warnCalledArgs, null); - testLogger.info('info called %s', 'param1'); - assert.deepStrictEqual(infoCalledArgs, null); - testLogger.debug('debug called %s', 'param1'); - assert.deepStrictEqual(debugCalledArgs, null); - testLogger.trace('trace called %s', 'param1'); - assert.deepStrictEqual(traceCalledArgs, null); - testLogger.forcedInfo('forcedInfo called %s', 'param1'); - assert.deepStrictEqual(forcedInfoCalledArgs, null); - assert.deepStrictEqual(infoCalledArgs, null); - }); - - it('should not throw even when legacy logger is invalid', () => { - const invalidConsole = { - debug: 1, - warn: 2, - error: 3, - trace: 4, - info: 5, - log: 6, - }; - - const testLogger = diagLogLevelFilter( - DiagLogLevel.ALL, - diagLoggerAdapter(invalidConsole as any) - ); - - testLogger.terminal('terminal called %s', 'param1'); - assert.deepStrictEqual(terminalCalledArgs, null); - testLogger.critical('critical called %s', 'param1'); - assert.deepStrictEqual(criticalCalledArgs, null); - testLogger.error('error called %s', 'param1'); - assert.deepStrictEqual(errorCalledArgs, null); - testLogger.warn('warn called %s', 'param1'); - assert.deepStrictEqual(warnCalledArgs, null); - testLogger.info('info called %s', 'param1'); - assert.deepStrictEqual(infoCalledArgs, null); - testLogger.debug('debug called %s', 'param1'); - assert.deepStrictEqual(debugCalledArgs, null); - testLogger.trace('trace called %s', 'param1'); - assert.deepStrictEqual(traceCalledArgs, null); - testLogger.forcedInfo('forcedInfo called %s', 'param1'); - assert.deepStrictEqual(forcedInfoCalledArgs, null); - assert.deepStrictEqual(infoCalledArgs, null); - }); - - it('should not throw even when DiagLogger is invalid', () => { - const invalidConsole = { - debug: 1, - warn: 2, - error: 3, - trace: 4, - info: 5, - log: 6, - }; - - const testLogger = diagLogLevelFilter( - DiagLogLevel.ALL, - invalidConsole as any - ); - - testLogger.terminal('terminal called %s', 'param1'); - assert.deepStrictEqual(terminalCalledArgs, null); - testLogger.critical('critical called %s', 'param1'); - assert.deepStrictEqual(criticalCalledArgs, null); - testLogger.error('error called %s', 'param1'); - assert.deepStrictEqual(errorCalledArgs, null); - testLogger.warn('warn called %s', 'param1'); - assert.deepStrictEqual(warnCalledArgs, null); - testLogger.info('info called %s', 'param1'); - assert.deepStrictEqual(infoCalledArgs, null); - testLogger.debug('debug called %s', 'param1'); - assert.deepStrictEqual(debugCalledArgs, null); - testLogger.trace('trace called %s', 'param1'); - assert.deepStrictEqual(traceCalledArgs, null); - testLogger.forcedInfo('forcedInfo called %s', 'param1'); - assert.deepStrictEqual(forcedInfoCalledArgs, null); - assert.deepStrictEqual(infoCalledArgs, null); - }); - - it('A Noop logger should implement all functions and not throw when called', () => { - const testLogger = noopDiagLogger(); - - assert.ok(typeof testLogger.terminal, 'function'); - testLogger.terminal('terminal called %s', 'param1'); - assert.ok(typeof testLogger.critical, 'function'); - testLogger.critical('critical called %s', 'param1'); - assert.ok(typeof testLogger.error, 'function'); - testLogger.error('error called %s', 'param1'); - assert.ok(typeof testLogger.warn, 'function'); - testLogger.warn('warn called %s', 'param1'); - assert.ok(typeof testLogger.info, 'function'); - testLogger.info('info called %s', 'param1'); - assert.ok(typeof testLogger.debug, 'function'); - testLogger.debug('debug called %s', 'param1'); - assert.ok(typeof testLogger.trace, 'function'); - testLogger.trace('trace called %s', 'param1'); - assert.ok(typeof testLogger.forcedInfo, 'function'); - testLogger.forcedInfo('forcedInfo called %s', 'param1'); + diagLoggerFunctions.forEach(fName => { + it(`should log with ${fName} message`, () => { + const testLogger = dummyLogger; + testLogger[fName](`${fName} called %s`, 'param1'); + diagLoggerFunctions.forEach(lName => { + if (fName === lName) { + assert.deepStrictEqual(calledArgs[fName], [ + `${fName} called %s`, + 'param1', + ]); + } else { + assert.strictEqual(calledArgs[lName], null); + } + }); + }); + + it(`diag should log with ${fName} message`, () => { + diag.setLogger(dummyLogger); + diag.setLogLevel(DiagLogLevel.ALL); + diag[fName](`${fName} called %s`, 'param1'); + diagLoggerFunctions.forEach(lName => { + if (fName === lName) { + assert.deepStrictEqual(calledArgs[fName], [ + `${fName} called %s`, + 'param1', + ]); + } else { + assert.strictEqual(calledArgs[lName], null); + } + }); + }); + + it(`NoopLogger should implement all functions and not throw when ${fName} called`, () => { + const testLogger = createNoopDiagLogger(); + + assert.ok(typeof testLogger[fName], 'function'); + testLogger[fName](`${fName} called %s`, 'param1'); + }); }); }); }); diff --git a/packages/opentelemetry-core/src/common/logging-error-handler.ts b/packages/opentelemetry-core/src/common/logging-error-handler.ts index d89055803d5..b3b34852084 100644 --- a/packages/opentelemetry-core/src/common/logging-error-handler.ts +++ b/packages/opentelemetry-core/src/common/logging-error-handler.ts @@ -19,7 +19,7 @@ import { Exception, DiagLogLevel, DiagConsoleLogger, - diagLogLevelFilter, + createLogLevelDiagLogger, } from '@opentelemetry/api'; import { ErrorHandler } from './types'; @@ -30,7 +30,8 @@ import { ErrorHandler } from './types'; */ export function loggingErrorHandler(logger?: Logger): ErrorHandler { logger = - logger ?? diagLogLevelFilter(DiagLogLevel.ERROR, new DiagConsoleLogger()); + logger ?? + createLogLevelDiagLogger(DiagLogLevel.ERROR, new DiagConsoleLogger()); return (ex: Exception) => { logger!.error(stringifyException(ex)); }; From fc00e10f40da1766f6a21e9d0832a8ec4b603095 Mon Sep 17 00:00:00 2001 From: Nev Wylie <54870357+MSNev@users.noreply.github.com> Date: Thu, 4 Feb 2021 11:59:38 -0800 Subject: [PATCH 4/5] fix: correct the usage of default logger for level and update test - fix issue where the global diag level affected trailing tests --- .../opentelemetry-api/src/diag/logLevel.ts | 2 +- .../test/diag/logLevel.test.ts | 58 ++++++++++++++----- 2 files changed, 45 insertions(+), 15 deletions(-) diff --git a/packages/opentelemetry-api/src/diag/logLevel.ts b/packages/opentelemetry-api/src/diag/logLevel.ts index 7ac5eb17774..d85e4cef656 100644 --- a/packages/opentelemetry-api/src/diag/logLevel.ts +++ b/packages/opentelemetry-api/src/diag/logLevel.ts @@ -124,7 +124,7 @@ export function createLogLevelDiagLogger( } if (!logger) { - logger = DiagAPI.instance().getLogger(); + logger = DiagAPI.instance(); } function _filterFunc( diff --git a/packages/opentelemetry-api/test/diag/logLevel.test.ts b/packages/opentelemetry-api/test/diag/logLevel.test.ts index a8a16f1c1b9..4872bbe4f5c 100644 --- a/packages/opentelemetry-api/test/diag/logLevel.test.ts +++ b/packages/opentelemetry-api/test/diag/logLevel.test.ts @@ -65,6 +65,7 @@ describe('LogLevelFilter DiagLogger', () => { beforeEach(() => { // set no logger diag.setLogger(null as any); + diag.setLogLevel(DiagLogLevel.INFO); // mock dummyLogger = {} as DiagLogger; @@ -213,6 +214,7 @@ describe('LogLevelFilter DiagLogger', () => { it(`should use default logger for undefined and log ${fName} message with ${map.message} level`, () => { diag.setLogger(dummyLogger); + diag.setLogLevel(DiagLogLevel.ALL); const testLogger = createLogLevelDiagLogger(map.level, undefined); testLogger[fName](`${fName} called %s`, 'param1'); diagLoggerFunctions.forEach(lName => { @@ -229,6 +231,7 @@ describe('LogLevelFilter DiagLogger', () => { it(`should use default logger for null and log ${fName} message with ${map.message} level`, () => { diag.setLogger(dummyLogger); + diag.setLogLevel(DiagLogLevel.ALL); const testLogger = createLogLevelDiagLogger(map.level, null); testLogger[fName](`${fName} called %s`, 'param1'); diagLoggerFunctions.forEach(lName => { @@ -260,21 +263,48 @@ describe('LogLevelFilter DiagLogger', () => { }); }); - it(`diag setLogLevel is ignored for specific logLevel logger and should log ${fName} message with ${map.message} level`, () => { - diag.setLogger(dummyLogger); - diag.setLogLevel(DiagLogLevel.NONE); + levelMap.forEach(masterLevelMap => { + it(`diag setLogLevel is not ignored when set to ${masterLevelMap.message} and using default logger to log ${fName} message with ${map.message} level`, () => { + diag.setLogger(dummyLogger); + diag.setLogLevel(masterLevelMap.level); - const testLogger = createLogLevelDiagLogger(map.level); - testLogger[fName](`${fName} called %s`, 'param1'); - diagLoggerFunctions.forEach(lName => { - if (fName === lName && map.ignoreFuncs.indexOf(lName) === -1) { - assert.deepStrictEqual(calledArgs[lName], [ - `${fName} called %s`, - 'param1', - ]); - } else { - assert.strictEqual(calledArgs[lName], null); - } + const testLogger = createLogLevelDiagLogger(map.level); + testLogger[fName](`${fName} called %s`, 'param1'); + diagLoggerFunctions.forEach(lName => { + if ( + fName === lName && + map.ignoreFuncs.indexOf(lName) === -1 && + masterLevelMap.ignoreFuncs.indexOf(lName) === -1 + ) { + assert.deepStrictEqual(calledArgs[lName], [ + `${fName} called %s`, + 'param1', + ]); + } else { + assert.strictEqual(calledArgs[lName], null); + } + }); + }); + + it(`diag setLogLevel is ignored when set to ${masterLevelMap.message} when using a specific logger to log ${fName} message with ${map.message} level`, () => { + diag.setLogger(dummyLogger); + diag.setLogLevel(masterLevelMap.level); + + const testLogger = createLogLevelDiagLogger( + map.level, + diag.getLogger() + ); + testLogger[fName](`${fName} called %s`, 'param1'); + diagLoggerFunctions.forEach(lName => { + if (fName === lName && map.ignoreFuncs.indexOf(lName) === -1) { + assert.deepStrictEqual(calledArgs[lName], [ + `${fName} called %s`, + 'param1', + ]); + } else { + assert.strictEqual(calledArgs[lName], null); + } + }); }); }); From a4cb4ba7f957f299c51f1f8e917c4a02f570e099 Mon Sep 17 00:00:00 2001 From: Nev Wylie <54870357+MSNev@users.noreply.github.com> Date: Tue, 9 Feb 2021 15:47:25 -0800 Subject: [PATCH 5/5] fix: address additional review comments summary of changes - removed forcedInfo -> startupInfo - change DiagLogLevel range add STARTUP - removed explicit numeric values on Core.LogLevel --- packages/opentelemetry-api/src/api/diag.ts | 3 +- .../src/diag/consoleLogger.ts | 17 +++++----- .../opentelemetry-api/src/diag/logLevel.ts | 34 ++++++++++--------- packages/opentelemetry-api/src/diag/logger.ts | 18 +++++----- .../test/diag/consoleLogger.test.ts | 2 +- .../test/diag/logLevel.test.ts | 30 ++++++++++++---- .../test/diag/logger.test.ts | 2 +- .../opentelemetry-core/src/common/types.ts | 8 ++--- 8 files changed, 64 insertions(+), 50 deletions(-) diff --git a/packages/opentelemetry-api/src/api/diag.ts b/packages/opentelemetry-api/src/api/diag.ts index d55a5caba56..f9914b3f066 100644 --- a/packages/opentelemetry-api/src/api/diag.ts +++ b/packages/opentelemetry-api/src/api/diag.ts @@ -146,9 +146,8 @@ export class DiagAPI implements DiagLogger { public debug!: DiagLogFunction; public info!: DiagLogFunction; public warn!: DiagLogFunction; + public startupInfo!: DiagLogFunction; public error!: DiagLogFunction; public critical!: DiagLogFunction; public terminal!: DiagLogFunction; - - public forcedInfo!: DiagLogFunction; } diff --git a/packages/opentelemetry-api/src/diag/consoleLogger.ts b/packages/opentelemetry-api/src/diag/consoleLogger.ts index e720dcf84b4..27f7cb9fbb7 100644 --- a/packages/opentelemetry-api/src/diag/consoleLogger.ts +++ b/packages/opentelemetry-api/src/diag/consoleLogger.ts @@ -24,7 +24,7 @@ const consoleMap: { n: keyof DiagLogger; c: keyof Console }[] = [ { n: 'info', c: 'info' }, { n: 'debug', c: 'debug' }, { n: 'verbose', c: 'trace' }, - { n: 'forcedInfo', c: 'info' }, + { n: 'startupInfo', c: 'info' }, ]; /** @@ -73,6 +73,13 @@ export class DiagConsoleLogger implements DiagLogger { /** Log an error scenario that was not expected and caused the requested operation to fail. */ public error!: DiagLogFunction; + /** + * Logs a general informational message that is used for logging component startup and version + * information without causing additional general informational messages when the logging level + * is set to DiagLogLevel.WARN or lower. + */ + public startupInfo!: DiagLogFunction; + /** * Log a warning scenario to inform the developer of an issues that should be investigated. * The requested operation may or may not have succeeded or completed. @@ -102,12 +109,4 @@ export class DiagConsoleLogger implements DiagLogger { * in a production environment. */ public verbose!: DiagLogFunction; - - /** - * Log a general informational message that should always be logged regardless of the - * current {@Link DiagLogLevel) and configured filtering level. This type of logging is - * useful for logging component startup and version information without causing additional - * general informational messages when the logging level is set to DiagLogLevel.WARN or lower. - */ - public forcedInfo!: DiagLogFunction; } diff --git a/packages/opentelemetry-api/src/diag/logLevel.ts b/packages/opentelemetry-api/src/diag/logLevel.ts index d85e4cef656..31241801ca8 100644 --- a/packages/opentelemetry-api/src/diag/logLevel.ts +++ b/packages/opentelemetry-api/src/diag/logLevel.ts @@ -24,38 +24,41 @@ import { DiagLogger, DiagLogFunction, createNoopDiagLogger } from './logger'; * compatibility/migration issues for any implementation that assume the numeric ordering. */ export enum DiagLogLevel { - /** DIagnostic Logging level setting to disable all logging (except and forced logs) */ - NONE = -99, + /** Diagnostic Logging level setting to disable all logging (except and forced logs) */ + NONE = 0, /** * Identifies a terminal situation that would cause the API to completely fail to initialize, * if this type of error is logged functionality of the API is not expected to be functional. */ - TERMINAL = -2, + TERMINAL = 10, /** * Identifies a critical error that needs to be addressed, functionality of the component * that emits this log detail may non-functional. */ - CRITICAL = -1, + CRITICAL = 20, /** Identifies an error scenario */ - ERROR = 0, + ERROR = 30, + + /** Identifies startup and failure (lower) scenarios */ + STARTUP = 40, /** Identifies a warning scenario */ - WARN = 1, + WARN = 50, /** General informational log message */ - INFO = 2, + INFO = 60, /** General debug log message */ - DEBUG = 3, + DEBUG = 70, /** * Detailed trace level logging should only be used for development, should only be set * in a development environment. */ - VERBOSE = 4, + VERBOSE = 80, /** Used to set the logging level to include all logging */ ALL = 9999, @@ -79,11 +82,11 @@ const fallbackLoggerFuncMap: { [n: string]: keyof Logger } = { info: 'info', debug: 'debug', verbose: 'debug', - forcedInfo: 'info', + startupInfo: 'info', }; /** Mapping from DiagLogger function name to logging level. */ -const levelMap: { n: keyof DiagLogger; l: DiagLogLevel; f?: boolean }[] = [ +const levelMap: { n: keyof DiagLogger; l: DiagLogLevel }[] = [ { n: 'terminal', l: DiagLogLevel.TERMINAL }, { n: 'critical', l: DiagLogLevel.CRITICAL }, { n: 'error', l: DiagLogLevel.ERROR }, @@ -91,7 +94,7 @@ const levelMap: { n: keyof DiagLogger; l: DiagLogLevel; f?: boolean }[] = [ { n: 'info', l: DiagLogLevel.INFO }, { n: 'debug', l: DiagLogLevel.DEBUG }, { n: 'verbose', l: DiagLogLevel.VERBOSE }, - { n: 'forcedInfo', l: DiagLogLevel.INFO, f: true }, + { n: 'startupInfo', l: DiagLogLevel.ERROR }, ]; /** @@ -130,10 +133,9 @@ export function createLogLevelDiagLogger( function _filterFunc( theLogger: DiagLogger, funcName: keyof DiagLogger, - theLevel: DiagLogLevel, - isForced?: boolean + theLevel: DiagLogLevel ): DiagLogFunction { - if (isForced || maxLevel >= theLevel) { + if (maxLevel >= theLevel) { return function () { const orgArguments = arguments as unknown; const theFunc = @@ -152,7 +154,7 @@ export function createLogLevelDiagLogger( const newLogger = {} as DiagLogger; for (let i = 0; i < levelMap.length; i++) { const name = levelMap[i].n; - newLogger[name] = _filterFunc(logger, name, levelMap[i].l, levelMap[i].f); + newLogger[name] = _filterFunc(logger, name, levelMap[i].l); } return newLogger; diff --git a/packages/opentelemetry-api/src/diag/logger.ts b/packages/opentelemetry-api/src/diag/logger.ts index 79d31317ccd..6b01ff9b1b9 100644 --- a/packages/opentelemetry-api/src/diag/logger.ts +++ b/packages/opentelemetry-api/src/diag/logger.ts @@ -53,6 +53,13 @@ export interface DiagLogger { /** Log an error scenario that was not expected and caused the requested operation to fail. */ error: DiagLogFunction; + /** + * Logs a general informational message that is used for logging component startup and version + * information without causing additional general informational messages when the logging level + * is set to DiagLogLevel.WARN or lower. + */ + startupInfo: DiagLogFunction; + /** * Log a warning scenario to inform the developer of an issues that should be investigated. * The requested operation may or may not have succeeded or completed. @@ -82,15 +89,6 @@ export interface DiagLogger { * in a production environment. */ verbose: DiagLogFunction; - - /** - * Log a general informational message that should always be logged regardless of the - * current or configured logging level {@Link DiagLogLevel} except when the level is set - * to {@Link DiagLogLevel.NONE). This type of logging is useful for logging component - * startup and version information without causing additional general informational messages - * when the logging level is set to DiagLogLevel.WARN or lower. - */ - forcedInfo: DiagLogFunction; } // DiagLogger implementation @@ -99,10 +97,10 @@ export const diagLoggerFunctions: Array = [ 'debug', 'info', 'warn', + 'startupInfo', 'error', 'critical', 'terminal', - 'forcedInfo', ]; function noopLogFunction() {} diff --git a/packages/opentelemetry-api/test/diag/consoleLogger.test.ts b/packages/opentelemetry-api/test/diag/consoleLogger.test.ts index 9a79265022c..b1150308f86 100644 --- a/packages/opentelemetry-api/test/diag/consoleLogger.test.ts +++ b/packages/opentelemetry-api/test/diag/consoleLogger.test.ts @@ -35,7 +35,7 @@ const expectedConsoleMap: { [n: string]: keyof Console } = { info: 'info', debug: 'debug', verbose: 'trace', - forcedInfo: 'info', + startupInfo: 'info', }; describe('DiagConsoleLogger', () => { diff --git a/packages/opentelemetry-api/test/diag/logLevel.test.ts b/packages/opentelemetry-api/test/diag/logLevel.test.ts index 4872bbe4f5c..b984135e1c6 100644 --- a/packages/opentelemetry-api/test/diag/logLevel.test.ts +++ b/packages/opentelemetry-api/test/diag/logLevel.test.ts @@ -42,7 +42,7 @@ const expectedIncompleteMap: { [n: string]: keyof Console } = { info: 'info', debug: 'debug', verbose: 'debug', - forcedInfo: 'info', + startupInfo: 'info', }; describe('LogLevelFilter DiagLogger', () => { @@ -54,7 +54,7 @@ describe('LogLevelFilter DiagLogger', () => { info: null, debug: null, verbose: null, - forcedInfo: null, + startupInfo: null, }; let dummyLogger: DiagLogger; @@ -118,16 +118,31 @@ describe('LogLevelFilter DiagLogger', () => { { message: 'CRITICAL', level: DiagLogLevel.CRITICAL, - ignoreFuncs: ['verbose', 'debug', 'info', 'warn', 'error'], + ignoreFuncs: [ + 'verbose', + 'debug', + 'info', + 'warn', + 'error', + 'startupInfo', + ], }, { message: 'TERMINAL', level: DiagLogLevel.TERMINAL, - ignoreFuncs: ['verbose', 'debug', 'info', 'warn', 'error', 'critical'], + ignoreFuncs: [ + 'verbose', + 'debug', + 'info', + 'warn', + 'error', + 'critical', + 'startupInfo', + ], }, { message: 'between TERMINAL and NONE', - level: -10, + level: 1, ignoreFuncs: [ 'verbose', 'debug', @@ -136,6 +151,7 @@ describe('LogLevelFilter DiagLogger', () => { 'error', 'critical', 'terminal', + 'startupInfo', ], }, { @@ -149,7 +165,7 @@ describe('LogLevelFilter DiagLogger', () => { 'error', 'critical', 'terminal', - 'forcedInfo', + 'startupInfo', ], }, { @@ -163,7 +179,7 @@ describe('LogLevelFilter DiagLogger', () => { 'error', 'critical', 'terminal', - 'forcedInfo', + 'startupInfo', ], }, ]; diff --git a/packages/opentelemetry-api/test/diag/logger.test.ts b/packages/opentelemetry-api/test/diag/logger.test.ts index 2242908f040..d1629e964e8 100644 --- a/packages/opentelemetry-api/test/diag/logger.test.ts +++ b/packages/opentelemetry-api/test/diag/logger.test.ts @@ -31,7 +31,7 @@ describe('DiagLogger functions', () => { info: null, debug: null, verbose: null, - forcedInfo: null, + startupInfo: null, }; let dummyLogger: DiagLogger; diff --git a/packages/opentelemetry-core/src/common/types.ts b/packages/opentelemetry-core/src/common/types.ts index 8b543c4f0ba..d24f7f1e5c8 100644 --- a/packages/opentelemetry-core/src/common/types.ts +++ b/packages/opentelemetry-core/src/common/types.ts @@ -20,10 +20,10 @@ import { Exception } from '@opentelemetry/api'; * @see {@link DiagLogLevel} from the api */ export enum LogLevel { - ERROR = 0, - WARN = 1, - INFO = 2, - DEBUG = 3, + ERROR, + WARN, + INFO, + DEBUG, } /**