Skip to content

Commit c9bd9dc

Browse files
committed
more wip work
1 parent e0587d8 commit c9bd9dc

File tree

6 files changed

+206
-109
lines changed

6 files changed

+206
-109
lines changed

packages/opentelemetry-node/package.json

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -54,5 +54,12 @@
5454
},
5555
"volta": {
5656
"extends": "../../package.json"
57-
}
57+
},
58+
"sideEffects": [
59+
"./cjs/index.js",
60+
"./esm/index.js",
61+
"./build/npm/cjs/index.js",
62+
"./build/npm/esm/index.js",
63+
"./src/index.ts"
64+
]
5865
}
Lines changed: 2 additions & 100 deletions
Original file line numberDiff line numberDiff line change
@@ -1,101 +1,3 @@
1-
import { Context } from '@opentelemetry/api';
2-
import { Span as OtelSpan, SpanProcessor as OtelSpanProcessor } from '@opentelemetry/sdk-trace-base';
3-
import { getCurrentHub } from '@sentry/core';
4-
import { Span as SentrySpan } from '@sentry/types';
1+
import '@sentry/tracing';
52

6-
/**
7-
* Converts OpenTelemetry Spans to Sentry Spans and sends them to Sentry via
8-
* the Sentry SDK.
9-
*/
10-
export class SentrySpanProcessor implements OtelSpanProcessor {
11-
private readonly _map: Record<SentrySpan['spanId'], [SentrySpan, SentrySpan | undefined]> = {};
12-
13-
/**
14-
* @inheritDoc
15-
*/
16-
public onStart(otelSpan: OtelSpan, _parentContext: Context): void {
17-
const hub = getCurrentHub();
18-
if (!hub) {
19-
return;
20-
}
21-
const scope = hub.getScope();
22-
if (!scope) {
23-
return;
24-
}
25-
26-
// if isSentryRequest(otelSpan) return;
27-
28-
const otelSpanId = otelSpan.spanContext().spanId;
29-
30-
const sentryParentSpan = scope.getSpan();
31-
if (sentryParentSpan) {
32-
const sentryChildSpan = sentryParentSpan.startChild({
33-
description: otelSpan.name,
34-
// instrumentor: 'otel',
35-
startTimestamp: otelSpan.startTime[0],
36-
});
37-
sentryChildSpan.spanId = otelSpanId;
38-
39-
this._map[otelSpanId] = [sentryChildSpan, sentryParentSpan];
40-
scope.setSpan(sentryChildSpan);
41-
} else {
42-
// const traceCtx = getTraceData(otelSpan);
43-
const transaction = hub.startTransaction({
44-
name: otelSpan.name,
45-
// ...traceCtx,
46-
// instrumentor: 'otel',
47-
startTimestamp: otelSpan.startTime[0],
48-
});
49-
transaction.spanId = otelSpanId;
50-
51-
this._map[otelSpanId] = [transaction, undefined];
52-
scope.setSpan(transaction);
53-
}
54-
}
55-
56-
/**
57-
* @inheritDoc
58-
*/
59-
public onEnd(otelSpan: OtelSpan): void {
60-
const hub = getCurrentHub();
61-
if (!hub) {
62-
return;
63-
}
64-
const scope = hub.getScope();
65-
if (!scope) {
66-
return;
67-
}
68-
69-
const otelSpanId = otelSpan.spanContext().spanId;
70-
const mapVal = this._map[otelSpanId];
71-
72-
if (mapVal) {
73-
const [sentrySpan, sentryParentSpan] = mapVal;
74-
75-
// updateSpanWithOtelData(sentrySpan, otelSpan);
76-
77-
sentrySpan.finish(otelSpan.endTime[0]);
78-
scope.setSpan(sentryParentSpan);
79-
// eslint-disable-next-line @typescript-eslint/no-dynamic-delete
80-
delete this._map[otelSpanId];
81-
}
82-
}
83-
84-
/**
85-
* @inheritDoc
86-
*/
87-
public shutdown(): Promise<void> {
88-
return Promise.resolve();
89-
}
90-
91-
/**
92-
* @inheritDoc
93-
*/
94-
public async forceFlush(): Promise<void> {
95-
const client = getCurrentHub().getClient();
96-
if (client) {
97-
return client.flush().then();
98-
}
99-
return Promise.resolve();
100-
}
101-
}
3+
export { SentrySpanProcessor } from './spanprocessor';
Lines changed: 115 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,115 @@
1+
import { Context } from '@opentelemetry/api';
2+
import { Span as OtelSpan, SpanProcessor as OtelSpanProcessor } from '@opentelemetry/sdk-trace-base';
3+
import { getCurrentHub } from '@sentry/core';
4+
import { Span as SentrySpan, TransactionContext } from '@sentry/types';
5+
6+
/**
7+
* Converts OpenTelemetry Spans to Sentry Spans and sends them to Sentry via
8+
* the Sentry SDK.
9+
*/
10+
export class SentrySpanProcessor implements OtelSpanProcessor {
11+
private readonly _map: Record<SentrySpan['spanId'], [SentrySpan, SentrySpan | undefined]> = {};
12+
13+
/**
14+
* @inheritDoc
15+
*/
16+
public onStart(otelSpan: OtelSpan, _parentContext: Context): void {
17+
const hub = getCurrentHub();
18+
if (!hub) {
19+
return;
20+
}
21+
const scope = hub.getScope();
22+
if (!scope) {
23+
return;
24+
}
25+
26+
// if isSentryRequest(otelSpan) return;
27+
28+
const otelSpanId = otelSpan.spanContext().spanId;
29+
30+
const sentryParentSpan = scope.getSpan();
31+
if (sentryParentSpan) {
32+
const sentryChildSpan = sentryParentSpan.startChild({
33+
description: otelSpan.name,
34+
// instrumentor: 'otel',
35+
startTimestamp: otelSpan.startTime[0],
36+
});
37+
sentryChildSpan.spanId = otelSpanId;
38+
console.log(sentryParentSpan, sentryChildSpan, otelSpan);
39+
40+
this._map[otelSpanId] = [sentryChildSpan, sentryParentSpan];
41+
scope.setSpan(sentryChildSpan);
42+
} else {
43+
const traceCtx = getTraceData(otelSpan);
44+
const transaction = hub.startTransaction({
45+
name: otelSpan.name,
46+
...traceCtx,
47+
// instrumentor: 'otel',
48+
startTimestamp: otelSpan.startTime[0],
49+
});
50+
transaction.spanId = otelSpanId;
51+
52+
this._map[otelSpanId] = [transaction, undefined];
53+
54+
scope.setSpan(transaction);
55+
}
56+
}
57+
58+
/**
59+
* @inheritDoc
60+
*/
61+
public onEnd(otelSpan: OtelSpan): void {
62+
const hub = getCurrentHub();
63+
if (!hub) {
64+
return;
65+
}
66+
const scope = hub.getScope();
67+
if (!scope) {
68+
return;
69+
}
70+
71+
const otelSpanId = otelSpan.spanContext().spanId;
72+
const mapVal = this._map[otelSpanId];
73+
74+
if (mapVal) {
75+
const [sentrySpan, sentryParentSpan] = mapVal;
76+
77+
// updateSpanWithOtelData(sentrySpan, otelSpan);
78+
79+
sentrySpan.finish(otelSpan.endTime[0]);
80+
scope.setSpan(sentryParentSpan);
81+
// eslint-disable-next-line @typescript-eslint/no-dynamic-delete
82+
delete this._map[otelSpanId];
83+
}
84+
}
85+
86+
/**
87+
* @inheritDoc
88+
*/
89+
public shutdown(): Promise<void> {
90+
return Promise.resolve();
91+
}
92+
93+
/**
94+
* @inheritDoc
95+
*/
96+
public async forceFlush(): Promise<void> {
97+
const client = getCurrentHub().getClient();
98+
if (client) {
99+
return client.flush().then();
100+
}
101+
return Promise.resolve();
102+
}
103+
}
104+
105+
function getTraceData(otelSpan: OtelSpan): Partial<TransactionContext> {
106+
const spanContext = otelSpan.spanContext();
107+
const traceId = spanContext.traceId;
108+
const spanId = spanContext.spanId;
109+
110+
const parentSpanId = otelSpan.parentSpanId;
111+
return { spanId, traceId, parentSpanId };
112+
}
113+
114+
// function updateSpanWithOtelData(sentrySpan: SentrySpan, otelSpan: OtelSpan): void {
115+
// }

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

Lines changed: 0 additions & 7 deletions
This file was deleted.
Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
import * as OpenTelemetry from '@opentelemetry/api';
2+
import { BasicTracerProvider, Span as OtelSpan } from '@opentelemetry/sdk-trace-base';
3+
import { Hub, makeMain } from '@sentry/core';
4+
import { addExtensionMethods, Span as SentrySpan, Transaction } from '@sentry/tracing';
5+
6+
import { SentrySpanProcessor } from '../src/spanprocessor';
7+
8+
// Integration Test of SentrySpanProcessor
9+
10+
beforeAll(() => {
11+
addExtensionMethods();
12+
});
13+
14+
describe('SentrySpanProcessor', () => {
15+
let hub: Hub;
16+
beforeEach(() => {
17+
hub = new Hub();
18+
makeMain(hub);
19+
20+
const provider = new BasicTracerProvider();
21+
provider.addSpanProcessor(new SentrySpanProcessor());
22+
provider.register();
23+
});
24+
25+
describe('onStart', () => {
26+
it('create a transaction', () => {
27+
const otelSpan = OpenTelemetry.trace.getTracer('default').startSpan('GET /users') as OtelSpan;
28+
const sentrySpanTransaction = hub.getScope()?.getSpan() as Transaction;
29+
expect(sentrySpanTransaction).toBeInstanceOf(Transaction);
30+
31+
// Make sure name is set
32+
expect(sentrySpanTransaction?.name).toBe('GET /users');
33+
34+
// Enforce we use otel timestamps
35+
expect(sentrySpanTransaction.startTimestamp).toEqual(otelSpan.startTime[0]);
36+
37+
// Check for otel trace context
38+
expect(sentrySpanTransaction.traceId).toEqual(otelSpan.spanContext().traceId);
39+
expect(sentrySpanTransaction.parentSpanId).toEqual(otelSpan.parentSpanId);
40+
expect(sentrySpanTransaction.spanId).toEqual(otelSpan.spanContext().spanId);
41+
});
42+
43+
it.only('creates a child span if there is a running transaction', () => {
44+
const tracer = OpenTelemetry.trace.getTracer('default');
45+
46+
tracer.startActiveSpan('GET /users', parentOtelSpan => {
47+
// console.log((parentOtelSpan as any).spanContext());
48+
// console.log(hub.getScope()?.getSpan()?.traceId);
49+
tracer.startActiveSpan('SELECT * FROM users;', child => {
50+
const childOtelSpan = child as OtelSpan;
51+
52+
const sentrySpan = hub.getScope()?.getSpan();
53+
expect(sentrySpan).toBeInstanceOf(SentrySpan);
54+
// console.log(hub.getScope()?.getSpan()?.traceId);
55+
// console.log(sentrySpan);
56+
57+
// Make sure name is set
58+
expect(sentrySpan?.description).toBe('SELECT * FROM users;');
59+
60+
// Enforce we use otel timestamps
61+
expect(sentrySpan?.startTimestamp).toEqual(childOtelSpan.startTime[0]);
62+
63+
// Check for otel trace context
64+
expect(sentrySpan?.spanId).toEqual(childOtelSpan.spanContext().spanId);
65+
66+
childOtelSpan.end();
67+
});
68+
69+
parentOtelSpan.end();
70+
});
71+
});
72+
});
73+
74+
// it('Creates a transaction if there is no running ', () => {
75+
// const otelSpan = OpenTelemetry.trace.getTracer('default').startSpan('GET /users') as OtelSpan;
76+
// processor.onStart(otelSpan, OpenTelemetry.context.active());
77+
78+
// const sentrySpanTransaction = hub.getScope()?.getSpan() as Transaction;
79+
// });
80+
});

packages/tracing/src/span.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -153,7 +153,7 @@ export class Span implements SpanInterface {
153153
* @inheritDoc
154154
*/
155155
public startChild(
156-
spanContext?: Pick<SpanContext, Exclude<keyof SpanContext, 'spanId' | 'sampled' | 'traceId' | 'parentSpanId'>>,
156+
spanContext?: Pick<SpanContext, Exclude<keyof SpanContext, 'sampled' | 'traceId' | 'parentSpanId'>>,
157157
): Span {
158158
const childSpan = new Span({
159159
...spanContext,

0 commit comments

Comments
 (0)