Skip to content

Commit 2ed5f8f

Browse files
authored
fix(otel): Add trace info to error events (#6364)
1 parent 6e915c3 commit 2ed5f8f

File tree

2 files changed

+73
-8
lines changed

2 files changed

+73
-8
lines changed

packages/opentelemetry-node/src/spanprocessor.ts

Lines changed: 28 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
1-
import { Context } from '@opentelemetry/api';
1+
import { Context, trace } from '@opentelemetry/api';
22
import { Span as OtelSpan, SpanProcessor as OtelSpanProcessor } from '@opentelemetry/sdk-trace-base';
3-
import { getCurrentHub } from '@sentry/core';
3+
import { addGlobalEventProcessor, getCurrentHub } from '@sentry/core';
44
import { Transaction } from '@sentry/tracing';
55
import { DynamicSamplingContext, Span as SentrySpan, TraceparentData, TransactionContext } from '@sentry/types';
66
import { logger } from '@sentry/utils';
@@ -20,6 +20,32 @@ export const SENTRY_SPAN_PROCESSOR_MAP: Map<SentrySpan['spanId'], SentrySpan> =
2020
* the Sentry SDK.
2121
*/
2222
export class SentrySpanProcessor implements OtelSpanProcessor {
23+
public constructor() {
24+
addGlobalEventProcessor(event => {
25+
const otelSpan = trace.getActiveSpan();
26+
if (!otelSpan) {
27+
return event;
28+
}
29+
30+
const otelSpanId = otelSpan.spanContext().spanId;
31+
const sentrySpan = SENTRY_SPAN_PROCESSOR_MAP.get(otelSpanId);
32+
33+
if (!sentrySpan) {
34+
return event;
35+
}
36+
37+
// If event has already set `trace` context, use that one.
38+
// This happens in the case of transaction events.
39+
event.contexts = { trace: sentrySpan.getTraceContext(), ...event.contexts };
40+
const transactionName = sentrySpan.transaction && sentrySpan.transaction.name;
41+
if (transactionName) {
42+
event.tags = { transaction: transactionName, ...event.tags };
43+
}
44+
45+
return event;
46+
});
47+
}
48+
2349
/**
2450
* @inheritDoc
2551
*/

packages/opentelemetry-node/test/spanprocessor.test.ts

Lines changed: 45 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,13 @@ import { SENTRY_SPAN_PROCESSOR_MAP, SentrySpanProcessor } from '../src/spanproce
1313

1414
const SENTRY_DSN = 'https://[email protected]/0';
1515

16+
const DEFAULT_NODE_CLIENT_OPTIONS = {
17+
dsn: SENTRY_DSN,
18+
integrations: [],
19+
transport: () => createTransport({ recordDroppedEvent: () => undefined }, _ => resolvedSyncPromise({})),
20+
stackParser: () => [],
21+
};
22+
1623
// Integration Test of SentrySpanProcessor
1724

1825
beforeAll(() => {
@@ -21,16 +28,12 @@ beforeAll(() => {
2128

2229
describe('SentrySpanProcessor', () => {
2330
let hub: Hub;
31+
let client: NodeClient;
2432
let provider: NodeTracerProvider;
2533
let spanProcessor: SentrySpanProcessor;
2634

2735
beforeEach(() => {
28-
const client = new NodeClient({
29-
dsn: SENTRY_DSN,
30-
integrations: [],
31-
transport: () => createTransport({ recordDroppedEvent: () => undefined }, _ => resolvedSyncPromise({})),
32-
stackParser: () => [],
33-
});
36+
client = new NodeClient(DEFAULT_NODE_CLIENT_OPTIONS);
3437
hub = new Hub(client);
3538
makeMain(hub);
3639

@@ -711,6 +714,42 @@ describe('SentrySpanProcessor', () => {
711714
});
712715
});
713716
});
717+
718+
it('associates an error to a transaction', () => {
719+
let sentryEvent: any;
720+
let otelSpan: any;
721+
722+
client = new NodeClient({
723+
...DEFAULT_NODE_CLIENT_OPTIONS,
724+
beforeSend: event => {
725+
sentryEvent = event;
726+
return null;
727+
},
728+
});
729+
hub = new Hub(client);
730+
makeMain(hub);
731+
732+
const tracer = provider.getTracer('default');
733+
734+
tracer.startActiveSpan('GET /users', parentOtelSpan => {
735+
tracer.startActiveSpan('SELECT * FROM users;', child => {
736+
hub.captureException(new Error('oh nooooo!'));
737+
otelSpan = child as OtelSpan;
738+
child.end();
739+
});
740+
741+
parentOtelSpan.end();
742+
});
743+
744+
expect(sentryEvent).toBeDefined();
745+
expect(sentryEvent.exception).toBeDefined();
746+
expect(sentryEvent.contexts.trace).toEqual({
747+
description: otelSpan.name,
748+
parent_span_id: otelSpan.parentSpanId,
749+
span_id: otelSpan.spanContext().spanId,
750+
trace_id: otelSpan.spanContext().traceId,
751+
});
752+
});
714753
});
715754

716755
// OTEL expects a custom date format

0 commit comments

Comments
 (0)