From a078aa4817efaa7dff36bf6eed542884ebbb5837 Mon Sep 17 00:00:00 2001 From: Martin Kuba Date: Thu, 29 Jan 2026 17:52:14 -0800 Subject: [PATCH 1/2] added suppress logging mechanism to support console instrumentations --- .../src/diag/SuppressedDiagLogger.ts | 67 +++++++++++++++++++ .../src/diag/suppress-logging.ts | 33 +++++++++ packages/opentelemetry-core/src/index.ts | 6 ++ 3 files changed, 106 insertions(+) create mode 100644 packages/opentelemetry-core/src/diag/SuppressedDiagLogger.ts create mode 100644 packages/opentelemetry-core/src/diag/suppress-logging.ts diff --git a/packages/opentelemetry-core/src/diag/SuppressedDiagLogger.ts b/packages/opentelemetry-core/src/diag/SuppressedDiagLogger.ts new file mode 100644 index 00000000000..508ff60ab34 --- /dev/null +++ b/packages/opentelemetry-core/src/diag/SuppressedDiagLogger.ts @@ -0,0 +1,67 @@ +/* + * 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 { context, DiagLogger, DiagLogFunction } from '@opentelemetry/api'; +import { suppressLogging } from './suppress-logging'; + +// Internal class - not exported +class SuppressedDiagLogger implements DiagLogger { + private _logger: DiagLogger; + + constructor(logger: DiagLogger) { + this._logger = logger; + } + + get error(): DiagLogFunction { + return this._proxy('error'); + } + + get warn(): DiagLogFunction { + return this._proxy('warn'); + } + + get info(): DiagLogFunction { + return this._proxy('info'); + } + + get debug(): DiagLogFunction { + return this._proxy('debug'); + } + + get verbose(): DiagLogFunction { + return this._proxy('verbose'); + } + + private _proxy(method: keyof DiagLogger): DiagLogFunction { + return (...args) => { + context.with(suppressLogging(context.active()), () => { + this._logger[method](...args); + }); + }; + } +} + +/** + * Creates a DiagLogger that wraps the provided logger and sets the logging + * suppression context before each log call. This is useful for preventing + * infinite loops when console instrumentations capture diag API calls. + * + * @param logger - The DiagLogger to wrap + * @returns A new DiagLogger that suppresses logging context during calls + */ +export function createSuppressedDiagLogger(logger: DiagLogger): DiagLogger { + return new SuppressedDiagLogger(logger); +} diff --git a/packages/opentelemetry-core/src/diag/suppress-logging.ts b/packages/opentelemetry-core/src/diag/suppress-logging.ts new file mode 100644 index 00000000000..5cb8eb9df75 --- /dev/null +++ b/packages/opentelemetry-core/src/diag/suppress-logging.ts @@ -0,0 +1,33 @@ +/* + * 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 { Context, createContextKey } from '@opentelemetry/api'; + +const SUPPRESS_LOGGING_KEY = createContextKey( + 'OpenTelemetry SDK Context Key SUPPRESS_LOGGING' +); + +export function suppressLogging(context: Context): Context { + return context.setValue(SUPPRESS_LOGGING_KEY, true); +} + +export function unsuppressLogging(context: Context): Context { + return context.deleteValue(SUPPRESS_LOGGING_KEY); +} + +export function isLoggingSuppressed(context: Context): boolean { + return context.getValue(SUPPRESS_LOGGING_KEY) === true; +} diff --git a/packages/opentelemetry-core/src/index.ts b/packages/opentelemetry-core/src/index.ts index 2a14ace80c9..3042f8df62a 100644 --- a/packages/opentelemetry-core/src/index.ts +++ b/packages/opentelemetry-core/src/index.ts @@ -71,6 +71,12 @@ export { suppressTracing, unsuppressTracing, } from './trace/suppress-tracing'; +export { + isLoggingSuppressed, + suppressLogging, + unsuppressLogging, +} from './diag/suppress-logging'; +export { createSuppressedDiagLogger } from './diag/SuppressedDiagLogger'; export { TraceState } from './trace/TraceState'; export { merge } from './utils/merge'; export { TimeoutError, callWithTimeout } from './utils/timeout'; From 8d3f3cbd2b198f2684ad86f30749e88d8a3e0663 Mon Sep 17 00:00:00 2001 From: Martin Kuba Date: Wed, 11 Feb 2026 09:59:30 -0800 Subject: [PATCH 2/2] changed to use global variable instead of context --- .../src/diag/SuppressedDiagLogger.ts | 14 ++++++++++---- .../src/diag/suppress-logging.ts | 18 +++++++----------- 2 files changed, 17 insertions(+), 15 deletions(-) diff --git a/packages/opentelemetry-core/src/diag/SuppressedDiagLogger.ts b/packages/opentelemetry-core/src/diag/SuppressedDiagLogger.ts index 508ff60ab34..24d751c3f6e 100644 --- a/packages/opentelemetry-core/src/diag/SuppressedDiagLogger.ts +++ b/packages/opentelemetry-core/src/diag/SuppressedDiagLogger.ts @@ -14,8 +14,8 @@ * limitations under the License. */ -import { context, DiagLogger, DiagLogFunction } from '@opentelemetry/api'; -import { suppressLogging } from './suppress-logging'; +import { DiagLogger, DiagLogFunction } from '@opentelemetry/api'; +import { isLoggingSuppressed, suppressLogging, unsuppressLogging } from './suppress-logging'; // Internal class - not exported class SuppressedDiagLogger implements DiagLogger { @@ -47,9 +47,15 @@ class SuppressedDiagLogger implements DiagLogger { private _proxy(method: keyof DiagLogger): DiagLogFunction { return (...args) => { - context.with(suppressLogging(context.active()), () => { + const wasSuppressed = isLoggingSuppressed(); + suppressLogging(); + try { this._logger[method](...args); - }); + } finally { + if (!wasSuppressed) { + unsuppressLogging(); + } + } }; } } diff --git a/packages/opentelemetry-core/src/diag/suppress-logging.ts b/packages/opentelemetry-core/src/diag/suppress-logging.ts index 5cb8eb9df75..d03860282e0 100644 --- a/packages/opentelemetry-core/src/diag/suppress-logging.ts +++ b/packages/opentelemetry-core/src/diag/suppress-logging.ts @@ -14,20 +14,16 @@ * limitations under the License. */ -import { Context, createContextKey } from '@opentelemetry/api'; +let _loggingSuppressed = false; -const SUPPRESS_LOGGING_KEY = createContextKey( - 'OpenTelemetry SDK Context Key SUPPRESS_LOGGING' -); - -export function suppressLogging(context: Context): Context { - return context.setValue(SUPPRESS_LOGGING_KEY, true); +export function suppressLogging(): void { + _loggingSuppressed = true; } -export function unsuppressLogging(context: Context): Context { - return context.deleteValue(SUPPRESS_LOGGING_KEY); +export function unsuppressLogging(): void { + _loggingSuppressed = false; } -export function isLoggingSuppressed(context: Context): boolean { - return context.getValue(SUPPRESS_LOGGING_KEY) === true; +export function isLoggingSuppressed(): boolean { + return _loggingSuppressed; }