From 7885d49a895f9905f6747058293be6cd838199ea Mon Sep 17 00:00:00 2001 From: Abhijeet Prasad Date: Mon, 9 Sep 2024 13:46:45 +0200 Subject: [PATCH] feat(otel): Upgrade @opentelemetry/semantic-conventions to 1.26.0 In 1.26.0 otel-js has updated the deprecations for the attributes based on the new changes to semantic conventions. They also changed the name of every export, for example: `SEMATTRS_HTTP_ROUTE` -> `ATTR_HTTP_ROUTE`. In addition some of these exports now live in `@opentelemetry/semantic-conventions/incubating` which means we have to change the overall export. --- packages/nextjs/package.json | 2 +- packages/nextjs/src/server/index.ts | 24 ++- packages/node/package.json | 6 +- packages/node/src/integrations/tracing/koa.ts | 4 +- packages/node/src/sdk/initOtel.ts | 13 +- packages/opentelemetry/package.json | 8 +- packages/opentelemetry/src/propagator.ts | 7 +- packages/opentelemetry/src/sampler.ts | 25 +-- packages/opentelemetry/src/spanExporter.ts | 9 +- .../src/utils/getRequestSpanData.ts | 22 ++- .../src/utils/isSentryRequest.ts | 8 +- packages/opentelemetry/src/utils/mapStatus.ts | 11 +- .../src/utils/parseSpanDescription.ts | 52 ++++--- .../opentelemetry/test/helpers/initOtel.ts | 13 +- packages/opentelemetry/test/trace.test.ts | 22 ++- .../test/utils/getRequestSpanData.test.ts | 7 +- .../test/utils/mapStatus.test.ts | 9 +- .../test/utils/parseSpanDescription.test.ts | 143 +++++++++--------- yarn.lock | 23 ++- 19 files changed, 229 insertions(+), 179 deletions(-) diff --git a/packages/nextjs/package.json b/packages/nextjs/package.json index 9880e0ffb28e..8e4fd27370da 100644 --- a/packages/nextjs/package.json +++ b/packages/nextjs/package.json @@ -69,7 +69,7 @@ }, "dependencies": { "@opentelemetry/instrumentation-http": "0.53.0", - "@opentelemetry/semantic-conventions": "^1.25.1", + "@opentelemetry/semantic-conventions": "^1.27.0", "@rollup/plugin-commonjs": "26.0.1", "@sentry/core": "8.29.0", "@sentry/node": "8.29.0", diff --git a/packages/nextjs/src/server/index.ts b/packages/nextjs/src/server/index.ts index 1132a6e1eed2..797e25a26bb7 100644 --- a/packages/nextjs/src/server/index.ts +++ b/packages/nextjs/src/server/index.ts @@ -10,7 +10,12 @@ import { getDefaultIntegrations, init as nodeInit } from '@sentry/node'; import type { NodeClient, NodeOptions } from '@sentry/node'; import { GLOBAL_OBJ, logger } from '@sentry/utils'; -import { SEMATTRS_HTTP_METHOD, SEMATTRS_HTTP_ROUTE, SEMATTRS_HTTP_TARGET } from '@opentelemetry/semantic-conventions'; +import { ATTR_HTTP_ROUTE } from '@opentelemetry/semantic-conventions'; +import { + ATTR_HTTP_METHOD, + ATTR_HTTP_REQUEST_METHOD, + ATTR_HTTP_TARGET, +} from '@opentelemetry/semantic-conventions/incubating'; import type { EventProcessor } from '@sentry/types'; import { DEBUG_BUILD } from '../common/debug-build'; import { devErrorSymbolicationEventProcessor } from '../common/devErrorSymbolicationEventProcessor'; @@ -150,9 +155,12 @@ export function init(options: NodeOptions): NodeClient | undefined { // because we didn't get the chance to do `suppressTracing`, since this happens outside of userland. // We need to drop these spans. if ( - typeof spanAttributes[SEMATTRS_HTTP_TARGET] === 'string' && - spanAttributes[SEMATTRS_HTTP_TARGET].includes('sentry_key') && - spanAttributes[SEMATTRS_HTTP_TARGET].includes('sentry_client') + // eslint-disable-next-line deprecation/deprecation + typeof spanAttributes[ATTR_HTTP_TARGET] === 'string' && + // eslint-disable-next-line deprecation/deprecation + spanAttributes[ATTR_HTTP_TARGET].includes('sentry_key') && + // eslint-disable-next-line deprecation/deprecation + spanAttributes[ATTR_HTTP_TARGET].includes('sentry_client') ) { samplingDecision.decision = false; } @@ -168,8 +176,12 @@ export function init(options: NodeOptions): NodeClient | undefined { const rootSpanAttributes = spanToJSON(rootSpan).data; // Only hoist the http.route attribute if the transaction doesn't already have it - if (rootSpanAttributes?.[SEMATTRS_HTTP_METHOD] && !rootSpanAttributes?.[SEMATTRS_HTTP_ROUTE]) { - rootSpan.setAttribute(SEMATTRS_HTTP_ROUTE, spanAttributes['next.route']); + if ( + // eslint-disable-next-line deprecation/deprecation + (rootSpanAttributes?.[ATTR_HTTP_REQUEST_METHOD] || rootSpanAttributes?.[ATTR_HTTP_METHOD]) && + !rootSpanAttributes?.[ATTR_HTTP_ROUTE] + ) { + rootSpan.setAttribute(ATTR_HTTP_ROUTE, spanAttributes['next.route']); } } diff --git a/packages/node/package.json b/packages/node/package.json index a77c1b56b215..63c6f719a2d4 100644 --- a/packages/node/package.json +++ b/packages/node/package.json @@ -87,9 +87,9 @@ "@opentelemetry/instrumentation-pg": "0.44.0", "@opentelemetry/instrumentation-redis-4": "0.42.0", "@opentelemetry/instrumentation-undici": "0.6.0", - "@opentelemetry/resources": "^1.25.1", - "@opentelemetry/sdk-trace-base": "^1.25.1", - "@opentelemetry/semantic-conventions": "^1.25.1", + "@opentelemetry/resources": "^1.26.0", + "@opentelemetry/sdk-trace-base": "^1.26.0", + "@opentelemetry/semantic-conventions": "^1.27.0", "@prisma/instrumentation": "5.19.1", "@sentry/core": "8.29.0", "@sentry/opentelemetry": "8.29.0", diff --git a/packages/node/src/integrations/tracing/koa.ts b/packages/node/src/integrations/tracing/koa.ts index 7db0225b6fc8..5fc43defce22 100644 --- a/packages/node/src/integrations/tracing/koa.ts +++ b/packages/node/src/integrations/tracing/koa.ts @@ -1,5 +1,5 @@ import { KoaInstrumentation } from '@opentelemetry/instrumentation-koa'; -import { SEMATTRS_HTTP_ROUTE } from '@opentelemetry/semantic-conventions'; +import { ATTR_HTTP_ROUTE } from '@opentelemetry/semantic-conventions/incubating'; import { SEMANTIC_ATTRIBUTE_SENTRY_OP, SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN, @@ -29,7 +29,7 @@ export const instrumentKoa = generateInstrumentOnce( return; } const attributes = spanToJSON(span).data; - const route = attributes && attributes[SEMATTRS_HTTP_ROUTE]; + const route = attributes && attributes[ATTR_HTTP_ROUTE]; // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access const method: string = info?.context?.request?.method?.toUpperCase() || 'GET'; if (route) { diff --git a/packages/node/src/sdk/initOtel.ts b/packages/node/src/sdk/initOtel.ts index 37b94ebc439f..d7aca5787c97 100644 --- a/packages/node/src/sdk/initOtel.ts +++ b/packages/node/src/sdk/initOtel.ts @@ -2,11 +2,8 @@ import moduleModule from 'module'; import { DiagLogLevel, diag } from '@opentelemetry/api'; import { Resource } from '@opentelemetry/resources'; import { BasicTracerProvider } from '@opentelemetry/sdk-trace-base'; -import { - SEMRESATTRS_SERVICE_NAME, - SEMRESATTRS_SERVICE_NAMESPACE, - SEMRESATTRS_SERVICE_VERSION, -} from '@opentelemetry/semantic-conventions'; +import { ATTR_SERVICE_NAME, ATTR_SERVICE_VERSION } from '@opentelemetry/semantic-conventions'; +import { ATTR_SERVICE_NAMESPACE } from '@opentelemetry/semantic-conventions/incubating'; import { SDK_VERSION } from '@sentry/core'; import { SentryPropagator, SentrySampler, SentrySpanProcessor } from '@sentry/opentelemetry'; import { GLOBAL_OBJ, consoleSandbox, logger } from '@sentry/utils'; @@ -130,9 +127,9 @@ export function setupOtel(client: NodeClient): BasicTracerProvider { const provider = new BasicTracerProvider({ sampler: new SentrySampler(client), resource: new Resource({ - [SEMRESATTRS_SERVICE_NAME]: 'node', - [SEMRESATTRS_SERVICE_NAMESPACE]: 'sentry', - [SEMRESATTRS_SERVICE_VERSION]: SDK_VERSION, + [ATTR_SERVICE_NAME]: 'node', + [ATTR_SERVICE_NAMESPACE]: 'sentry', + [ATTR_SERVICE_VERSION]: SDK_VERSION, }), forceFlushTimeoutMillis: 500, }); diff --git a/packages/opentelemetry/package.json b/packages/opentelemetry/package.json index 99fd7e84a6c8..34037826e3ed 100644 --- a/packages/opentelemetry/package.json +++ b/packages/opentelemetry/package.json @@ -47,15 +47,15 @@ "@opentelemetry/api": "^1.9.0", "@opentelemetry/core": "^1.25.1", "@opentelemetry/instrumentation": "^0.52.1", - "@opentelemetry/sdk-trace-base": "^1.25.1", - "@opentelemetry/semantic-conventions": "^1.25.1" + "@opentelemetry/sdk-trace-base": "^1.26.0", + "@opentelemetry/semantic-conventions": "^1.27.0" }, "devDependencies": { "@opentelemetry/api": "^1.9.0", "@opentelemetry/context-async-hooks": "^1.25.1", "@opentelemetry/core": "^1.25.1", - "@opentelemetry/sdk-trace-base": "^1.25.1", - "@opentelemetry/semantic-conventions": "^1.25.1" + "@opentelemetry/sdk-trace-base": "^1.26.0", + "@opentelemetry/semantic-conventions": "^1.27.0" }, "scripts": { "build": "run-p build:transpile build:types", diff --git a/packages/opentelemetry/src/propagator.ts b/packages/opentelemetry/src/propagator.ts index 4ed5a15532d2..2d57b4925ac8 100644 --- a/packages/opentelemetry/src/propagator.ts +++ b/packages/opentelemetry/src/propagator.ts @@ -3,9 +3,8 @@ import { INVALID_TRACEID } from '@opentelemetry/api'; import { context } from '@opentelemetry/api'; import { propagation, trace } from '@opentelemetry/api'; import { W3CBaggagePropagator, isTracingSuppressed } from '@opentelemetry/core'; -import { SEMATTRS_HTTP_URL } from '@opentelemetry/semantic-conventions'; +import { ATTR_HTTP_URL, ATTR_URL_FULL } from '@opentelemetry/semantic-conventions/incubating'; import type { continueTrace } from '@sentry/core'; -import { SEMANTIC_ATTRIBUTE_URL_FULL } from '@sentry/core'; import { hasTracingEnabled } from '@sentry/core'; import { getRootSpan } from '@sentry/core'; import { spanToJSON } from '@sentry/core'; @@ -294,7 +293,9 @@ function getExistingBaggage(carrier: unknown): string | undefined { */ function getCurrentURL(span: Span): string | undefined { const spanData = spanToJSON(span).data; - const urlAttribute = spanData?.[SEMATTRS_HTTP_URL] || spanData?.[SEMANTIC_ATTRIBUTE_URL_FULL]; + // `ATTR_URL_FULL` is the new attribute, but we still support the old one, `ATTR_HTTP_URL`, for now. + // eslint-disable-next-line deprecation/deprecation + const urlAttribute = spanData?.[ATTR_HTTP_URL] || spanData?.[ATTR_URL_FULL]; if (urlAttribute) { return urlAttribute; } diff --git a/packages/opentelemetry/src/sampler.ts b/packages/opentelemetry/src/sampler.ts index 03d47989ae1d..cddc9dc35cb5 100644 --- a/packages/opentelemetry/src/sampler.ts +++ b/packages/opentelemetry/src/sampler.ts @@ -5,10 +5,8 @@ import { TraceState } from '@opentelemetry/core'; import type { Sampler, SamplingResult } from '@opentelemetry/sdk-trace-base'; import { SamplingDecision } from '@opentelemetry/sdk-trace-base'; import { - SEMANTIC_ATTRIBUTE_HTTP_REQUEST_METHOD, SEMANTIC_ATTRIBUTE_SENTRY_OP, SEMANTIC_ATTRIBUTE_SENTRY_SAMPLE_RATE, - SEMANTIC_ATTRIBUTE_URL_FULL, hasTracingEnabled, sampleSpan, } from '@sentry/core'; @@ -16,7 +14,12 @@ import type { Client, SpanAttributes } from '@sentry/types'; import { logger } from '@sentry/utils'; import { SENTRY_TRACE_STATE_SAMPLED_NOT_RECORDING, SENTRY_TRACE_STATE_URL } from './constants'; -import { SEMATTRS_HTTP_METHOD, SEMATTRS_HTTP_URL } from '@opentelemetry/semantic-conventions'; +import { + ATTR_HTTP_METHOD, + ATTR_HTTP_REQUEST_METHOD, + ATTR_HTTP_URL, + ATTR_URL_FULL, +} from '@opentelemetry/semantic-conventions/incubating'; import { DEBUG_BUILD } from './debug-build'; import { getPropagationContextFromSpan } from './propagator'; import { getSamplingDecision } from './utils/getSamplingDecision'; @@ -52,13 +55,13 @@ export class SentrySampler implements Sampler { return wrapSamplingDecision({ decision: undefined, context, spanAttributes }); } + // `ATTR_HTTP_REQUEST_METHOD` is the new attribute, but we still support the old one, `ATTR_HTTP_METHOD`, for now. + // eslint-disable-next-line deprecation/deprecation + const maybeSpanHttpMethod = spanAttributes[ATTR_HTTP_METHOD] || spanAttributes[ATTR_HTTP_REQUEST_METHOD]; + // If we have a http.client span that has no local parent, we never want to sample it // but we want to leave downstream sampling decisions up to the server - if ( - spanKind === SpanKind.CLIENT && - (spanAttributes[SEMATTRS_HTTP_METHOD] || spanAttributes[SEMANTIC_ATTRIBUTE_HTTP_REQUEST_METHOD]) && - (!parentSpan || parentContext?.isRemote) - ) { + if (spanKind === SpanKind.CLIENT && maybeSpanHttpMethod && (!parentSpan || parentContext?.isRemote)) { return wrapSamplingDecision({ decision: undefined, context, spanAttributes }); } @@ -109,7 +112,7 @@ export class SentrySampler implements Sampler { [SEMANTIC_ATTRIBUTE_SENTRY_SAMPLE_RATE]: sampleRate, }; - const method = `${spanAttributes[SEMATTRS_HTTP_METHOD]}`.toUpperCase(); + const method = `${maybeSpanHttpMethod}`.toUpperCase(); if (method === 'OPTIONS' || method === 'HEAD') { DEBUG_BUILD && logger.log(`[Tracing] Not sampling span because HTTP method is '${method}' for ${spanName}`); @@ -198,7 +201,9 @@ function getBaseTraceState(context: Context, spanAttributes: SpanAttributes): Tr let traceState = parentContext?.traceState || new TraceState(); // We always keep the URL on the trace state, so we can access it in the propagator - const url = spanAttributes[SEMATTRS_HTTP_URL] || spanAttributes[SEMANTIC_ATTRIBUTE_URL_FULL]; + // `ATTR_URL_FULL` is the new attribute, but we still support the old one, `ATTR_HTTP_URL`, for now. + // eslint-disable-next-line deprecation/deprecation + const url = spanAttributes[ATTR_HTTP_URL] || spanAttributes[ATTR_URL_FULL]; if (url && typeof url === 'string') { traceState = traceState.set(SENTRY_TRACE_STATE_URL, url); } diff --git a/packages/opentelemetry/src/spanExporter.ts b/packages/opentelemetry/src/spanExporter.ts index 5714a3d93970..1cb8ec67e653 100644 --- a/packages/opentelemetry/src/spanExporter.ts +++ b/packages/opentelemetry/src/spanExporter.ts @@ -1,7 +1,7 @@ import type { Span } from '@opentelemetry/api'; import { SpanKind } from '@opentelemetry/api'; import type { ReadableSpan } from '@opentelemetry/sdk-trace-base'; -import { SEMATTRS_HTTP_STATUS_CODE } from '@opentelemetry/semantic-conventions'; +import { ATTR_HTTP_RESPONSE_STATUS_CODE, ATTR_HTTP_STATUS_CODE } from '@opentelemetry/semantic-conventions/incubating'; import { captureEvent, getCapturedScopesOnSpan, @@ -358,9 +358,10 @@ function getData(span: ReadableSpan): Record { data['otel.kind'] = SpanKind[span.kind]; } - if (attributes[SEMATTRS_HTTP_STATUS_CODE]) { - const statusCode = attributes[SEMATTRS_HTTP_STATUS_CODE] as string; - data['http.response.status_code'] = statusCode; + // eslint-disable-next-line deprecation/deprecation + const maybeHttpStatusCodeAttribute = attributes[ATTR_HTTP_STATUS_CODE]; + if (maybeHttpStatusCodeAttribute) { + data[ATTR_HTTP_RESPONSE_STATUS_CODE] = maybeHttpStatusCodeAttribute as string; } const requestData = getRequestSpanData(span); diff --git a/packages/opentelemetry/src/utils/getRequestSpanData.ts b/packages/opentelemetry/src/utils/getRequestSpanData.ts index 8ce4419c925d..476945f588fa 100644 --- a/packages/opentelemetry/src/utils/getRequestSpanData.ts +++ b/packages/opentelemetry/src/utils/getRequestSpanData.ts @@ -1,6 +1,11 @@ import type { Span } from '@opentelemetry/api'; import type { ReadableSpan } from '@opentelemetry/sdk-trace-base'; -import { SEMATTRS_HTTP_METHOD, SEMATTRS_HTTP_URL } from '@opentelemetry/semantic-conventions'; +import { + ATTR_HTTP_METHOD, + ATTR_HTTP_REQUEST_METHOD, + ATTR_HTTP_URL, + ATTR_URL_FULL, +} from '@opentelemetry/semantic-conventions/incubating'; import type { SanitizedRequestData } from '@sentry/types'; import { getSanitizedUrlString, parseUrl } from '@sentry/utils'; @@ -15,9 +20,15 @@ export function getRequestSpanData(span: Span | ReadableSpan): Partial = { - url: span.attributes[SEMATTRS_HTTP_URL] as string | undefined, - 'http.method': span.attributes[SEMATTRS_HTTP_METHOD] as string | undefined, + url: maybeUrlAttribute, + // eslint-disable-next-line deprecation/deprecation + 'http.method': (span.attributes[ATTR_HTTP_REQUEST_METHOD] || span.attributes[ATTR_HTTP_METHOD]) as + | string + | undefined, }; // Default to GET if URL is set but method is not @@ -26,9 +37,8 @@ export function getRequestSpanData(span: Span | ReadableSpan): Partial { }); it('does sample when HTTP method is other than OPTIONS or HEAD', () => { - const spanGET = startSpanManual({ name: 'test span', attributes: { [SEMATTRS_HTTP_METHOD]: 'GET' } }, span => { + const spanGET = startSpanManual({ name: 'test span', attributes: { [ATTR_HTTP_METHOD]: 'GET' } }, span => { return span; }); expect(spanIsSampled(spanGET)).toBe(true); expect(getSamplingDecision(spanGET.spanContext())).toBe(true); - const spanPOST = startSpanManual({ name: 'test span', attributes: { [SEMATTRS_HTTP_METHOD]: 'POST' } }, span => { + const spanPOST = startSpanManual({ name: 'test span', attributes: { [ATTR_HTTP_METHOD]: 'POST' } }, span => { return span; }); expect(spanIsSampled(spanPOST)).toBe(true); expect(getSamplingDecision(spanPOST.spanContext())).toBe(true); - const spanPUT = startSpanManual({ name: 'test span', attributes: { [SEMATTRS_HTTP_METHOD]: 'PUT' } }, span => { + const spanPUT = startSpanManual({ name: 'test span', attributes: { [ATTR_HTTP_METHOD]: 'PUT' } }, span => { return span; }); expect(spanIsSampled(spanPUT)).toBe(true); expect(getSamplingDecision(spanPUT.spanContext())).toBe(true); - const spanDELETE = startSpanManual( - { name: 'test span', attributes: { [SEMATTRS_HTTP_METHOD]: 'DELETE' } }, - span => { - return span; - }, - ); + const spanDELETE = startSpanManual({ name: 'test span', attributes: { [ATTR_HTTP_METHOD]: 'DELETE' } }, span => { + return span; + }); expect(spanIsSampled(spanDELETE)).toBe(true); expect(getSamplingDecision(spanDELETE.spanContext())).toBe(true); }); it('does not sample when HTTP method is OPTIONS', () => { - const span = startSpanManual({ name: 'test span', attributes: { [SEMATTRS_HTTP_METHOD]: 'OPTIONS' } }, span => { + const span = startSpanManual({ name: 'test span', attributes: { [ATTR_HTTP_METHOD]: 'OPTIONS' } }, span => { return span; }); expect(spanIsSampled(span)).toBe(false); @@ -1498,7 +1496,7 @@ describe('HTTP methods (sampling)', () => { }); it('does not sample when HTTP method is HEAD', () => { - const span = startSpanManual({ name: 'test span', attributes: { [SEMATTRS_HTTP_METHOD]: 'HEAD' } }, span => { + const span = startSpanManual({ name: 'test span', attributes: { [ATTR_HTTP_METHOD]: 'HEAD' } }, span => { return span; }); expect(spanIsSampled(span)).toBe(false); diff --git a/packages/opentelemetry/test/utils/getRequestSpanData.test.ts b/packages/opentelemetry/test/utils/getRequestSpanData.test.ts index 5b067189740e..0da346ac046d 100644 --- a/packages/opentelemetry/test/utils/getRequestSpanData.test.ts +++ b/packages/opentelemetry/test/utils/getRequestSpanData.test.ts @@ -1,4 +1,5 @@ -import { SEMATTRS_HTTP_METHOD, SEMATTRS_HTTP_URL } from '@opentelemetry/semantic-conventions'; +/* eslint-disable deprecation/deprecation */ +import { ATTR_HTTP_METHOD, ATTR_HTTP_URL } from '@opentelemetry/semantic-conventions/incubating'; import { getRequestSpanData } from '../../src/utils/getRequestSpanData'; import { createSpan } from '../helpers/createSpan'; @@ -14,8 +15,8 @@ describe('getRequestSpanData', () => { it('works with http span', () => { const span = createSpan(); span.setAttributes({ - [SEMATTRS_HTTP_URL]: 'http://example.com?foo=bar#baz', - [SEMATTRS_HTTP_METHOD]: 'GET', + [ATTR_HTTP_URL]: 'http://example.com?foo=bar#baz', + [ATTR_HTTP_METHOD]: 'GET', }); const data = getRequestSpanData(span); diff --git a/packages/opentelemetry/test/utils/mapStatus.test.ts b/packages/opentelemetry/test/utils/mapStatus.test.ts index 1734586ee7a2..4326e8bd7a1a 100644 --- a/packages/opentelemetry/test/utils/mapStatus.test.ts +++ b/packages/opentelemetry/test/utils/mapStatus.test.ts @@ -1,4 +1,5 @@ -import { SEMATTRS_HTTP_STATUS_CODE, SEMATTRS_RPC_GRPC_STATUS_CODE } from '@opentelemetry/semantic-conventions'; +/* eslint-disable deprecation/deprecation */ +import { ATTR_HTTP_STATUS_CODE, ATTR_RPC_GRPC_STATUS_CODE } from '@opentelemetry/semantic-conventions/incubating'; import { SPAN_STATUS_ERROR, SPAN_STATUS_OK } from '@sentry/core'; import type { SpanStatus } from '@sentry/types'; @@ -62,11 +63,11 @@ describe('mapStatus', () => { span.setStatus({ code: 0 }); // UNSET if (httpCode) { - span.setAttribute(SEMATTRS_HTTP_STATUS_CODE, httpCode); + span.setAttribute(ATTR_HTTP_STATUS_CODE, httpCode); } if (grpcCode) { - span.setAttribute(SEMATTRS_RPC_GRPC_STATUS_CODE, grpcCode); + span.setAttribute(ATTR_RPC_GRPC_STATUS_CODE, grpcCode); } const actual = mapStatus(span); @@ -99,7 +100,7 @@ describe('mapStatus', () => { it('infers error status form attributes when span already has error status without message', () => { const span = createSpan(); - span.setAttribute(SEMATTRS_HTTP_STATUS_CODE, 500); + span.setAttribute(ATTR_HTTP_STATUS_CODE, 500); span.setStatus({ code: 2 }); // ERROR expect(mapStatus(span)).toEqual({ code: SPAN_STATUS_ERROR, message: 'internal_error' }); }); diff --git a/packages/opentelemetry/test/utils/parseSpanDescription.test.ts b/packages/opentelemetry/test/utils/parseSpanDescription.test.ts index 2b1d25dbacff..b22639809656 100644 --- a/packages/opentelemetry/test/utils/parseSpanDescription.test.ts +++ b/packages/opentelemetry/test/utils/parseSpanDescription.test.ts @@ -1,18 +1,19 @@ +/* eslint-disable deprecation/deprecation */ import type { Span } from '@opentelemetry/api'; import { SpanKind } from '@opentelemetry/api'; import { - SEMATTRS_DB_STATEMENT, - SEMATTRS_DB_SYSTEM, - SEMATTRS_FAAS_TRIGGER, - SEMATTRS_HTTP_HOST, - SEMATTRS_HTTP_METHOD, - SEMATTRS_HTTP_ROUTE, - SEMATTRS_HTTP_STATUS_CODE, - SEMATTRS_HTTP_TARGET, - SEMATTRS_HTTP_URL, - SEMATTRS_MESSAGING_SYSTEM, - SEMATTRS_RPC_SERVICE, -} from '@opentelemetry/semantic-conventions'; + ATTR_DB_STATEMENT, + ATTR_DB_SYSTEM, + ATTR_FAAS_TRIGGER, + ATTR_HTTP_HOST, + ATTR_HTTP_METHOD, + ATTR_HTTP_ROUTE, + ATTR_HTTP_STATUS_CODE, + ATTR_HTTP_TARGET, + ATTR_HTTP_URL, + ATTR_MESSAGING_SYSTEM, + ATTR_RPC_SERVICE, +} from '@opentelemetry/semantic-conventions/incubating'; import { descriptionForHttpMethod, getSanitizedUrl, parseSpanDescription } from '../../src/utils/parseSpanDescription'; @@ -43,7 +44,7 @@ describe('parseSpanDescription', () => { [ 'works with deprecated http method', { - [SEMATTRS_HTTP_METHOD]: 'GET', + [ATTR_HTTP_METHOD]: 'GET', }, 'test name', SpanKind.CLIENT, @@ -69,8 +70,8 @@ describe('parseSpanDescription', () => { [ 'works with db system', { - [SEMATTRS_DB_SYSTEM]: 'mysql', - [SEMATTRS_DB_STATEMENT]: 'SELECT * from users', + [ATTR_DB_SYSTEM]: 'mysql', + [ATTR_DB_STATEMENT]: 'SELECT * from users', }, 'test name', SpanKind.CLIENT, @@ -83,7 +84,7 @@ describe('parseSpanDescription', () => { [ 'works with db system without statement', { - [SEMATTRS_DB_SYSTEM]: 'mysql', + [ATTR_DB_SYSTEM]: 'mysql', }, 'test name', SpanKind.CLIENT, @@ -96,7 +97,7 @@ describe('parseSpanDescription', () => { [ 'works with rpc service', { - [SEMATTRS_RPC_SERVICE]: 'rpc-test-service', + [ATTR_RPC_SERVICE]: 'rpc-test-service', }, 'test name', undefined, @@ -109,7 +110,7 @@ describe('parseSpanDescription', () => { [ 'works with messaging system', { - [SEMATTRS_MESSAGING_SYSTEM]: 'test-messaging-system', + [ATTR_MESSAGING_SYSTEM]: 'test-messaging-system', }, 'test name', undefined, @@ -122,7 +123,7 @@ describe('parseSpanDescription', () => { [ 'works with faas trigger', { - [SEMATTRS_FAAS_TRIGGER]: 'test-faas-trigger', + [ATTR_FAAS_TRIGGER]: 'test-faas-trigger', }, 'test name', undefined, @@ -138,9 +139,9 @@ describe('parseSpanDescription', () => { 'sentry.skip_span_data_inference': true, // All of these should be ignored - [SEMATTRS_HTTP_METHOD]: 'GET', - [SEMATTRS_DB_SYSTEM]: 'mysql', - [SEMATTRS_DB_STATEMENT]: 'SELECT * from users', + [ATTR_HTTP_METHOD]: 'GET', + [ATTR_DB_SYSTEM]: 'mysql', + [ATTR_DB_STATEMENT]: 'SELECT * from users', }, 'test name', undefined, @@ -177,9 +178,9 @@ describe('descriptionForHttpMethod', () => { 'works with basic client GET', 'GET', { - [SEMATTRS_HTTP_METHOD]: 'GET', - [SEMATTRS_HTTP_URL]: 'https://www.example.com/my-path', - [SEMATTRS_HTTP_TARGET]: '/my-path', + [ATTR_HTTP_METHOD]: 'GET', + [ATTR_HTTP_URL]: 'https://www.example.com/my-path', + [ATTR_HTTP_TARGET]: '/my-path', }, 'test name', SpanKind.CLIENT, @@ -196,9 +197,9 @@ describe('descriptionForHttpMethod', () => { 'works with basic server POST', 'POST', { - [SEMATTRS_HTTP_METHOD]: 'POST', - [SEMATTRS_HTTP_URL]: 'https://www.example.com/my-path', - [SEMATTRS_HTTP_TARGET]: '/my-path', + [ATTR_HTTP_METHOD]: 'POST', + [ATTR_HTTP_URL]: 'https://www.example.com/my-path', + [ATTR_HTTP_TARGET]: '/my-path', }, 'test name', SpanKind.SERVER, @@ -215,10 +216,10 @@ describe('descriptionForHttpMethod', () => { 'works with client GET with route', 'GET', { - [SEMATTRS_HTTP_METHOD]: 'GET', - [SEMATTRS_HTTP_URL]: 'https://www.example.com/my-path/123', - [SEMATTRS_HTTP_TARGET]: '/my-path/123', - [SEMATTRS_HTTP_ROUTE]: '/my-path/:id', + [ATTR_HTTP_METHOD]: 'GET', + [ATTR_HTTP_URL]: 'https://www.example.com/my-path/123', + [ATTR_HTTP_TARGET]: '/my-path/123', + [ATTR_HTTP_ROUTE]: '/my-path/:id', }, 'test name', SpanKind.CLIENT, @@ -235,9 +236,9 @@ describe('descriptionForHttpMethod', () => { 'works with basic client GET with SpanKind.INTERNAL', 'GET', { - [SEMATTRS_HTTP_METHOD]: 'GET', - [SEMATTRS_HTTP_URL]: 'https://www.example.com/my-path', - [SEMATTRS_HTTP_TARGET]: '/my-path', + [ATTR_HTTP_METHOD]: 'GET', + [ATTR_HTTP_URL]: 'https://www.example.com/my-path', + [ATTR_HTTP_TARGET]: '/my-path', }, 'test name', SpanKind.INTERNAL, @@ -273,11 +274,11 @@ describe('getSanitizedUrl', () => { [ 'uses url without query for client request', { - [SEMATTRS_HTTP_URL]: 'http://example.com/?what=true', - [SEMATTRS_HTTP_METHOD]: 'GET', - [SEMATTRS_HTTP_TARGET]: '/?what=true', - [SEMATTRS_HTTP_HOST]: 'example.com:80', - [SEMATTRS_HTTP_STATUS_CODE]: 200, + [ATTR_HTTP_URL]: 'http://example.com/?what=true', + [ATTR_HTTP_METHOD]: 'GET', + [ATTR_HTTP_TARGET]: '/?what=true', + [ATTR_HTTP_HOST]: 'example.com:80', + [ATTR_HTTP_STATUS_CODE]: 200, }, SpanKind.CLIENT, { @@ -291,11 +292,11 @@ describe('getSanitizedUrl', () => { [ 'uses url without hash for client request', { - [SEMATTRS_HTTP_URL]: 'http://example.com/sub#hash', - [SEMATTRS_HTTP_METHOD]: 'GET', - [SEMATTRS_HTTP_TARGET]: '/sub#hash', - [SEMATTRS_HTTP_HOST]: 'example.com:80', - [SEMATTRS_HTTP_STATUS_CODE]: 200, + [ATTR_HTTP_URL]: 'http://example.com/sub#hash', + [ATTR_HTTP_METHOD]: 'GET', + [ATTR_HTTP_TARGET]: '/sub#hash', + [ATTR_HTTP_HOST]: 'example.com:80', + [ATTR_HTTP_STATUS_CODE]: 200, }, SpanKind.CLIENT, { @@ -309,12 +310,12 @@ describe('getSanitizedUrl', () => { [ 'uses route if available for client request', { - [SEMATTRS_HTTP_URL]: 'http://example.com/?what=true', - [SEMATTRS_HTTP_METHOD]: 'GET', - [SEMATTRS_HTTP_TARGET]: '/?what=true', - [SEMATTRS_HTTP_ROUTE]: '/my-route', - [SEMATTRS_HTTP_HOST]: 'example.com:80', - [SEMATTRS_HTTP_STATUS_CODE]: 200, + [ATTR_HTTP_URL]: 'http://example.com/?what=true', + [ATTR_HTTP_METHOD]: 'GET', + [ATTR_HTTP_TARGET]: '/?what=true', + [ATTR_HTTP_ROUTE]: '/my-route', + [ATTR_HTTP_HOST]: 'example.com:80', + [ATTR_HTTP_STATUS_CODE]: 200, }, SpanKind.CLIENT, { @@ -328,10 +329,10 @@ describe('getSanitizedUrl', () => { [ 'falls back to target for client request if url not available', { - [SEMATTRS_HTTP_METHOD]: 'GET', - [SEMATTRS_HTTP_TARGET]: '/?what=true', - [SEMATTRS_HTTP_HOST]: 'example.com:80', - [SEMATTRS_HTTP_STATUS_CODE]: 200, + [ATTR_HTTP_METHOD]: 'GET', + [ATTR_HTTP_TARGET]: '/?what=true', + [ATTR_HTTP_HOST]: 'example.com:80', + [ATTR_HTTP_STATUS_CODE]: 200, }, SpanKind.CLIENT, { @@ -345,11 +346,11 @@ describe('getSanitizedUrl', () => { [ 'uses target without query for server request', { - [SEMATTRS_HTTP_URL]: 'http://example.com/?what=true', - [SEMATTRS_HTTP_METHOD]: 'GET', - [SEMATTRS_HTTP_TARGET]: '/?what=true', - [SEMATTRS_HTTP_HOST]: 'example.com:80', - [SEMATTRS_HTTP_STATUS_CODE]: 200, + [ATTR_HTTP_URL]: 'http://example.com/?what=true', + [ATTR_HTTP_METHOD]: 'GET', + [ATTR_HTTP_TARGET]: '/?what=true', + [ATTR_HTTP_HOST]: 'example.com:80', + [ATTR_HTTP_STATUS_CODE]: 200, }, SpanKind.SERVER, { @@ -363,11 +364,11 @@ describe('getSanitizedUrl', () => { [ 'uses target without hash for server request', { - [SEMATTRS_HTTP_URL]: 'http://example.com/?what=true', - [SEMATTRS_HTTP_METHOD]: 'GET', - [SEMATTRS_HTTP_TARGET]: '/sub#hash', - [SEMATTRS_HTTP_HOST]: 'example.com:80', - [SEMATTRS_HTTP_STATUS_CODE]: 200, + [ATTR_HTTP_URL]: 'http://example.com/?what=true', + [ATTR_HTTP_METHOD]: 'GET', + [ATTR_HTTP_TARGET]: '/sub#hash', + [ATTR_HTTP_HOST]: 'example.com:80', + [ATTR_HTTP_STATUS_CODE]: 200, }, SpanKind.SERVER, { @@ -381,12 +382,12 @@ describe('getSanitizedUrl', () => { [ 'uses route for server request if available', { - [SEMATTRS_HTTP_URL]: 'http://example.com/?what=true', - [SEMATTRS_HTTP_METHOD]: 'GET', - [SEMATTRS_HTTP_TARGET]: '/?what=true', - [SEMATTRS_HTTP_ROUTE]: '/my-route', - [SEMATTRS_HTTP_HOST]: 'example.com:80', - [SEMATTRS_HTTP_STATUS_CODE]: 200, + [ATTR_HTTP_URL]: 'http://example.com/?what=true', + [ATTR_HTTP_METHOD]: 'GET', + [ATTR_HTTP_TARGET]: '/?what=true', + [ATTR_HTTP_ROUTE]: '/my-route', + [ATTR_HTTP_HOST]: 'example.com:80', + [ATTR_HTTP_STATUS_CODE]: 200, }, SpanKind.SERVER, { diff --git a/yarn.lock b/yarn.lock index 86f0c70cbdbd..ee25fb5f28d5 100644 --- a/yarn.lock +++ b/yarn.lock @@ -7330,7 +7330,7 @@ "@opentelemetry/core" "1.25.0" "@opentelemetry/semantic-conventions" "1.25.0" -"@opentelemetry/resources@1.25.1", "@opentelemetry/resources@^1.23.0", "@opentelemetry/resources@^1.25.1", "@opentelemetry/resources@^1.8.0": +"@opentelemetry/resources@1.25.1", "@opentelemetry/resources@^1.23.0", "@opentelemetry/resources@^1.8.0": version "1.25.1" resolved "https://registry.yarnpkg.com/@opentelemetry/resources/-/resources-1.25.1.tgz#bb9a674af25a1a6c30840b755bc69da2796fefbb" integrity sha512-pkZT+iFYIZsVn6+GzM0kSX+u3MSLCY9md+lIJOoKl/P+gJFfxJte/60Usdp8Ce4rOs8GduUpSPNe1ddGyDT1sQ== @@ -7338,6 +7338,14 @@ "@opentelemetry/core" "1.25.1" "@opentelemetry/semantic-conventions" "1.25.1" +"@opentelemetry/resources@1.26.0", "@opentelemetry/resources@^1.26.0": + version "1.26.0" + resolved "https://registry.yarnpkg.com/@opentelemetry/resources/-/resources-1.26.0.tgz#da4c7366018bd8add1f3aa9c91c6ac59fd503cef" + integrity sha512-CPNYchBE7MBecCSVy0HKpUISEeJOniWqcHaAHpmasZ3j9o6V3AyBzhRc90jdmemq0HOxDr6ylhUbDhBqqPpeNw== + dependencies: + "@opentelemetry/core" "1.26.0" + "@opentelemetry/semantic-conventions" "1.27.0" + "@opentelemetry/resources@^0.12.0": version "0.12.0" resolved "https://registry.yarnpkg.com/@opentelemetry/resources/-/resources-0.12.0.tgz#5eb287c3032a2bebb2bb9f69b44bd160d2a7d591" @@ -7381,7 +7389,7 @@ "@opentelemetry/resources" "1.23.0" "@opentelemetry/semantic-conventions" "1.23.0" -"@opentelemetry/sdk-trace-base@^1.22", "@opentelemetry/sdk-trace-base@^1.23.0", "@opentelemetry/sdk-trace-base@^1.25.1": +"@opentelemetry/sdk-trace-base@^1.22", "@opentelemetry/sdk-trace-base@^1.23.0": version "1.25.1" resolved "https://registry.yarnpkg.com/@opentelemetry/sdk-trace-base/-/sdk-trace-base-1.25.1.tgz#cbc1e60af255655d2020aa14cde17b37bd13df37" integrity sha512-C8k4hnEbc5FamuZQ92nTOp8X/diCY56XUTnMiv9UTuJitCzaNNHAVsdm5+HLCdI8SLQsLWIrG38tddMxLVoftw== @@ -7390,6 +7398,15 @@ "@opentelemetry/resources" "1.25.1" "@opentelemetry/semantic-conventions" "1.25.1" +"@opentelemetry/sdk-trace-base@^1.26.0": + version "1.26.0" + resolved "https://registry.yarnpkg.com/@opentelemetry/sdk-trace-base/-/sdk-trace-base-1.26.0.tgz#0c913bc6d2cfafd901de330e4540952269ae579c" + integrity sha512-olWQldtvbK4v22ymrKLbIcBi9L2SpMO84sCPY54IVsJhP9fRsxJT194C/AVaAuJzLE30EdhhM1VmvVYR7az+cw== + dependencies: + "@opentelemetry/core" "1.26.0" + "@opentelemetry/resources" "1.26.0" + "@opentelemetry/semantic-conventions" "1.27.0" + "@opentelemetry/semantic-conventions@1.23.0": version "1.23.0" resolved "https://registry.yarnpkg.com/@opentelemetry/semantic-conventions/-/semantic-conventions-1.23.0.tgz#627f2721b960fe586b7f72a07912cb7699f06eef" @@ -7400,7 +7417,7 @@ resolved "https://registry.yarnpkg.com/@opentelemetry/semantic-conventions/-/semantic-conventions-1.25.0.tgz#390eb4d42a29c66bdc30066af9035645e9bb7270" integrity sha512-M+kkXKRAIAiAP6qYyesfrC5TOmDpDVtsxuGfPcqd9B/iBrac+E14jYwrgm0yZBUIbIP2OnqC3j+UgkXLm1vxUQ== -"@opentelemetry/semantic-conventions@1.25.1", "@opentelemetry/semantic-conventions@^1.17.0", "@opentelemetry/semantic-conventions@^1.23.0", "@opentelemetry/semantic-conventions@^1.25.1": +"@opentelemetry/semantic-conventions@1.25.1", "@opentelemetry/semantic-conventions@^1.17.0", "@opentelemetry/semantic-conventions@^1.23.0": version "1.25.1" resolved "https://registry.yarnpkg.com/@opentelemetry/semantic-conventions/-/semantic-conventions-1.25.1.tgz#0deecb386197c5e9c2c28f2f89f51fb8ae9f145e" integrity sha512-ZDjMJJQRlyk8A1KZFCc+bCbsyrn1wTwdNt56F7twdfUfnHUZUq77/WfONCj8p72NZOyP7pNTdUWSTYC3GTbuuQ==