Skip to content

fix(ext/telemetry): add exception.* attributes to OTEL log records#32726

Merged
bartlomieju merged 7 commits intodenoland:mainfrom
bartlomieju:fix/otel-log-exception-attributes
Mar 17, 2026
Merged

fix(ext/telemetry): add exception.* attributes to OTEL log records#32726
bartlomieju merged 7 commits intodenoland:mainfrom
bartlomieju:fix/otel-log-exception-attributes

Conversation

@bartlomieju
Copy link
Copy Markdown
Member

Summary

  • When a single Error object is logged via console.log/console.error/etc., the OTEL log record now includes exception.type, exception.message, and exception.stacktrace attributes per the OpenTelemetry semantic conventions for exception logs
  • Only activates when the sole argument has a [ErrorData] internal slot (checked via isNativeError)
  • Non-Error logs and multi-argument calls are unaffected

Closes #27915
Closes #29104

Test plan

  • New spec test log_exception verifies:
    • console.error(new Error(...)) → exception attributes present
    • console.log("plain") → no exception attributes
    • console.error("a", "b") → no exception attributes (multiple args)
  • All existing otel_basic tests pass

🤖 Generated with Claude Code

bartlomieju and others added 2 commits March 14, 2026 17:27
When a single Error object is passed to console.log/error/warn/etc,
the OTEL log record now includes exception.type, exception.message,
and exception.stacktrace attributes per the OpenTelemetry semantic
conventions for exception logs.

Closes denoland#27915
Closes denoland#29104

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Instead of adding a 3rd parameter to Console's printFunc calls (which
broke existing consumers expecting only 2 args), wrap the otel console
methods to capture Error objects in a module-level variable before the
Console stringifies them.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Copy link
Copy Markdown
Contributor

@kajukitli kajukitli left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The PR introduces exception attribute recording for OpenTelemetry console logging, but has a significant race condition vulnerability due to the use of global mutable state (pendingException) to pass exception context between wrapper methods and the logging function. This pattern is unsafe in concurrent JavaScript execution contexts.

[HIGH] ext/telemetry/telemetry.ts:1189: Race condition due to global mutable state pendingException. When multiple console methods are called concurrently (from different async contexts, timers, or callbacks), the exception set by one call could be incorrectly associated with a different log message, or cleared before being processed.

Suggestion: Pass the exception directly through the console wrapping mechanism rather than using global state, or use a synchronous stack-based approach that ties the exception to the specific log call.

[MEDIUM] ext/telemetry/telemetry.ts:1199: Exception is consumed even when not used. pendingException is cleared at the start of otelLog regardless of whether the function completes successfully or returns early, causing exception information to be silently lost.

Suggestion: Only clear pendingException after it has been successfully used to emit a log record.

[MEDIUM] ext/telemetry/telemetry.ts:1193: Exception capture is too restrictive. The wrapper only captures the exception when args.length === 1, so calls like console.error(err, 'additional context') won't record exception attributes even though an error is being logged.

Suggestion: Check if the first argument is a native error regardless of args.length to support logging errors with additional context.

Copy link
Copy Markdown
Contributor

@kajukitli kajukitli left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Reviewed with full repo context. Initial findings didn't hold up on closer inspection. Looks good.

Copy link
Copy Markdown
Contributor

@kajukitli kajukitli left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This PR adds OpenTelemetry exception attribute recording for console error/warn methods. The implementation has a race condition concern with the global pendingException state that could cause exceptions to be misattributed in concurrent scenarios, and the exception capture only works for single-argument Error calls which may be an intentional limitation but could surprise users.

[MEDIUM] ext/telemetry/telemetry.ts:1189: Race condition with global pendingException state. The variable is set in wrapped console methods and consumed in otelLog. In concurrent async scenarios, an exception from one call could be incorrectly associated with a different log call, or lost if another console call happens between setting and consuming.

Suggestion: Consider passing the exception through the Console callback mechanism or using a more context-aware approach instead of relying on module-level global state.

[MEDIUM] ext/telemetry/telemetry.ts:1196: Exception is only captured for single-argument Error calls. console.error(new Error('test'), 'extra info') will NOT capture exception attributes. The test confirms this limitation, but it may surprise users who expect exception metadata when any Error is logged.

Suggestion: Consider capturing exception info when the first argument is a native Error regardless of args.length, if the intent is to capture exception metadata whenever an Error object is logged.

bartlomieju and others added 4 commits March 15, 2026 13:07
Previously exception attributes were only captured when console.error
was called with a single Error argument. Now they are captured whenever
the first argument is a native Error, regardless of additional args.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…ream

Consolidate op_otel_log_exception and op_otel_log_foreign_exception into
op_otel_log and op_otel_log_foreign by adding optional exception string
parameters. This fixes a bug where exception log records were missing the
log.iostream attribute, and extracts a severity_from_level helper to
eliminate the 4x duplicated severity match.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…on test

The expected output was missing log.iostream attributes (present on all
OTEL log records) and exception attributes for the multi-arg error case
(console.error(error, "extra") also sets pendingException).

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…butes

Avoids redundant .to_owned() allocations by consuming the String
directly via .into().

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@bartlomieju bartlomieju merged commit c665693 into denoland:main Mar 17, 2026
220 of 222 checks passed
@bartlomieju bartlomieju deleted the fix/otel-log-exception-attributes branch March 17, 2026 12:44
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

OTEL: Store error message + stack + name separately [otel] logging Error objects should add exception.* attributes to log

3 participants