diff --git a/packages/node-core/package.json b/packages/node-core/package.json index ae247548614e..7c32730522f6 100644 --- a/packages/node-core/package.json +++ b/packages/node-core/package.json @@ -80,7 +80,6 @@ "@opentelemetry/api": "^1.9.0", "@opentelemetry/core": "^1.30.1 || ^2.1.0", "@opentelemetry/instrumentation": ">=0.57.1 <1", - "@opentelemetry/resources": "^1.30.1 || ^2.1.0", "@opentelemetry/sdk-trace-base": "^1.30.1 || ^2.1.0", "@opentelemetry/semantic-conventions": "^1.39.0", "@opentelemetry/exporter-trace-otlp-http": ">=0.57.0 <1" @@ -95,9 +94,6 @@ "@opentelemetry/instrumentation": { "optional": true }, - "@opentelemetry/resources": { - "optional": true - }, "@opentelemetry/sdk-trace-base": { "optional": true }, @@ -118,7 +114,6 @@ "@opentelemetry/core": "^2.6.1", "@opentelemetry/exporter-trace-otlp-http": "^0.214.0", "@opentelemetry/instrumentation": "^0.214.0", - "@opentelemetry/resources": "^2.6.1", "@opentelemetry/sdk-trace-base": "^2.6.1", "@opentelemetry/semantic-conventions": "^1.40.0", "@types/node": "^18.19.1" diff --git a/packages/node-core/test/helpers/mockSdkInit.ts b/packages/node-core/test/helpers/mockSdkInit.ts index 556a33091d8e..8d9f66b5329c 100644 --- a/packages/node-core/test/helpers/mockSdkInit.ts +++ b/packages/node-core/test/helpers/mockSdkInit.ts @@ -1,11 +1,5 @@ import { context, propagation, ProxyTracerProvider, trace } from '@opentelemetry/api'; -import { defaultResource, resourceFromAttributes } from '@opentelemetry/resources'; import { BasicTracerProvider, type SpanProcessor } from '@opentelemetry/sdk-trace-base'; -import { - ATTR_SERVICE_NAME, - ATTR_SERVICE_VERSION, - SEMRESATTRS_SERVICE_NAMESPACE, -} from '@opentelemetry/semantic-conventions'; import { createTransport, debug, @@ -14,9 +8,8 @@ import { getGlobalScope, getIsolationScope, resolvedSyncPromise, - SDK_VERSION, } from '@sentry/core'; -import { SentryPropagator, SentrySampler, SentrySpanProcessor } from '@sentry/opentelemetry'; +import { getSentryResource, SentryPropagator, SentrySampler, SentrySpanProcessor } from '@sentry/opentelemetry'; import type { NodeClient } from '../../src'; import { SentryContextManager, validateOpenTelemetrySetup } from '../../src'; import { init } from '../../src/sdk'; @@ -64,14 +57,7 @@ export function setupOtel(client: NodeClient): BasicTracerProvider | undefined { // Create and configure TracerProvider with same config as Node SDK const provider = new BasicTracerProvider({ sampler: new SentrySampler(client), - resource: defaultResource().merge( - resourceFromAttributes({ - [ATTR_SERVICE_NAME]: 'node', - // eslint-disable-next-line deprecation/deprecation - [SEMRESATTRS_SERVICE_NAMESPACE]: 'sentry', - [ATTR_SERVICE_VERSION]: SDK_VERSION, - }), - ), + resource: getSentryResource('node'), forceFlushTimeoutMillis: 500, spanProcessors: [ new SentrySpanProcessor({ diff --git a/packages/node/package.json b/packages/node/package.json index 7d1d17bfe4a8..4e4ac224639f 100644 --- a/packages/node/package.json +++ b/packages/node/package.json @@ -89,7 +89,6 @@ "@opentelemetry/instrumentation-redis": "0.62.0", "@opentelemetry/instrumentation-tedious": "0.33.0", "@opentelemetry/instrumentation-undici": "0.24.0", - "@opentelemetry/resources": "^2.6.1", "@opentelemetry/sdk-trace-base": "^2.6.1", "@opentelemetry/semantic-conventions": "^1.40.0", "@prisma/instrumentation": "7.6.0", diff --git a/packages/node/src/sdk/initOtel.ts b/packages/node/src/sdk/initOtel.ts index a0f1951c376b..2554b98c76f7 100644 --- a/packages/node/src/sdk/initOtel.ts +++ b/packages/node/src/sdk/initOtel.ts @@ -1,13 +1,7 @@ import { context, propagation, trace } from '@opentelemetry/api'; -import { defaultResource, resourceFromAttributes } from '@opentelemetry/resources'; import type { SpanProcessor } from '@opentelemetry/sdk-trace-base'; import { BasicTracerProvider } from '@opentelemetry/sdk-trace-base'; -import { - ATTR_SERVICE_NAME, - ATTR_SERVICE_VERSION, - SEMRESATTRS_SERVICE_NAMESPACE, -} from '@opentelemetry/semantic-conventions'; -import { debug as coreDebug, SDK_VERSION } from '@sentry/core'; +import { debug as coreDebug } from '@sentry/core'; import { initializeEsmLoader, type NodeClient, @@ -16,6 +10,7 @@ import { } from '@sentry/node-core'; import { type AsyncLocalStorageLookup, + getSentryResource, SentryPropagator, SentrySampler, SentrySpanProcessor, @@ -95,14 +90,7 @@ export function setupOtel( // Create and configure NodeTracerProvider const provider = new BasicTracerProvider({ sampler: new SentrySampler(client), - resource: defaultResource().merge( - resourceFromAttributes({ - [ATTR_SERVICE_NAME]: 'node', - // eslint-disable-next-line deprecation/deprecation - [SEMRESATTRS_SERVICE_NAMESPACE]: 'sentry', - [ATTR_SERVICE_VERSION]: SDK_VERSION, - }), - ), + resource: getSentryResource('node'), forceFlushTimeoutMillis: 500, spanProcessors: [ new SentrySpanProcessor({ diff --git a/packages/opentelemetry/src/index.ts b/packages/opentelemetry/src/index.ts index c5fe1d3376d7..a49597f67fdf 100644 --- a/packages/opentelemetry/src/index.ts +++ b/packages/opentelemetry/src/index.ts @@ -49,6 +49,8 @@ export { SentrySampler, wrapSamplingDecision } from './sampler'; export { openTelemetrySetupCheck } from './utils/setupCheck'; +export { getSentryResource } from './resource'; + export { withStreamedSpan } from '@sentry/core'; // Legacy diff --git a/packages/opentelemetry/src/resource.ts b/packages/opentelemetry/src/resource.ts new file mode 100644 index 000000000000..9c1f95a7179c --- /dev/null +++ b/packages/opentelemetry/src/resource.ts @@ -0,0 +1,59 @@ +import type { Attributes, AttributeValue } from '@opentelemetry/api'; +import { SDK_INFO } from '@opentelemetry/core'; +import { + ATTR_SERVICE_NAME, + ATTR_SERVICE_VERSION, + ATTR_TELEMETRY_SDK_LANGUAGE, + ATTR_TELEMETRY_SDK_NAME, + ATTR_TELEMETRY_SDK_VERSION, + SEMRESATTRS_SERVICE_NAMESPACE, +} from '@opentelemetry/semantic-conventions'; +import { SDK_VERSION } from '@sentry/core'; + +type RawResourceAttribute = [string, AttributeValue | undefined]; + +/** + * Minimal Resource implementation that satisfies the OpenTelemetry Resource interface + * used by BasicTracerProvider, without depending on `@opentelemetry/resources`. + */ +class SentryResource { + private _attributes: Attributes; + + public constructor(attributes: Attributes) { + this._attributes = attributes; + } + + public get attributes(): Attributes { + return this._attributes; + } + + public merge(other: SentryResource | null): SentryResource { + if (!other) { + return this; + } + return new SentryResource({ ...this._attributes, ...other.attributes }); + } + + public getRawAttributes(): RawResourceAttribute[] { + return Object.entries(this._attributes); + } +} + +/** + * Returns a Resource for use in Sentry's OpenTelemetry TracerProvider setup. + * + * Combines the default OTel SDK telemetry attributes with Sentry-specific + * service attributes, equivalent to what was previously done via: + * `defaultResource().merge(resourceFromAttributes({ ... }))` + */ +export function getSentryResource(serviceName: string): SentryResource { + return new SentryResource({ + [ATTR_SERVICE_NAME]: serviceName, + // eslint-disable-next-line deprecation/deprecation + [SEMRESATTRS_SERVICE_NAMESPACE]: 'sentry', + [ATTR_SERVICE_VERSION]: SDK_VERSION, + [ATTR_TELEMETRY_SDK_LANGUAGE]: SDK_INFO[ATTR_TELEMETRY_SDK_LANGUAGE], + [ATTR_TELEMETRY_SDK_NAME]: SDK_INFO[ATTR_TELEMETRY_SDK_NAME], + [ATTR_TELEMETRY_SDK_VERSION]: SDK_INFO[ATTR_TELEMETRY_SDK_VERSION], + }); +} diff --git a/packages/opentelemetry/test/helpers/initOtel.ts b/packages/opentelemetry/test/helpers/initOtel.ts index f3b176f13b10..a080679c1e78 100644 --- a/packages/opentelemetry/test/helpers/initOtel.ts +++ b/packages/opentelemetry/test/helpers/initOtel.ts @@ -1,15 +1,10 @@ import { context, diag, DiagLogLevel, propagation, trace } from '@opentelemetry/api'; -import { defaultResource, resourceFromAttributes } from '@opentelemetry/resources'; import { BasicTracerProvider } from '@opentelemetry/sdk-trace-base'; -import { - ATTR_SERVICE_NAME, - ATTR_SERVICE_VERSION, - SEMRESATTRS_SERVICE_NAMESPACE, -} from '@opentelemetry/semantic-conventions'; -import { debug, getClient, SDK_VERSION } from '@sentry/core'; +import { debug, getClient } from '@sentry/core'; import { SentryAsyncLocalStorageContextManager } from '../../src/asyncLocalStorageContextManager'; import { DEBUG_BUILD } from '../../src/debug-build'; import { SentryPropagator } from '../../src/propagator'; +import { getSentryResource } from '../../src/resource'; import { SentrySampler } from '../../src/sampler'; import { setupEventContextTrace } from '../../src/setupEventContextTrace'; import { SentrySpanProcessor } from '../../src/spanProcessor'; @@ -59,14 +54,7 @@ export function setupOtel(client: TestClientInterface): [BasicTracerProvider, Se // Create and configure NodeTracerProvider const provider = new BasicTracerProvider({ sampler: new SentrySampler(client), - resource: defaultResource().merge( - resourceFromAttributes({ - [ATTR_SERVICE_NAME]: 'opentelemetry-test', - // eslint-disable-next-line deprecation/deprecation - [SEMRESATTRS_SERVICE_NAMESPACE]: 'sentry', - [ATTR_SERVICE_VERSION]: SDK_VERSION, - }), - ), + resource: getSentryResource('opentelemetry-test'), forceFlushTimeoutMillis: 500, spanProcessors: [spanProcessor], }); diff --git a/packages/vercel-edge/src/sdk.ts b/packages/vercel-edge/src/sdk.ts index e35aa770c880..d0666a6f66e1 100644 --- a/packages/vercel-edge/src/sdk.ts +++ b/packages/vercel-edge/src/sdk.ts @@ -1,11 +1,5 @@ import { context, diag, DiagLogLevel, propagation, trace } from '@opentelemetry/api'; -import { defaultResource, resourceFromAttributes } from '@opentelemetry/resources'; import { BasicTracerProvider } from '@opentelemetry/sdk-trace-base'; -import { - ATTR_SERVICE_NAME, - ATTR_SERVICE_VERSION, - SEMRESATTRS_SERVICE_NAMESPACE, -} from '@opentelemetry/semantic-conventions'; import type { Client, Integration, Options } from '@sentry/core'; import { consoleIntegration, @@ -22,12 +16,12 @@ import { linkedErrorsIntegration, nodeStackLineParser, requestDataIntegration, - SDK_VERSION, spanStreamingIntegration, stackParserFromStackParserOptions, } from '@sentry/core'; import { enhanceDscWithOpenTelemetryRootSpanName, + getSentryResource, openTelemetrySetupCheck, SentryPropagator, SentrySampler, @@ -166,14 +160,7 @@ export function setupOtel(client: VercelEdgeClient): void { // Create and configure NodeTracerProvider const provider = new BasicTracerProvider({ sampler: new SentrySampler(client), - resource: defaultResource().merge( - resourceFromAttributes({ - [ATTR_SERVICE_NAME]: 'edge', - // eslint-disable-next-line deprecation/deprecation - [SEMRESATTRS_SERVICE_NAMESPACE]: 'sentry', - [ATTR_SERVICE_VERSION]: SDK_VERSION, - }), - ), + resource: getSentryResource('edge'), forceFlushTimeoutMillis: 500, spanProcessors: [ new SentrySpanProcessor({