Skip to content

Commit 40aec25

Browse files
committed
feat(opentelemetry): Do not use SentrySpan & Transaction classes
Instead, we build the transaction event manually in the span exporter now. We also ensure to emit `spanStart` & `spanEnd` hooks now in the span processor.
1 parent 24c4eba commit 40aec25

File tree

10 files changed

+240
-420
lines changed

10 files changed

+240
-420
lines changed

packages/core/src/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,7 @@ export {
9191
spanIsSampled,
9292
spanToTraceContext,
9393
getSpanDescendants,
94+
getStatusMessage,
9495
} from './utils/spanUtils';
9596
export { getRootSpan } from './utils/getRootSpan';
9697
export { applySdkMetadata } from './utils/sdkMetadata';

packages/node-experimental/test/integration/transactions.test.ts

Lines changed: 71 additions & 79 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,11 @@ describe('Integration | Transactions', () => {
1515
});
1616

1717
it('correctly creates transaction & spans', async () => {
18-
const beforeSendTransaction = jest.fn(() => null);
18+
const transactions: TransactionEvent[] = [];
19+
const beforeSendTransaction = jest.fn(event => {
20+
transactions.push(event);
21+
return null;
22+
});
1923

2024
mockSdkInit({ enableTracing: true, beforeSendTransaction });
2125

@@ -58,86 +62,74 @@ describe('Integration | Transactions', () => {
5862

5963
await client.flush();
6064

61-
expect(beforeSendTransaction).toHaveBeenCalledTimes(1);
62-
expect(beforeSendTransaction).toHaveBeenLastCalledWith(
63-
expect.objectContaining({
64-
breadcrumbs: [
65-
{ message: 'test breadcrumb 1', timestamp: 123456 },
66-
{ message: 'test breadcrumb 2', timestamp: 123456 },
67-
{ message: 'test breadcrumb 3', timestamp: 123456 },
68-
],
69-
contexts: {
70-
otel: {
71-
attributes: {
72-
'test.outer': 'test value',
73-
'sentry.op': 'test op',
74-
'sentry.origin': 'auto.test',
75-
'sentry.source': 'task',
76-
},
77-
resource: {
78-
'service.name': 'node',
79-
'service.namespace': 'sentry',
80-
'service.version': expect.any(String),
81-
'telemetry.sdk.language': 'nodejs',
82-
'telemetry.sdk.name': 'opentelemetry',
83-
'telemetry.sdk.version': expect.any(String),
84-
},
85-
},
86-
runtime: { name: 'node', version: expect.any(String) },
87-
trace: {
88-
data: {
89-
'otel.kind': 'INTERNAL',
90-
'sentry.op': 'test op',
91-
'sentry.origin': 'auto.test',
92-
'sentry.source': 'task',
93-
'sentry.sample_rate': 1,
94-
'test.outer': 'test value',
95-
},
96-
op: 'test op',
97-
span_id: expect.any(String),
98-
status: 'ok',
99-
trace_id: expect.any(String),
100-
origin: 'auto.test',
101-
},
102-
},
103-
environment: 'production',
104-
event_id: expect.any(String),
105-
platform: 'node',
106-
sdkProcessingMetadata: expect.objectContaining({
107-
dynamicSamplingContext: expect.objectContaining({
108-
environment: 'production',
109-
public_key: expect.any(String),
110-
sample_rate: '1',
111-
sampled: 'true',
112-
trace_id: expect.any(String),
113-
transaction: 'test name',
114-
}),
115-
sampleRate: 1,
116-
spanMetadata: expect.any(Object),
117-
requestPath: 'test-path',
118-
}),
119-
server_name: expect.any(String),
120-
// spans are circular (they have a reference to the transaction), which leads to jest choking on this
121-
// instead we compare them in detail below
122-
spans: [expect.any(Object), expect.any(Object)],
123-
start_timestamp: expect.any(Number),
124-
tags: {
125-
'outer.tag': 'test value',
126-
'test.tag': 'test value',
127-
},
128-
timestamp: expect.any(Number),
129-
transaction: 'test name',
130-
transaction_info: { source: 'task' },
131-
type: 'transaction',
132-
}),
133-
{
134-
event_id: expect.any(String),
65+
expect(transactions).toHaveLength(1);
66+
const transaction = transactions[0];
67+
68+
expect(transaction.breadcrumbs).toEqual([
69+
{ message: 'test breadcrumb 1', timestamp: 123456 },
70+
{ message: 'test breadcrumb 2', timestamp: 123456 },
71+
{ message: 'test breadcrumb 3', timestamp: 123456 },
72+
]);
73+
74+
expect(transaction.contexts?.otel).toEqual({
75+
attributes: {
76+
'test.outer': 'test value',
77+
'sentry.op': 'test op',
78+
'sentry.origin': 'auto.test',
79+
'sentry.source': 'task',
13580
},
136-
);
81+
resource: {
82+
'service.name': 'node',
83+
'service.namespace': 'sentry',
84+
'service.version': expect.any(String),
85+
'telemetry.sdk.language': 'nodejs',
86+
'telemetry.sdk.name': 'opentelemetry',
87+
'telemetry.sdk.version': expect.any(String),
88+
},
89+
});
13790

138-
// Checking the spans here, as they are circular to the transaction...
139-
const runArgs = beforeSendTransaction.mock.calls[0] as unknown as [TransactionEvent, unknown];
140-
const spans = runArgs[0].spans || [];
91+
expect(transaction.contexts?.trace).toEqual({
92+
data: {
93+
'otel.kind': 'INTERNAL',
94+
'sentry.op': 'test op',
95+
'sentry.origin': 'auto.test',
96+
'sentry.source': 'task',
97+
'sentry.sample_rate': 1,
98+
'test.outer': 'test value',
99+
},
100+
op: 'test op',
101+
span_id: expect.any(String),
102+
status: 'ok',
103+
trace_id: expect.any(String),
104+
origin: 'auto.test',
105+
});
106+
107+
expect(transaction.sdkProcessingMetadata?.sampleRate).toEqual(1);
108+
expect(transaction.sdkProcessingMetadata?.requestPath).toEqual('test-path');
109+
expect(transaction.sdkProcessingMetadata?.dynamicSamplingContext).toEqual({
110+
environment: 'production',
111+
public_key: expect.any(String),
112+
sample_rate: '1',
113+
sampled: 'true',
114+
trace_id: expect.any(String),
115+
transaction: 'test name',
116+
});
117+
118+
expect(transaction.environment).toEqual('production');
119+
expect(transaction.event_id).toEqual(expect.any(String));
120+
expect(transaction.start_timestamp).toEqual(expect.any(Number));
121+
expect(transaction.timestamp).toEqual(expect.any(Number));
122+
expect(transaction.transaction).toEqual('test name');
123+
124+
expect(transaction.tags).toEqual({
125+
'outer.tag': 'test value',
126+
'test.tag': 'test value',
127+
});
128+
expect(transaction.transaction_info).toEqual({ source: 'task' });
129+
expect(transaction.type).toEqual('transaction');
130+
131+
expect(transaction.spans).toHaveLength(2);
132+
const spans = transaction.spans || [];
141133

142134
// note: Currently, spans do not have any context/span added to them
143135
// This is the same behavior as for the "regular" SDKs

packages/opentelemetry/src/custom/hubextensions.ts

Lines changed: 0 additions & 33 deletions
This file was deleted.

packages/opentelemetry/src/custom/transaction.ts

Lines changed: 0 additions & 21 deletions
This file was deleted.

packages/opentelemetry/src/index.ts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,6 @@ export { startSpan, startSpanManual, startInactiveSpan, withActiveSpan } from '.
3434
export { setupGlobalHub } from './custom/hub';
3535
// eslint-disable-next-line deprecation/deprecation
3636
export { getCurrentHub } from './custom/getCurrentHub';
37-
export { addTracingExtensions } from './custom/hubextensions';
3837
export { setupEventContextTrace } from './setupEventContextTrace';
3938

4039
export { setOpenTelemetryContextAsyncContextStrategy } from './asyncContextStrategy';

0 commit comments

Comments
 (0)