Skip to content

feat(opentelemetry-core,sdk-trace-base,sdk-logs): append exception.cause chain to ATTR_EXCEPTION_STACKTRACE#6634

Open
abhisheksurve45 wants to merge 1 commit into
open-telemetry:mainfrom
abhisheksurve45:feat/exception-cause-stacktrace
Open

feat(opentelemetry-core,sdk-trace-base,sdk-logs): append exception.cause chain to ATTR_EXCEPTION_STACKTRACE#6634
abhisheksurve45 wants to merge 1 commit into
open-telemetry:mainfrom
abhisheksurve45:feat/exception-cause-stacktrace

Conversation

@abhisheksurve45
Copy link
Copy Markdown

Which problem is this PR solving?

JavaScript's Error object supports a cause option since Node.js 16.9+, allowing errors to be chained (e.g., new Error('outer', { cause: innerError })). Previously, OTel JS only captured the top-level error.stack in ATTR_EXCEPTION_STACKTRACE, silently dropping all nested cause stacks.

This PR appends the full cause chain to ATTR_EXCEPTION_STACKTRACE in the format \nCaused by: <stack>, recursively walking the chain. This aligns with how OTel Java already handles cause chains via Throwable.printStackTrace.

Fixes #6423

Short description of the changes

  • Added buildExceptionCauseChain() utility in @opentelemetry/core that walks the cause chain of an exception, appending each level's stack as \nCaused by: <stack>. Handles circular references via a Set.
  • Updated Span.recordException() in sdk-trace-base to use the utility.
  • Updated LogRecordImpl._setException() in sdk-logs to use the utility.

Type of change

  • New feature (non-breaking change which adds functionality)

How Has This Been Tested?

Unit tests added for all three packages:

  • packages/opentelemetry-core/test/common/exception.test.ts — tests for the shared utility covering: single cause, cause with no stack, multi-level chain, circular reference, and primitive/null cause.
  • packages/opentelemetry-sdk-trace-base/test/common/Span.test.ts — tests for single and multi-level cause chain in recordException().
  • experimental/packages/sdk-logs/test/common/LogRecord.test.ts — tests for single and multi-level cause chain in _setException().

Checklist:

  • Followed the style guidelines of this project
  • Unit tests have been added
  • Documentation has been updated

@abhisheksurve45 abhisheksurve45 marked this pull request as ready for review April 26, 2026 20:01
@abhisheksurve45 abhisheksurve45 requested a review from a team as a code owner April 26, 2026 20:01
@abhisheksurve45 abhisheksurve45 changed the title [WIP] feat(opentelemetry-core,sdk-trace-base,sdk-logs): append exception.cause chain to ATTR_EXCEPTION_STACKTRACE feat(opentelemetry-core,sdk-trace-base,sdk-logs): append exception.cause chain to ATTR_EXCEPTION_STACKTRACE Apr 26, 2026
* SPDX-License-Identifier: Apache-2.0
*/

export function buildExceptionCauseChain(cause: unknown): string {
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

IIUC if we could pass the top error here. The only issue would be that the 1st stack will start with the string \nCaused by: producing something like

'\nCaused by: Error: top\n    at top:1:1\nCaused by: Error: mid\n    at mid:1:1\nCaused by: Error: root\n    at root:1:1'

with a couple of changes this function could get the top error and return the whole chain.

I wonder if there is a case where we want to have only the cause chain 🤔

@david-luna
Copy link
Copy Markdown
Contributor

david-luna commented Apr 29, 2026

@abhisheksurve45 thanks for your contribution. I left a comment about the scope of the new function. Maybe other @open-telemetry/javascript-approvers want to give their view.

In the meantime you may want to npm run lint:fix to make the CI happy

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.

Add exception.cause?.stack to the ATTR_EXCEPTION_STACKTRACE attribute

2 participants