packages/opentelemetry-node/lib/logging.js (68 lines of code) (raw):

/* * Copyright Elasticsearch B.V. and contributors * SPDX-License-Identifier: Apache-2.0 */ // This provides a `log` singleton Logger instance to be used for logging // by this SDK. // // Dev Note: This file is loaded very early in bootstrapping the SDK, typically // before ESM hooks are registered. To keep that code path simple, this file // should keep deps to a minimum. const luggite = require('./luggite'); const _globalThis = typeof globalThis === 'object' ? globalThis : global; const _symLog = Symbol.for('elastic-otel-node.log'); // Dev Note: `OTEL_LOG_LEVEL`s are not standardized. // https://github.com/open-telemetry/opentelemetry-specification/issues/920 // https://github.com/open-telemetry/opentelemetry-specification/issues/2039 const DEFAULT_OTEL_LOG_LEVEL = 'INFO'; const LUGGITE_LEVEL_FROM_OTEL_LOG_LEVEL = { NONE: luggite.FATAL + 1, // TODO: support 'silent' luggite level ERROR: 'error', WARN: 'warn', INFO: 'info', DEBUG: 'debug', VERBOSE: 'trace', ALL: 'trace', }; // As a hack for occasional unergonomic diag logging from upstream OTel JS, we // sometimes filter out specific log messages. This should be used sparingly, // and each case should ideally have an upstream issue to remove it or downgrade // the log level. const FILTER_OUT_DIAG_ERROR_MESSAGES = [ // https://github.com/open-telemetry/opentelemetry-js/pull/5546, @opentelemetry/resources@2.0.1 'Accessing resource attributes before async attributes settled', ]; const FILTER_OUT_DIAG_WARN_MESSAGES = [ // https://github.com/open-telemetry/opentelemetry-js-contrib/pull/2767 'No meter provider, using default', ]; /** * Return an OTel log level to use, based on the OTEL_LOG_LEVEL envvar. * This is normalized to upper-case, and defaults to INFO if the value is * not set or unrecognized. */ function otelLogLevelFromEnv() { let otelLogLevel; if (process.env.OTEL_LOG_LEVEL) { otelLogLevel = process.env.OTEL_LOG_LEVEL.toUpperCase(); if (LUGGITE_LEVEL_FROM_OTEL_LOG_LEVEL[otelLogLevel] === undefined) { otelLogLevel = null; } } if (!otelLogLevel) { otelLogLevel = DEFAULT_OTEL_LOG_LEVEL; } return otelLogLevel; } /** * Create a logger using the level from OTEL_LOG_LEVEL, default 'info'. */ function createLogger() { const level = LUGGITE_LEVEL_FROM_OTEL_LOG_LEVEL[otelLogLevelFromEnv()] || null; return luggite.createLogger({name: 'elastic-otel-node', level}); } /** * Register the singleton `log` to handle OTel `api.diag.*()` calls. */ function registerOTelDiagLogger(api) { // TODO: when luggite supports .child, add a module/component attr for diag log output const diagLevel = otelLogLevelFromEnv(); api.diag.setLogger( { error: (msg, ...args) => { if (FILTER_OUT_DIAG_ERROR_MESSAGES.includes(msg)) { return; } log.error(msg, ...args); }, warn: (msg, ...args) => { if (FILTER_OUT_DIAG_WARN_MESSAGES.includes(msg)) { return; } log.warn(msg, ...args); }, info: log.info.bind(log), debug: log.debug.bind(log), verbose: log.trace.bind(log), }, api.DiagLogLevel[diagLevel] ); } // ---- main line // Create, if necessary, and export a singleton `log` logger instance. if (_globalThis[_symLog] === undefined) { _globalThis[_symLog] = createLogger(); } /** @type {import('./luggite').Logger} */ const log = _globalThis[_symLog]; // ---- exports module.exports = { log, registerOTelDiagLogger, };