Skip to content

Commit 4f19e32

Browse files
committed
feat(node-experimental): Provide otel-powered async context strategy
1 parent 5fdaaa7 commit 4f19e32

File tree

2 files changed

+46
-0
lines changed

2 files changed

+46
-0
lines changed

packages/node-experimental/src/sdk/initOtel.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import { getCurrentHub } from '@sentry/core';
44
import { SentryPropagator, SentrySpanProcessor } from '@sentry/opentelemetry-node';
55

66
import type { NodeExperimentalClient } from './client';
7+
import { setOtelContextAsyncContextStrategy } from './otelContextAsyncContextStrategy';
78

89
/**
910
* Initialize OpenTelemetry for Node.
@@ -27,6 +28,8 @@ export function initOtel(): () => void {
2728
propagator: new SentryPropagator(),
2829
});
2930

31+
setOtelContextAsyncContextStrategy();
32+
3033
// Cleanup function
3134
return () => {
3235
void provider.forceFlush();
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
import * as api from '@opentelemetry/api';
2+
import type { Carrier, Hub, RunWithAsyncContextOptions } from '@sentry/core';
3+
import { ensureHubOnCarrier, getHubFromCarrier, setAsyncContextStrategy } from '@sentry/core';
4+
5+
const hubKey = api.createContextKey('sentry_hub');
6+
7+
/**
8+
* Sets the async context strategy to use follow the OTEL context under the hood.
9+
*/
10+
export function setOtelContextAsyncContextStrategy(): void {
11+
function getCurrentHub(): Hub | undefined {
12+
const ctx = api.context.active();
13+
14+
// Returning undefined means the global hub will be used
15+
return ctx.getValue(hubKey) as Hub | undefined;
16+
}
17+
18+
function createNewHub(parent: Hub | undefined): Hub {
19+
const carrier: Carrier = {};
20+
ensureHubOnCarrier(carrier, parent);
21+
return getHubFromCarrier(carrier);
22+
}
23+
24+
function runWithAsyncContext<T>(callback: () => T, options: RunWithAsyncContextOptions): T {
25+
const existingHub = getCurrentHub();
26+
27+
if (existingHub && options?.reuseExisting) {
28+
// We're already in an async context, so we don't need to create a new one
29+
// just call the callback with the current hub
30+
return callback();
31+
}
32+
33+
const newHub = createNewHub(existingHub);
34+
35+
const ctx = api.context.active();
36+
37+
return api.context.with(ctx.setValue(hubKey, newHub), () => {
38+
return callback();
39+
});
40+
}
41+
42+
setAsyncContextStrategy({ getCurrentHub, runWithAsyncContext });
43+
}

0 commit comments

Comments
 (0)