Skip to content

Commit 11d854e

Browse files
authored
feat(opentelemetry): Do not capture span events as breadcrumbs (#10612)
This allows us to simplify things, for now - we may add this back later in a more generic way, when/if we add the events to our shared span interface.
1 parent ab410c6 commit 11d854e

File tree

3 files changed

+3
-211
lines changed

3 files changed

+3
-211
lines changed
Lines changed: 2 additions & 79 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,8 @@
1-
import type { Span } from '@opentelemetry/api';
2-
import type { TimedEvent } from '@opentelemetry/sdk-trace-base';
31
import { Scope } from '@sentry/core';
4-
import type { Breadcrumb, ScopeData, SeverityLevel, Span as SentrySpan } from '@sentry/types';
5-
import { dropUndefinedKeys, logger } from '@sentry/utils';
2+
import type { Span as SentrySpan } from '@sentry/types';
3+
import { logger } from '@sentry/utils';
64

75
import { DEBUG_BUILD } from '../debug-build';
8-
import { InternalSentrySemanticAttributes } from '../semanticAttributes';
9-
import { convertOtelTimeToSeconds } from '../utils/convertOtelTimeToSeconds';
10-
import { getActiveSpan } from '../utils/getActiveSpan';
11-
import { getSpanParent } from '../utils/spanData';
12-
import { spanHasEvents } from '../utils/spanTypes';
136

147
/** A fork of the classic scope with some otel specific stuff. */
158
export class OpenTelemetryScope extends Scope {
@@ -64,74 +57,4 @@ export class OpenTelemetryScope extends Scope {
6457

6558
return this;
6659
}
67-
68-
/** @inheritDoc */
69-
public getScopeData(): ScopeData {
70-
const data = super.getScopeData();
71-
72-
data.breadcrumbs = this._getBreadcrumbs();
73-
74-
return data;
75-
}
76-
77-
/**
78-
* @inheritDoc
79-
*/
80-
protected _getBreadcrumbs(): Breadcrumb[] {
81-
const span = getActiveSpan();
82-
const spanBreadcrumbs = span ? getBreadcrumbsForSpan(span) : [];
83-
84-
return spanBreadcrumbs.length > 0 ? this._breadcrumbs.concat(spanBreadcrumbs) : this._breadcrumbs;
85-
}
86-
}
87-
88-
/**
89-
* Get all breadcrumbs for the given span as well as it's parents.
90-
*/
91-
function getBreadcrumbsForSpan(span: Span): Breadcrumb[] {
92-
const events = span ? getOtelEvents(span) : [];
93-
94-
return events.map(otelEventToBreadcrumb);
95-
}
96-
97-
function otelEventToBreadcrumb(event: TimedEvent): Breadcrumb {
98-
const attributes = event.attributes || {};
99-
100-
const type = attributes[InternalSentrySemanticAttributes.BREADCRUMB_TYPE] as string | undefined;
101-
const level = attributes[InternalSentrySemanticAttributes.BREADCRUMB_LEVEL] as SeverityLevel | undefined;
102-
const eventId = attributes[InternalSentrySemanticAttributes.BREADCRUMB_EVENT_ID] as string | undefined;
103-
const category = attributes[InternalSentrySemanticAttributes.BREADCRUMB_CATEGORY] as string | undefined;
104-
const dataStr = attributes[InternalSentrySemanticAttributes.BREADCRUMB_DATA] as string | undefined;
105-
106-
const breadcrumb: Breadcrumb = dropUndefinedKeys({
107-
timestamp: convertOtelTimeToSeconds(event.time),
108-
message: event.name,
109-
type,
110-
level,
111-
event_id: eventId,
112-
category,
113-
});
114-
115-
if (typeof dataStr === 'string') {
116-
try {
117-
const data = JSON.parse(dataStr);
118-
breadcrumb.data = data;
119-
} catch (e) {} // eslint-disable-line no-empty
120-
}
121-
122-
return breadcrumb;
123-
}
124-
125-
function getOtelEvents(span: Span, events: TimedEvent[] = []): TimedEvent[] {
126-
if (spanHasEvents(span)) {
127-
events.push(...span.events);
128-
}
129-
130-
// Go up parent chain and collect events
131-
const parent = getSpanParent(span);
132-
if (parent) {
133-
return getOtelEvents(parent, events);
134-
}
135-
136-
return events;
13760
}
Lines changed: 0 additions & 131 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,6 @@
11
import { makeSession } from '@sentry/core';
2-
import type { Breadcrumb } from '@sentry/types';
32

43
import { OpenTelemetryScope } from '../../src/custom/scope';
5-
import { InternalSentrySemanticAttributes } from '../../src/semanticAttributes';
6-
import { setSpanParent } from '../../src/utils/spanData';
7-
import { createSpan } from '../helpers/createSpan';
8-
import * as GetActiveSpan from './../../src/utils/getActiveSpan';
94

105
describe('NodeExperimentalScope', () => {
116
afterEach(() => {
@@ -93,130 +88,4 @@ describe('NodeExperimentalScope', () => {
9388

9489
expect(scope['_span']).toBeUndefined();
9590
});
96-
97-
describe('_getBreadcrumbs', () => {
98-
it('gets from scope if no span is found', () => {
99-
jest.spyOn(GetActiveSpan, 'getActiveSpan').mockReturnValue(undefined);
100-
101-
const scope = new OpenTelemetryScope();
102-
const breadcrumbs: Breadcrumb[] = [
103-
{ message: 'test1', timestamp: 1234 },
104-
{ message: 'test2', timestamp: 12345 },
105-
{ message: 'test3', timestamp: 12346 },
106-
];
107-
scope['_breadcrumbs'] = breadcrumbs;
108-
109-
expect(scope['_getBreadcrumbs']()).toEqual(breadcrumbs);
110-
});
111-
112-
it('gets events from active span if found', () => {
113-
const span = createSpan();
114-
jest.spyOn(GetActiveSpan, 'getActiveSpan').mockReturnValue(span);
115-
116-
const scope = new OpenTelemetryScope();
117-
118-
const now = Date.now();
119-
120-
span.addEvent('basic event', now);
121-
span.addEvent('breadcrumb event', {}, now + 1000);
122-
span.addEvent(
123-
'breadcrumb event 2',
124-
{
125-
[InternalSentrySemanticAttributes.BREADCRUMB_DATA]: JSON.stringify({ nested: { indeed: true } }),
126-
[InternalSentrySemanticAttributes.BREADCRUMB_TYPE]: 'test-type',
127-
[InternalSentrySemanticAttributes.BREADCRUMB_LEVEL]: 'info',
128-
[InternalSentrySemanticAttributes.BREADCRUMB_EVENT_ID]: 'test-event-id',
129-
[InternalSentrySemanticAttributes.BREADCRUMB_CATEGORY]: 'test-category',
130-
},
131-
now + 3000,
132-
);
133-
span.addEvent(
134-
'breadcrumb event invalid JSON data',
135-
{
136-
[InternalSentrySemanticAttributes.BREADCRUMB_DATA]: 'this is not JSON...',
137-
},
138-
now + 2000,
139-
);
140-
141-
expect(scope['_getBreadcrumbs']()).toEqual([
142-
{ message: 'basic event', timestamp: now / 1000 },
143-
{ message: 'breadcrumb event', timestamp: now / 1000 + 1 },
144-
{
145-
message: 'breadcrumb event 2',
146-
timestamp: now / 1000 + 3,
147-
data: { nested: { indeed: true } },
148-
level: 'info',
149-
event_id: 'test-event-id',
150-
category: 'test-category',
151-
type: 'test-type',
152-
},
153-
{ message: 'breadcrumb event invalid JSON data', timestamp: now / 1000 + 2 },
154-
]);
155-
});
156-
157-
it('gets events from spans up the parent chain if found', () => {
158-
const span = createSpan();
159-
const parentSpan = createSpan();
160-
const rootSpan = createSpan();
161-
jest.spyOn(GetActiveSpan, 'getActiveSpan').mockReturnValue(span);
162-
163-
setSpanParent(span, parentSpan);
164-
setSpanParent(parentSpan, rootSpan);
165-
166-
const scope = new OpenTelemetryScope();
167-
168-
const now = Date.now();
169-
170-
span.addEvent('basic event', now);
171-
parentSpan.addEvent('parent breadcrumb event', {}, now + 1000);
172-
span.addEvent(
173-
'breadcrumb event 2',
174-
{
175-
[InternalSentrySemanticAttributes.BREADCRUMB_DATA]: JSON.stringify({ nested: true }),
176-
},
177-
now + 3000,
178-
);
179-
rootSpan.addEvent(
180-
'breadcrumb event invalid JSON data',
181-
{
182-
[InternalSentrySemanticAttributes.BREADCRUMB_DATA]: 'this is not JSON...',
183-
},
184-
now + 2000,
185-
);
186-
187-
expect(scope['_getBreadcrumbs']()).toEqual([
188-
{ message: 'basic event', timestamp: now / 1000 },
189-
{ message: 'breadcrumb event 2', timestamp: now / 1000 + 3, data: { nested: true } },
190-
{ message: 'parent breadcrumb event', timestamp: now / 1000 + 1 },
191-
{ message: 'breadcrumb event invalid JSON data', timestamp: now / 1000 + 2 },
192-
]);
193-
});
194-
195-
it('combines scope & span breadcrumbs if both exist', () => {
196-
const span = createSpan();
197-
jest.spyOn(GetActiveSpan, 'getActiveSpan').mockReturnValue(span);
198-
199-
const scope = new OpenTelemetryScope();
200-
201-
const breadcrumbs: Breadcrumb[] = [
202-
{ message: 'test1', timestamp: 1234 },
203-
{ message: 'test2', timestamp: 12345 },
204-
{ message: 'test3', timestamp: 12346 },
205-
];
206-
scope['_breadcrumbs'] = breadcrumbs;
207-
208-
const now = Date.now();
209-
210-
span.addEvent('basic event', now);
211-
span.addEvent('breadcrumb event', {}, now + 1000);
212-
213-
expect(scope['_getBreadcrumbs']()).toEqual([
214-
{ message: 'test1', timestamp: 1234 },
215-
{ message: 'test2', timestamp: 12345 },
216-
{ message: 'test3', timestamp: 12346 },
217-
{ message: 'basic event', timestamp: now / 1000 },
218-
{ message: 'breadcrumb event', timestamp: now / 1000 + 1 },
219-
]);
220-
});
221-
});
22291
});

packages/opentelemetry/test/integration/transactions.test.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -174,7 +174,7 @@ describe('Integration | Transactions', () => {
174174
]);
175175
});
176176

177-
it('correctly creates concurrent transaction & spans xxx', async () => {
177+
it('correctly creates concurrent transaction & spans', async () => {
178178
const beforeSendTransaction = jest.fn(() => null);
179179

180180
mockSdkInit({ enableTracing: true, beforeSendTransaction });

0 commit comments

Comments
 (0)