Skip to content

Commit

Permalink
fix(otel): Add trace info to error events (#6364)
Browse files Browse the repository at this point in the history
  • Loading branch information
AbhiPrasad authored Dec 1, 2022
1 parent 6e915c3 commit 2ed5f8f
Show file tree
Hide file tree
Showing 2 changed files with 73 additions and 8 deletions.
30 changes: 28 additions & 2 deletions packages/opentelemetry-node/src/spanprocessor.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { Context } from '@opentelemetry/api';
import { Context, trace } from '@opentelemetry/api';
import { Span as OtelSpan, SpanProcessor as OtelSpanProcessor } from '@opentelemetry/sdk-trace-base';
import { getCurrentHub } from '@sentry/core';
import { addGlobalEventProcessor, getCurrentHub } from '@sentry/core';
import { Transaction } from '@sentry/tracing';
import { DynamicSamplingContext, Span as SentrySpan, TraceparentData, TransactionContext } from '@sentry/types';
import { logger } from '@sentry/utils';
Expand All @@ -20,6 +20,32 @@ export const SENTRY_SPAN_PROCESSOR_MAP: Map<SentrySpan['spanId'], SentrySpan> =
* the Sentry SDK.
*/
export class SentrySpanProcessor implements OtelSpanProcessor {
public constructor() {
addGlobalEventProcessor(event => {
const otelSpan = trace.getActiveSpan();
if (!otelSpan) {
return event;
}

const otelSpanId = otelSpan.spanContext().spanId;
const sentrySpan = SENTRY_SPAN_PROCESSOR_MAP.get(otelSpanId);

if (!sentrySpan) {
return event;
}

// If event has already set `trace` context, use that one.
// This happens in the case of transaction events.
event.contexts = { trace: sentrySpan.getTraceContext(), ...event.contexts };
const transactionName = sentrySpan.transaction && sentrySpan.transaction.name;
if (transactionName) {
event.tags = { transaction: transactionName, ...event.tags };
}

return event;
});
}

/**
* @inheritDoc
*/
Expand Down
51 changes: 45 additions & 6 deletions packages/opentelemetry-node/test/spanprocessor.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,13 @@ import { SENTRY_SPAN_PROCESSOR_MAP, SentrySpanProcessor } from '../src/spanproce

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

const DEFAULT_NODE_CLIENT_OPTIONS = {
dsn: SENTRY_DSN,
integrations: [],
transport: () => createTransport({ recordDroppedEvent: () => undefined }, _ => resolvedSyncPromise({})),
stackParser: () => [],
};

// Integration Test of SentrySpanProcessor

beforeAll(() => {
Expand All @@ -21,16 +28,12 @@ beforeAll(() => {

describe('SentrySpanProcessor', () => {
let hub: Hub;
let client: NodeClient;
let provider: NodeTracerProvider;
let spanProcessor: SentrySpanProcessor;

beforeEach(() => {
const client = new NodeClient({
dsn: SENTRY_DSN,
integrations: [],
transport: () => createTransport({ recordDroppedEvent: () => undefined }, _ => resolvedSyncPromise({})),
stackParser: () => [],
});
client = new NodeClient(DEFAULT_NODE_CLIENT_OPTIONS);
hub = new Hub(client);
makeMain(hub);

Expand Down Expand Up @@ -711,6 +714,42 @@ describe('SentrySpanProcessor', () => {
});
});
});

it('associates an error to a transaction', () => {
let sentryEvent: any;
let otelSpan: any;

client = new NodeClient({
...DEFAULT_NODE_CLIENT_OPTIONS,
beforeSend: event => {
sentryEvent = event;
return null;
},
});
hub = new Hub(client);
makeMain(hub);

const tracer = provider.getTracer('default');

tracer.startActiveSpan('GET /users', parentOtelSpan => {
tracer.startActiveSpan('SELECT * FROM users;', child => {
hub.captureException(new Error('oh nooooo!'));
otelSpan = child as OtelSpan;
child.end();
});

parentOtelSpan.end();
});

expect(sentryEvent).toBeDefined();
expect(sentryEvent.exception).toBeDefined();
expect(sentryEvent.contexts.trace).toEqual({
description: otelSpan.name,
parent_span_id: otelSpan.parentSpanId,
span_id: otelSpan.spanContext().spanId,
trace_id: otelSpan.spanContext().traceId,
});
});
});

// OTEL expects a custom date format
Expand Down

0 comments on commit 2ed5f8f

Please sign in to comment.