Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view

This file was deleted.

This file was deleted.

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
},
"dependencies": {
"@sentry/deno": "file:../../packed/sentry-deno-packed.tgz",
"@opentelemetry/api": "^1.9.0",
"@opentelemetry/api": "^1.9.1",
"ai": "^3.0.0",
"zod": "^3.22.4"
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,10 +15,9 @@ const NODE_EXPORTS_IGNORE = [
// Probably generated by transpilation, no need to require it
'__esModule',
// Only required from the Node package
'setNodeAsyncContextStrategy',
'setOpenTelemetryContextAsyncContextStrategy',
'getDefaultIntegrationsWithoutPerformance',
'initWithoutDefaultIntegrations',
'SentryContextManager',
'preloadOpenTelemetry',
// Internal helper only needed within integrations (e.g. bunRuntimeMetricsIntegration)
'_INTERNAL_normalizeCollectionInterval',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
"test:assert": "pnpm test"
},
"dependencies": {
"@opentelemetry/api": "1.9.0",
"@opentelemetry/api": "1.9.1",

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

intermediate state: this is needed because the api versions need to align. will go away once this is no longer supported so this is OK for now.

"@opentelemetry/sdk-trace-node": "2.6.1",
"@opentelemetry/exporter-trace-otlp-http": "0.214.0",
"@opentelemetry/instrumentation-undici": "0.24.0",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,9 @@ const provider = new NodeTracerProvider({
// Initialize the provider
provider.register({
propagator: new SentryPropagator(),
contextManager: new Sentry.SentryContextManager(),
// We make sure to use the context manager that was previously set up in init
// TODO: This is not ideal but it is just an intermediate state until all of this otel linking stuff is gone
contextManager: null,
});

registerInstrumentations({
Expand Down
13 changes: 1 addition & 12 deletions packages/cloudflare/test/async.test.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,4 @@
import {
getCurrentScope,
getGlobalScope,
getIsolationScope,
GLOBAL_OBJ,
Scope,
withIsolationScope,
withScope,
} from '@sentry/core';
import { AsyncLocalStorage } from 'async_hooks';
import { getCurrentScope, getGlobalScope, getIsolationScope, Scope, withIsolationScope, withScope } from '@sentry/core';
import { beforeEach, describe, expect, it } from 'vitest';
import { setAsyncLocalStorageAsyncContextStrategy } from '../src/async';

Expand All @@ -17,7 +8,6 @@ describe('withScope()', () => {
getCurrentScope().clear();
getGlobalScope().clear();

(GLOBAL_OBJ as any).AsyncLocalStorage = AsyncLocalStorage;
setAsyncLocalStorageAsyncContextStrategy();
});

Expand Down Expand Up @@ -95,7 +85,6 @@ describe('withIsolationScope()', () => {
getIsolationScope().clear();
getCurrentScope().clear();
getGlobalScope().clear();
(GLOBAL_OBJ as any).AsyncLocalStorage = AsyncLocalStorage;

setAsyncLocalStorageAsyncContextStrategy();
});
Expand Down
6 changes: 1 addition & 5 deletions packages/node/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -54,10 +54,7 @@ export { getAutoPerformanceIntegrations } from './integrations/tracing';

export type { NodeOptions, OpenTelemetryServerRuntimeOptions } from './types';

export {
// This needs exporting so the NodeClient can be used without calling init
setOpenTelemetryContextAsyncContextStrategy as setNodeAsyncContextStrategy,
} from '@sentry/opentelemetry';
export { setOpenTelemetryContextAsyncContextStrategy } from '@sentry/opentelemetry';

export {
addBreadcrumb,
Expand Down Expand Up @@ -206,7 +203,6 @@ export { createGetModuleFromFilename } from './utils/module';
export { httpServerIntegration } from './integrations/http/httpServerIntegration';
export { httpServerSpansIntegration } from './integrations/http/httpServerSpansIntegration';
export { processSessionIntegration } from './integrations/processSession';
export { SentryContextManager } from './otel/contextManager';
export { generateInstrumentOnce } from './otel/instrument';
export { NodeClient } from './sdk/client';
// eslint-disable-next-line typescript/no-deprecated
Expand Down
7 changes: 0 additions & 7 deletions packages/node/src/otel/contextManager.ts

This file was deleted.

3 changes: 2 additions & 1 deletion packages/node/src/sdk/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -175,7 +175,7 @@ function _init(

const clientOptions = getClientOptions({ ...options, defaultIntegrations }, getDefaultIntegrationsImpl);

setOpenTelemetryContextAsyncContextStrategy(clientOptions);
const asyncLocalStorageLookup = setOpenTelemetryContextAsyncContextStrategy();
Comment thread
sentry[bot] marked this conversation as resolved.

const scope = getCurrentScope();
scope.update(clientOptions.initialScope);
Expand All @@ -193,6 +193,7 @@ function _init(
getCurrentScope().setClient(client);

client.init();
client.asyncLocalStorageLookup = asyncLocalStorageLookup;

/*! rollup-include-cjs-only */
debug.log(`SDK initialized from CommonJS`);
Expand Down
16 changes: 5 additions & 11 deletions packages/node/src/sdk/initOtel.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,10 @@
import type { TracerProvider } from '@opentelemetry/api';
import { context, propagation, trace } from '@opentelemetry/api';
import { propagation, trace } from '@opentelemetry/api';
import { debug as coreDebug, hasSpanStreamingEnabled } from '@sentry/core';
import { SentryContextManager } from '../otel/contextManager';
import { setupOpenTelemetryLogger } from '../otel/logger';
import type { NodeClient } from './client';
import {
applyOtelSpanData,
type AsyncLocalStorageLookup,
backfillStreamedSpanDataFromOtel,
getSentryResource,
SentryPropagator,
Expand Down Expand Up @@ -78,9 +76,8 @@ export function initOpenTelemetry(client: NodeClient): void {
setupOpenTelemetryLogger();
}

const [provider, asyncLocalStorageLookup] = setupOtel(client);
const provider = setupOtel(client);
client.traceProvider = provider;
client.asyncLocalStorageLookup = asyncLocalStorageLookup;
}

interface NodePreloadOptions {
Expand Down Expand Up @@ -125,22 +122,19 @@ function getPreloadMethods(integrationNames?: string[]): ((() => void) & { id: s
}

/** Just exported for tests. */
export function setupOtel(client: NodeClient): [SentryTracerProvider | undefined, AsyncLocalStorageLookup | undefined] {
export function setupOtel(client: NodeClient): SentryTracerProvider | undefined {
const provider = new SentryTracerProvider({ resource: getSentryResource('node') });

if (!registerGlobalTracerProvider(provider)) {
DEBUG_BUILD &&
coreDebug.warn(
'Could not register SentryTracerProvider because another OpenTelemetry tracer provider is already registered.',
);
return [undefined, undefined];
return undefined;
}

propagation.setGlobalPropagator(new SentryPropagator());

const ctxManager = new SentryContextManager();
context.setGlobalContextManager(ctxManager);

client.on('spanEnd', span => {
applyOtelSpanData(span, { finalizeStatus: true });
});
Expand All @@ -163,5 +157,5 @@ export function setupOtel(client: NodeClient): [SentryTracerProvider | undefined
};
});

return [provider, ctxManager.getAsyncLocalStorageLookup()];
return provider;
}
18 changes: 2 additions & 16 deletions packages/opentelemetry/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -19,22 +19,8 @@
"./package.json": "./package.json",
".": {
"types": "./build/types/index.d.ts",
"node": {
"import": "./build/esm/index.js",
"require": "./build/cjs/index.js"
},
"worker": {
"import": "./build/esm/index.js",
"require": "./build/cjs/index.js"
},
"browser": {
"import": "./build/esm/index.browser.js",
"require": "./build/cjs/index.browser.js"
},
"default": {
"import": "./build/esm/index.js",
"require": "./build/cjs/index.js"
}
"import": "./build/esm/index.js",
"require": "./build/cjs/index.js"
}
},
"publishConfig": {
Expand Down
2 changes: 1 addition & 1 deletion packages/opentelemetry/rollup.npm.config.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { makeBaseNPMConfig, makeNPMConfigVariants } from '@sentry-internal/rollu

export default makeNPMConfigVariants(
makeBaseNPMConfig({
entrypoints: ['src/index.ts', 'src/index.browser.ts'],
entrypoints: ['src/index.ts'],
packageSpecificConfig: {
output: {
// set exports to 'named' or 'auto' so that rollup doesn't warn
Expand Down
44 changes: 39 additions & 5 deletions packages/opentelemetry/src/asyncContextStrategy.ts
Original file line number Diff line number Diff line change
@@ -1,24 +1,34 @@
import * as api from '@opentelemetry/api';
import type { Scope, TracingChannelBinding } from '@sentry/core';
import { getDefaultCurrentScope, getDefaultIsolationScope, setAsyncContextStrategy } from '@sentry/core';
import {
getDefaultCurrentScope,
getDefaultIsolationScope,
getRootSpan,
setAsyncContextStrategy,
spanIsIgnored,
} from '@sentry/core';
import {
SENTRY_FORK_ISOLATION_SCOPE_CONTEXT_KEY,
SENTRY_FORK_SET_ISOLATION_SCOPE_CONTEXT_KEY,
SENTRY_FORK_SET_SCOPE_CONTEXT_KEY,
SENTRY_TRACE_STATE_CHILD_IGNORED,
} from './constants';
import { continueTrace, startInactiveSpan, startNewTrace, startSpan, startSpanManual, withActiveSpan } from './trace';
import type { CurrentScopes } from './types';
import { getContextFromScope, getScopesFromContext } from './utils/contextData';
import { getActiveSpan } from './utils/getActiveSpan';
import { getTraceData } from './utils/getTraceData';
import { AsyncLocalStorage } from 'node:async_hooks';
import type { AsyncLocalStorageLookup } from './asyncLocalStorageContextManager';
import { SentryAsyncLocalStorageContextManager } from './asyncLocalStorageContextManager';

/**
* Sets the async context strategy to use follow the OTEL context under the hood.
* We handle forking a hub inside of our custom OTEL Context Manager (./otelContextManager.ts)
*/
export function setOpenTelemetryContextAsyncContextStrategy(options?: {
getTracingChannelBinding?: () => TracingChannelBinding | undefined;
}): void {
export function setOpenTelemetryContextAsyncContextStrategy(): AsyncLocalStorageLookup {
const asyncLocalStorage = new AsyncLocalStorage<api.Context>();

function getScopes(): CurrentScopes {
const ctx = api.context.active();
const scopes = getScopesFromContext(ctx);
Expand Down Expand Up @@ -91,6 +101,13 @@ export function setOpenTelemetryContextAsyncContextStrategy(options?: {
return getScopes().isolationScope;
}

function getTracingChannelBinding(): TracingChannelBinding {
return {
asyncLocalStorage,
getStoreWithActiveSpan,
} satisfies TracingChannelBinding;
}

setAsyncContextStrategy({
withScope,
withSetScope,
Expand All @@ -108,6 +125,23 @@ export function setOpenTelemetryContextAsyncContextStrategy(options?: {
// The types here don't fully align, because our own `Span` type is narrower
// than the OTEL one - but this is OK for here, as we now we'll only have OTEL spans passed around
withActiveSpan: withActiveSpan,
getTracingChannelBinding: options?.getTracingChannelBinding,
getTracingChannelBinding,
});

const ctxManager = new SentryAsyncLocalStorageContextManager(asyncLocalStorage);
api.context.setGlobalContextManager(ctxManager);

return ctxManager.getAsyncLocalStorageLookup();
}

function getStoreWithActiveSpan(span: Parameters<TracingChannelBinding['getStoreWithActiveSpan']>[0]): api.Context {
const activeContext = api.context.active();

// Tracing channels bind directly to the context manager's AsyncLocalStorage and bypass
// SentryContextManager.with(), so ignored children must restore their parent here as well.
const isIgnoredChild =
(spanIsIgnored(span) && getRootSpan(span) !== span) ||
span.spanContext().traceState?.get(SENTRY_TRACE_STATE_CHILD_IGNORED) === '1';

return isIgnoredChild ? activeContext : api.trace.setSpan(activeContext, span);
}
Loading
Loading