Skip to content

Commit 8214839

Browse files
authored
fix(otel): Add transaction source logic to otel spans (#6160)
1 parent 24cfda2 commit 8214839

File tree

3 files changed

+46
-8
lines changed

3 files changed

+46
-8
lines changed

packages/opentelemetry-node/src/spanprocessor.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -172,9 +172,9 @@ function updateTransactionWithOtelData(transaction: Transaction, otelSpan: OtelS
172172

173173
transaction.setStatus(mapOtelStatus(otelSpan));
174174

175-
const { op, description } = parseSpanDescription(otelSpan);
175+
const { op, description, source } = parseSpanDescription(otelSpan);
176176
transaction.op = op;
177-
transaction.name = description;
177+
transaction.setName(description, source);
178178
}
179179

180180
function convertOtelTimeToSeconds([seconds, nano]: [number, number]): number {

packages/opentelemetry-node/src/utils/parse-otel-span-description.ts

Lines changed: 14 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,12 @@
11
import { AttributeValue, SpanKind } from '@opentelemetry/api';
22
import { Span as OtelSpan } from '@opentelemetry/sdk-trace-base';
33
import { SemanticAttributes } from '@opentelemetry/semantic-conventions';
4+
import { TransactionSource } from '@sentry/types';
45

56
interface SpanDescription {
67
op: string | undefined;
78
description: string;
9+
source: TransactionSource;
810
}
911

1012
/**
@@ -36,6 +38,7 @@ export function parseSpanDescription(otelSpan: OtelSpan): SpanDescription {
3638
return {
3739
op: 'rpc',
3840
description: name,
41+
source: 'route',
3942
};
4043
}
4144

@@ -45,16 +48,17 @@ export function parseSpanDescription(otelSpan: OtelSpan): SpanDescription {
4548
return {
4649
op: 'message',
4750
description: name,
51+
source: 'route',
4852
};
4953
}
5054

5155
// If faas.trigger exists then this is a function as a service span.
5256
const faasTrigger = attributes[SemanticAttributes.FAAS_TRIGGER];
5357
if (faasTrigger) {
54-
return { op: faasTrigger.toString(), description: name };
58+
return { op: faasTrigger.toString(), description: name, source: 'route' };
5559
}
5660

57-
return { op: undefined, description: name };
61+
return { op: undefined, description: name, source: 'custom' };
5862
}
5963

6064
function descriptionForDbSystem(otelSpan: OtelSpan, _dbSystem: AttributeValue): SpanDescription {
@@ -65,7 +69,7 @@ function descriptionForDbSystem(otelSpan: OtelSpan, _dbSystem: AttributeValue):
6569

6670
const description = statement ? statement.toString() : name;
6771

68-
return { op: 'db', description };
72+
return { op: 'db', description, source: 'task' };
6973
}
7074

7175
function descriptionForHttpMethod(otelSpan: OtelSpan, httpMethod: AttributeValue): SpanDescription {
@@ -82,15 +86,19 @@ function descriptionForHttpMethod(otelSpan: OtelSpan, httpMethod: AttributeValue
8286
break;
8387
}
8488

89+
const httpTarget = attributes[SemanticAttributes.HTTP_TARGET];
90+
const httpRoute = attributes[SemanticAttributes.HTTP_ROUTE];
91+
8592
// Ex. /api/users
86-
const httpPath = attributes[SemanticAttributes.HTTP_ROUTE] || attributes[SemanticAttributes.HTTP_TARGET];
93+
const httpPath = httpRoute || httpTarget;
8794

8895
if (!httpPath) {
89-
return { op: opParts.join('.'), description: name };
96+
return { op: opParts.join('.'), description: name, source: 'custom' };
9097
}
9198

9299
// Ex. description="GET /api/users".
93100
const description = `${httpMethod} ${httpPath}`;
101+
const source: TransactionSource = httpRoute ? 'route' : 'url';
94102

95-
return { op: opParts.join('.'), description };
103+
return { op: opParts.join('.'), description, source };
96104
}

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

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -443,6 +443,36 @@ describe('SentrySpanProcessor', () => {
443443
});
444444
});
445445

446+
it('adds transaction source `url` for HTTP_TARGET', async () => {
447+
const tracer = provider.getTracer('default');
448+
449+
tracer.startActiveSpan('GET /users', otelSpan => {
450+
const sentrySpan = getSpanForOtelSpan(otelSpan);
451+
452+
otelSpan.setAttribute(SemanticAttributes.HTTP_METHOD, 'GET');
453+
otelSpan.setAttribute(SemanticAttributes.HTTP_TARGET, '/my/route/123');
454+
455+
otelSpan.end();
456+
457+
expect(sentrySpan?.transaction?.metadata.source).toBe('url');
458+
});
459+
});
460+
461+
it('adds transaction source `url` for HTTP_ROUTE', async () => {
462+
const tracer = provider.getTracer('default');
463+
464+
tracer.startActiveSpan('GET /users', otelSpan => {
465+
const sentrySpan = getSpanForOtelSpan(otelSpan);
466+
467+
otelSpan.setAttribute(SemanticAttributes.HTTP_METHOD, 'GET');
468+
otelSpan.setAttribute(SemanticAttributes.HTTP_ROUTE, '/my/route/:id');
469+
470+
otelSpan.end();
471+
472+
expect(sentrySpan?.transaction?.metadata.source).toBe('route');
473+
});
474+
});
475+
446476
it('updates based on attributes for DB_SYSTEM', async () => {
447477
const tracer = provider.getTracer('default');
448478

0 commit comments

Comments
 (0)