Skip to content

Commit 412b45c

Browse files
committed
WIP
1 parent e8442a7 commit 412b45c

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

46 files changed

+3470
-311
lines changed

packages/node-experimental/package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
},
2525
"dependencies": {
2626
"@opentelemetry/api": "~1.6.0",
27+
"@opentelemetry/core": "~1.17.0",
2728
"@opentelemetry/context-async-hooks": "~1.17.0",
2829
"@opentelemetry/instrumentation": "~0.43.0",
2930
"@opentelemetry/instrumentation-express": "~0.33.1",
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,16 @@
11
import { createContextKey } from '@opentelemetry/api';
22

33
export const OTEL_CONTEXT_HUB_KEY = createContextKey('sentry_hub');
4+
5+
export const OTEL_ATTR_ORIGIN = 'sentry.origin';
6+
export const OTEL_ATTR_OP = 'sentry.op';
7+
export const OTEL_ATTR_SOURCE = 'sentry.source';
8+
9+
export const OTEL_ATTR_PARENT_SAMPLED = 'sentry.parentSampled';
10+
export const OTEL_ATTR_DROP_SPAN = 'sentry.dropSpan';
11+
12+
export const OTEL_ATTR_BREADCRUMB_TYPE = 'sentry.breadcrumb.type';
13+
export const OTEL_ATTR_BREADCRUMB_LEVEL = 'sentry.breadcrumb.level';
14+
export const OTEL_ATTR_BREADCRUMB_EVENT_ID = 'sentry.breadcrumb.event_id';
15+
export const OTEL_ATTR_BREADCRUMB_CATEGORY = 'sentry.breadcrumb.category';
16+
export const OTEL_ATTR_BREADCRUMB_DATA = 'sentry.breadcrumb.data';

packages/node-experimental/src/index.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ export { INTEGRATIONS as Integrations };
1212
export { getAutoPerformanceIntegrations } from './integrations/getAutoPerformanceIntegrations';
1313
export * as Handlers from './sdk/handlers';
1414
export * from './sdk/trace';
15+
export { getActiveSpan } from './utils/getActiveSpan';
1516
export { getCurrentHub, getHubFromCarrier } from './sdk/hub';
1617

1718
export {
@@ -39,7 +40,6 @@ export {
3940
makeMain,
4041
runWithAsyncContext,
4142
Scope,
42-
startTransaction,
4343
SDK_VERSION,
4444
setContext,
4545
setExtra,

packages/node-experimental/src/integrations/http.ts

Lines changed: 19 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -3,12 +3,13 @@ import { SpanKind } from '@opentelemetry/api';
33
import { registerInstrumentations } from '@opentelemetry/instrumentation';
44
import { HttpInstrumentation } from '@opentelemetry/instrumentation-http';
55
import { SemanticAttributes } from '@opentelemetry/semantic-conventions';
6-
import { hasTracingEnabled, Transaction } from '@sentry/core';
7-
import { getCurrentHub } from '@sentry/node';
8-
import { _INTERNAL_getSentrySpan } from '@sentry/opentelemetry-node';
6+
import { hasTracingEnabled } from '@sentry/core';
97
import type { EventProcessor, Hub, Integration } from '@sentry/types';
108
import type { ClientRequest, IncomingMessage, ServerResponse } from 'http';
119

10+
import { OTEL_ATTR_DROP_SPAN, OTEL_ATTR_ORIGIN } from '../constants';
11+
import { setOtelSpanMetadata } from '../opentelemetry/spanData';
12+
import { getCurrentHub } from '../sdk/hub';
1213
import type { NodeExperimentalClient, OtelSpan } from '../types';
1314
import { getRequestSpanData } from '../utils/getRequestSpanData';
1415

@@ -110,7 +111,7 @@ export class Http implements Integration {
110111
requireParentforOutgoingSpans: true,
111112
requireParentforIncomingSpans: false,
112113
requestHook: (span, req) => {
113-
this._updateSentrySpan(span as unknown as OtelSpan, req);
114+
this._updateSpan(span as unknown as OtelSpan, req);
114115
},
115116
responseHook: (span, res) => {
116117
this._addRequestBreadcrumb(span as unknown as OtelSpan, res);
@@ -122,8 +123,6 @@ export class Http implements Integration {
122123
this._shouldCreateSpanForRequest =
123124
// eslint-disable-next-line deprecation/deprecation
124125
this._shouldCreateSpanForRequest || clientOptions?.shouldCreateSpanForRequest;
125-
126-
client?.on?.('otelSpanEnd', this._onSpanEnd);
127126
}
128127

129128
/**
@@ -133,64 +132,33 @@ export class Http implements Integration {
133132
this._unload?.();
134133
}
135134

136-
private _onSpanEnd: (otelSpan: unknown, mutableOptions: { drop: boolean }) => void = (
137-
otelSpan: unknown,
138-
mutableOptions: { drop: boolean },
139-
) => {
135+
/** If the span for this request should be dropped (=not sent to Sentry). */
136+
private _shouldDropSpan(otelSpan: OtelSpan): boolean {
140137
if (!this._shouldCreateSpans) {
141-
mutableOptions.drop = true;
142-
return;
138+
return true;
143139
}
144140

145141
if (this._shouldCreateSpanForRequest) {
146-
const url = getHttpUrl((otelSpan as OtelSpan).attributes);
142+
const url = getHttpUrl(otelSpan.attributes);
147143
if (url && !this._shouldCreateSpanForRequest(url)) {
148-
mutableOptions.drop = true;
149-
return;
144+
return true;
150145
}
151146
}
152147

153-
return;
154-
};
155-
156-
/** Update the Sentry span data based on the OTEL span. */
157-
private _updateSentrySpan(span: OtelSpan, request: ClientRequest | IncomingMessage): void {
158-
const data = getRequestSpanData(span);
159-
const { attributes } = span;
160-
161-
const sentrySpan = _INTERNAL_getSentrySpan(span.spanContext().spanId);
162-
if (!sentrySpan) {
163-
return;
164-
}
165-
166-
sentrySpan.origin = 'auto.http.otel.http';
167-
168-
const additionalData: Record<string, unknown> = {
169-
url: data.url,
170-
};
171-
172-
if (sentrySpan instanceof Transaction && span.kind === SpanKind.SERVER) {
173-
sentrySpan.setMetadata({ request });
174-
}
148+
return false;
149+
}
175150

176-
if (attributes[SemanticAttributes.HTTP_STATUS_CODE]) {
177-
const statusCode = attributes[SemanticAttributes.HTTP_STATUS_CODE] as string;
178-
additionalData['http.response.status_code'] = statusCode;
151+
/** Update the span with data we need. */
152+
private _updateSpan(span: OtelSpan, request: ClientRequest | IncomingMessage): void {
153+
span.setAttribute(OTEL_ATTR_ORIGIN, 'auto.http.otel.http');
179154

180-
sentrySpan.setTag('http.status_code', statusCode);
155+
if (span.kind === SpanKind.SERVER) {
156+
setOtelSpanMetadata(span, { request });
181157
}
182158

183-
if (data['http.query']) {
184-
additionalData['http.query'] = data['http.query'].slice(1);
159+
if (this._shouldDropSpan(span as unknown as OtelSpan)) {
160+
span.setAttribute(OTEL_ATTR_DROP_SPAN, true);
185161
}
186-
if (data['http.fragment']) {
187-
additionalData['http.fragment'] = data['http.fragment'].slice(1);
188-
}
189-
190-
Object.keys(additionalData).forEach(prop => {
191-
const value = additionalData[prop];
192-
sentrySpan.setData(prop, value);
193-
});
194162
}
195163

196164
/** Add a breadcrumb for outgoing requests. */
Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
import type { Span as OtelSpan } from '@opentelemetry/api';
2+
import type { Hub, Scope, TransactionMetadata } from '@sentry/types';
3+
4+
// We store the parent span, scope & metadata in separate weakmaps, so we can access them for a given span
5+
// This way we can enhance the data that an OTEL Span natively gives us
6+
// and since we are using weakmaps, we do not need to clean up after ourselves
7+
const otelSpanScope = new WeakMap<OtelSpan, Scope>();
8+
const otelSpanHub = new WeakMap<OtelSpan, Hub>();
9+
const otelSpanParent = new WeakMap<OtelSpan, OtelSpan>();
10+
const otelSpanMetadata = new WeakMap<OtelSpan, Partial<TransactionMetadata>>();
11+
12+
/** Set the Sentry scope on an OTEL span. */
13+
export function setOtelSpanScope(span: OtelSpan, scope: Scope): void {
14+
otelSpanScope.set(span, scope);
15+
}
16+
17+
/** Get the Sentry scope of an OTEL span. */
18+
export function getOtelSpanScope(span: OtelSpan): Scope | undefined {
19+
return otelSpanScope.get(span);
20+
}
21+
22+
/** Set the Sentry hub on an OTEL span. */
23+
export function setOtelSpanHub(span: OtelSpan, hub: Hub): void {
24+
otelSpanHub.set(span, hub);
25+
}
26+
27+
/** Get the Sentry hub of an OTEL span. */
28+
export function getOtelSpanHub(span: OtelSpan): Hub | undefined {
29+
return otelSpanHub.get(span);
30+
}
31+
32+
/** Set the parent OTEL span on an OTEL span. */
33+
export function setOtelSpanParent(span: OtelSpan, parentSpan: OtelSpan): void {
34+
otelSpanParent.set(span, parentSpan);
35+
}
36+
37+
/** Get the parent OTEL span of an OTEL span. */
38+
export function getOtelSpanParent(span: OtelSpan): OtelSpan | undefined {
39+
return otelSpanParent.get(span);
40+
}
41+
42+
/** Set metadata for an OTEL span. */
43+
export function setOtelSpanMetadata(span: OtelSpan, metadata: Partial<TransactionMetadata>): void {
44+
otelSpanMetadata.set(span, metadata);
45+
}
46+
47+
/** Get metadata for an OTEL span. */
48+
export function getOtelSpanMetadata(span: OtelSpan): Partial<TransactionMetadata> | undefined {
49+
return otelSpanMetadata.get(span);
50+
}

0 commit comments

Comments
 (0)