From 41bf7e74653c57c769b7ff4966b8113b9302f51e Mon Sep 17 00:00:00 2001 From: s1gr1d <32902192+s1gr1d@users.noreply.github.com> Date: Wed, 12 Aug 2026 11:10:52 +0200 Subject: [PATCH 1/3] feat(server-utils)!: Align AMQP and Redis span attributes --- .../suites/tracing/amqplib/test.ts | 23 ++--- .../suites/tracing/redis-cache/test.ts | 93 ++++++++++--------- .../suites/tracing/redis/test.ts | 42 +++++---- docs/migration/v11-end-state.md | 3 +- .../integrations/tracing-channel/amqplib.ts | 50 +--------- .../integrations/tracing-channel/ioredis.ts | 41 +++++--- .../src/integrations/tracing-channel/redis.ts | 48 +++------- .../tracing-channel/ioredis.test.ts | 14 +-- 8 files changed, 135 insertions(+), 179 deletions(-) diff --git a/dev-packages/node-integration-tests/suites/tracing/amqplib/test.ts b/dev-packages/node-integration-tests/suites/tracing/amqplib/test.ts index 90b6a7c932b9..87b8c8002c3e 100644 --- a/dev-packages/node-integration-tests/suites/tracing/amqplib/test.ts +++ b/dev-packages/node-integration-tests/suites/tracing/amqplib/test.ts @@ -1,25 +1,20 @@ import type { TransactionEvent } from '@sentry/core'; import { afterAll, describe, expect } from 'vitest'; +import { isOrchestrionEnabled } from '../../../utils'; import { cleanupChildProcesses, createEsmAndCjsTests, describeWithDockerCompose } from '../../../utils/runner'; // Each scenario uses its own queue name to keep them isolated on the shared broker, so the // expected producer span is parameterized by the routing key (queue name) it publishes to. // The scenarios all publish via `sendToQueue`, which delegates to `publish('', queue, ...)` — i.e. the // default (empty) exchange with the queue name as the routing key. +const orchestrionMessagingAttributes = isOrchestrionEnabled() ? { 'messaging.operation.name': 'send' } : {}; + const expectedProducerSpan = (routingKey: string) => expect.objectContaining({ op: 'queue.publish', data: expect.objectContaining({ 'messaging.system': 'rabbitmq', - // Legacy messaging attributes emitted by both the OTel and orchestrion integrations. - 'messaging.destination': '', - 'messaging.destination_kind': 'topic', - 'messaging.rabbitmq.routing_key': routingKey, - 'messaging.url': 'amqp://sentry:***@localhost:5672/', - 'messaging.protocol': 'AMQP', - 'messaging.protocol_version': '0.9.1', - 'net.peer.name': 'localhost', - 'net.peer.port': 5672, + ...orchestrionMessagingAttributes, 'messaging.operation.type': 'send', 'messaging.destination.name': '', 'messaging.rabbitmq.destination.routing_key': routingKey, @@ -35,18 +30,16 @@ const expectedProducerSpan = (routingKey: string) => status: 'ok', }); +const consumerMessagingAttributes = isOrchestrionEnabled() ? { 'messaging.operation.name': 'process' } : {}; + const EXPECTED_MESSAGE_SPAN_CONSUMER = expect.objectContaining({ op: 'queue.process', data: expect.objectContaining({ 'messaging.system': 'rabbitmq', - // Legacy messaging attributes emitted by both the OTel and orchestrion integrations. The consumer - // reads the default exchange ('') off the delivered message and the queue name as the routing key. - 'messaging.destination': '', - 'messaging.destination_kind': 'topic', - 'messaging.rabbitmq.routing_key': 'queue1', - 'messaging.operation': 'process', + // The consumer reads the default exchange ('') off the delivered message and the queue name as the routing key. 'messaging.destination.name': '', 'messaging.rabbitmq.destination.routing_key': 'queue1', + ...consumerMessagingAttributes, 'messaging.operation.type': 'process', 'sentry.kind': 'consumer', 'sentry.op': 'queue.process', diff --git a/dev-packages/node-integration-tests/suites/tracing/redis-cache/test.ts b/dev-packages/node-integration-tests/suites/tracing/redis-cache/test.ts index d877a66b512e..5f9bf76c98e9 100644 --- a/dev-packages/node-integration-tests/suites/tracing/redis-cache/test.ts +++ b/dev-packages/node-integration-tests/suites/tracing/redis-cache/test.ts @@ -8,6 +8,12 @@ describeWithDockerCompose('redis cache auto instrumentation', { workingDirectory }); const redisOrigin = isOrchestrionEnabled() ? 'auto.db.redis' : 'auto.db.otel.redis'; + const dbQueryTextAttribute = isOrchestrionEnabled() ? 'db.query.text' : 'db.statement'; + const redisSystemAttributes = isOrchestrionEnabled() ? { 'db.system.name': 'redis' } : { 'db.system': 'redis' }; + const redisConnectionAttributes = isOrchestrionEnabled() + ? { 'server.address': 'localhost', 'server.port': 6383 } + : { 'net.peer.name': 'localhost', 'net.peer.port': 6383 }; + const redisSpanOp = isOrchestrionEnabled() ? 'db.query' : 'db'; describe('ioredis non-cache keys', () => { const EXPECTED_TRANSACTION = { @@ -15,26 +21,24 @@ describeWithDockerCompose('redis cache auto instrumentation', { workingDirectory spans: expect.arrayContaining([ expect.objectContaining({ description: 'set test-key [1 other arguments]', - op: 'db', + op: redisSpanOp, origin: redisOrigin, data: expect.objectContaining({ - 'sentry.op': 'db', - 'db.system': 'redis', - 'net.peer.name': 'localhost', - 'net.peer.port': 6383, - 'db.statement': 'set test-key [1 other arguments]', + 'sentry.op': redisSpanOp, + ...redisSystemAttributes, + ...redisConnectionAttributes, + [dbQueryTextAttribute]: 'set test-key [1 other arguments]', }), }), expect.objectContaining({ description: 'get test-key', - op: 'db', + op: redisSpanOp, origin: redisOrigin, data: expect.objectContaining({ - 'sentry.op': 'db', - 'db.system': 'redis', - 'net.peer.name': 'localhost', - 'net.peer.port': 6383, - 'db.statement': 'get test-key', + 'sentry.op': redisSpanOp, + ...redisSystemAttributes, + ...redisConnectionAttributes, + [dbQueryTextAttribute]: 'get test-key', }), }), ]), @@ -58,7 +62,7 @@ describeWithDockerCompose('redis cache auto instrumentation', { workingDirectory origin: redisOrigin, data: expect.objectContaining({ 'sentry.origin': redisOrigin, - 'db.statement': 'set ioredis-cache:test-key [1 other arguments]', + [dbQueryTextAttribute]: 'set ioredis-cache:test-key [1 other arguments]', 'cache.key': ['ioredis-cache:test-key'], 'cache.item_size': 2, 'network.peer.address': 'localhost', @@ -72,7 +76,7 @@ describeWithDockerCompose('redis cache auto instrumentation', { workingDirectory origin: redisOrigin, data: expect.objectContaining({ 'sentry.origin': redisOrigin, - 'db.statement': 'set ioredis-cache:test-key-set-EX [3 other arguments]', + [dbQueryTextAttribute]: 'set ioredis-cache:test-key-set-EX [3 other arguments]', 'cache.key': ['ioredis-cache:test-key-set-EX'], 'cache.item_size': 2, 'network.peer.address': 'localhost', @@ -86,7 +90,7 @@ describeWithDockerCompose('redis cache auto instrumentation', { workingDirectory origin: redisOrigin, data: expect.objectContaining({ 'sentry.origin': redisOrigin, - 'db.statement': 'setex ioredis-cache:test-key-setex [2 other arguments]', + [dbQueryTextAttribute]: 'setex ioredis-cache:test-key-setex [2 other arguments]', 'cache.key': ['ioredis-cache:test-key-setex'], 'cache.item_size': 2, 'network.peer.address': 'localhost', @@ -100,7 +104,7 @@ describeWithDockerCompose('redis cache auto instrumentation', { workingDirectory origin: redisOrigin, data: expect.objectContaining({ 'sentry.origin': redisOrigin, - 'db.statement': 'get ioredis-cache:test-key', + [dbQueryTextAttribute]: 'get ioredis-cache:test-key', 'cache.hit': true, 'cache.key': ['ioredis-cache:test-key'], 'cache.item_size': 10, @@ -115,7 +119,7 @@ describeWithDockerCompose('redis cache auto instrumentation', { workingDirectory origin: redisOrigin, data: expect.objectContaining({ 'sentry.origin': redisOrigin, - 'db.statement': 'get ioredis-cache:unavailable-data', + [dbQueryTextAttribute]: 'get ioredis-cache:unavailable-data', 'cache.hit': false, 'cache.key': ['ioredis-cache:unavailable-data'], 'network.peer.address': 'localhost', @@ -129,7 +133,7 @@ describeWithDockerCompose('redis cache auto instrumentation', { workingDirectory origin: redisOrigin, data: expect.objectContaining({ 'sentry.origin': redisOrigin, - 'db.statement': 'mget [3 other arguments]', + [dbQueryTextAttribute]: 'mget [3 other arguments]', 'cache.hit': true, 'cache.key': ['test-key', 'ioredis-cache:test-key', 'ioredis-cache:unavailable-data'], 'network.peer.address': 'localhost', @@ -143,7 +147,7 @@ describeWithDockerCompose('redis cache auto instrumentation', { workingDirectory origin: redisOrigin, data: expect.objectContaining({ 'sentry.origin': redisOrigin, - 'db.statement': 'del ioredis-cache:test-key', + [dbQueryTextAttribute]: 'del ioredis-cache:test-key', 'cache.key': ['ioredis-cache:test-key'], 'network.peer.address': 'localhost', 'network.peer.port': 6383, @@ -183,15 +187,15 @@ describeWithDockerCompose('redis cache auto instrumentation', { workingDirectory op: 'db', origin: 'auto.db.otel.redis', data: expect.objectContaining({ - 'db.system': 'redis', - 'db.statement': 'SET redis-multi-key [1 other arguments]', + ...redisSystemAttributes, + [dbQueryTextAttribute]: 'SET redis-multi-key [1 other arguments]', }), }), expect.objectContaining({ description: 'GET redis-multi-key', op: 'db', origin: 'auto.db.otel.redis', - data: expect.objectContaining({ 'db.system': 'redis', 'db.statement': 'GET redis-multi-key' }), + data: expect.objectContaining({ ...redisSystemAttributes, [dbQueryTextAttribute]: 'GET redis-multi-key' }), }), ]; @@ -205,7 +209,7 @@ describeWithDockerCompose('redis cache auto instrumentation', { workingDirectory origin: redisOrigin, data: expect.objectContaining({ 'sentry.origin': redisOrigin, - 'db.statement': 'SET redis-cache:test-key [1 other arguments]', + [dbQueryTextAttribute]: 'SET redis-cache:test-key [1 other arguments]', 'cache.key': ['redis-cache:test-key'], 'cache.item_size': 2, }), @@ -217,7 +221,7 @@ describeWithDockerCompose('redis cache auto instrumentation', { workingDirectory origin: redisOrigin, data: expect.objectContaining({ 'sentry.origin': redisOrigin, - 'db.statement': 'SET redis-cache:test-key-set-EX [3 other arguments]', + [dbQueryTextAttribute]: 'SET redis-cache:test-key-set-EX [3 other arguments]', 'cache.key': ['redis-cache:test-key-set-EX'], 'cache.item_size': 2, }), @@ -229,7 +233,7 @@ describeWithDockerCompose('redis cache auto instrumentation', { workingDirectory origin: redisOrigin, data: expect.objectContaining({ 'sentry.origin': redisOrigin, - 'db.statement': 'SETEX redis-cache:test-key-setex [2 other arguments]', + [dbQueryTextAttribute]: 'SETEX redis-cache:test-key-setex [2 other arguments]', 'cache.key': ['redis-cache:test-key-setex'], 'cache.item_size': 2, }), @@ -241,7 +245,7 @@ describeWithDockerCompose('redis cache auto instrumentation', { workingDirectory origin: redisOrigin, data: expect.objectContaining({ 'sentry.origin': redisOrigin, - 'db.statement': 'GET redis-cache:test-key', + [dbQueryTextAttribute]: 'GET redis-cache:test-key', 'cache.hit': true, 'cache.key': ['redis-cache:test-key'], 'cache.item_size': 10, @@ -254,7 +258,7 @@ describeWithDockerCompose('redis cache auto instrumentation', { workingDirectory origin: redisOrigin, data: expect.objectContaining({ 'sentry.origin': redisOrigin, - 'db.statement': 'GET redis-cache:unavailable-data', + [dbQueryTextAttribute]: 'GET redis-cache:unavailable-data', 'cache.hit': false, 'cache.key': ['redis-cache:unavailable-data'], }), @@ -266,7 +270,7 @@ describeWithDockerCompose('redis cache auto instrumentation', { workingDirectory origin: redisOrigin, data: expect.objectContaining({ 'sentry.origin': redisOrigin, - 'db.statement': 'MGET [3 other arguments]', + [dbQueryTextAttribute]: 'MGET [3 other arguments]', 'cache.hit': true, 'cache.key': ['redis-test-key', 'redis-cache:test-key', 'redis-cache:unavailable-data'], }), @@ -278,7 +282,7 @@ describeWithDockerCompose('redis cache auto instrumentation', { workingDirectory origin: redisOrigin, data: expect.objectContaining({ 'sentry.origin': redisOrigin, - 'db.statement': 'DEL redis-cache:test-key', + [dbQueryTextAttribute]: 'DEL redis-cache:test-key', 'cache.key': ['redis-cache:test-key'], }), }), @@ -291,8 +295,8 @@ describeWithDockerCompose('redis cache auto instrumentation', { workingDirectory origin: redisOrigin, data: expect.objectContaining({ 'sentry.origin': redisOrigin, - 'db.system': 'redis', - 'db.statement': 'INCR redis-test-key', + ...redisSystemAttributes, + [dbQueryTextAttribute]: 'INCR redis-test-key', }), }), ]), @@ -336,15 +340,18 @@ describeWithDockerCompose('redis cache auto instrumentation', { workingDirectory op: 'db', origin: 'auto.db.otel.redis', data: expect.objectContaining({ - 'db.system': 'redis', - 'db.statement': 'SET redis-5-multi-key [1 other arguments]', + ...redisSystemAttributes, + [dbQueryTextAttribute]: 'SET redis-5-multi-key [1 other arguments]', }), }), expect.objectContaining({ description: 'GET redis-5-multi-key', op: 'db', origin: 'auto.db.otel.redis', - data: expect.objectContaining({ 'db.system': 'redis', 'db.statement': 'GET redis-5-multi-key' }), + data: expect.objectContaining({ + ...redisSystemAttributes, + [dbQueryTextAttribute]: 'GET redis-5-multi-key', + }), }), ]; @@ -358,7 +365,7 @@ describeWithDockerCompose('redis cache auto instrumentation', { workingDirectory origin: redisOrigin, data: expect.objectContaining({ 'sentry.origin': redisOrigin, - 'db.statement': 'SET redis-5-cache:test-key [1 other arguments]', + [dbQueryTextAttribute]: 'SET redis-5-cache:test-key [1 other arguments]', 'cache.key': ['redis-5-cache:test-key'], 'cache.item_size': 2, }), @@ -370,7 +377,7 @@ describeWithDockerCompose('redis cache auto instrumentation', { workingDirectory origin: redisOrigin, data: expect.objectContaining({ 'sentry.origin': redisOrigin, - 'db.statement': 'SET redis-5-cache:test-key-set-EX [3 other arguments]', + [dbQueryTextAttribute]: 'SET redis-5-cache:test-key-set-EX [3 other arguments]', 'cache.key': ['redis-5-cache:test-key-set-EX'], 'cache.item_size': 2, }), @@ -382,7 +389,7 @@ describeWithDockerCompose('redis cache auto instrumentation', { workingDirectory origin: redisOrigin, data: expect.objectContaining({ 'sentry.origin': redisOrigin, - 'db.statement': 'SETEX redis-5-cache:test-key-setex [2 other arguments]', + [dbQueryTextAttribute]: 'SETEX redis-5-cache:test-key-setex [2 other arguments]', 'cache.key': ['redis-5-cache:test-key-setex'], 'cache.item_size': 2, }), @@ -394,7 +401,7 @@ describeWithDockerCompose('redis cache auto instrumentation', { workingDirectory origin: redisOrigin, data: expect.objectContaining({ 'sentry.origin': redisOrigin, - 'db.statement': 'GET redis-5-cache:test-key', + [dbQueryTextAttribute]: 'GET redis-5-cache:test-key', 'cache.hit': true, 'cache.key': ['redis-5-cache:test-key'], 'cache.item_size': 10, @@ -407,7 +414,7 @@ describeWithDockerCompose('redis cache auto instrumentation', { workingDirectory origin: redisOrigin, data: expect.objectContaining({ 'sentry.origin': redisOrigin, - 'db.statement': 'GET redis-5-cache:unavailable-data', + [dbQueryTextAttribute]: 'GET redis-5-cache:unavailable-data', 'cache.hit': false, 'cache.key': ['redis-5-cache:unavailable-data'], }), @@ -419,7 +426,7 @@ describeWithDockerCompose('redis cache auto instrumentation', { workingDirectory origin: redisOrigin, data: expect.objectContaining({ 'sentry.origin': redisOrigin, - 'db.statement': 'MGET [3 other arguments]', + [dbQueryTextAttribute]: 'MGET [3 other arguments]', 'cache.hit': true, 'cache.key': ['redis-5-test-key', 'redis-5-cache:test-key', 'redis-5-cache:unavailable-data'], }), @@ -431,7 +438,7 @@ describeWithDockerCompose('redis cache auto instrumentation', { workingDirectory origin: redisOrigin, data: expect.objectContaining({ 'sentry.origin': redisOrigin, - 'db.statement': 'DEL redis-5-cache:test-key', + [dbQueryTextAttribute]: 'DEL redis-5-cache:test-key', 'cache.key': ['redis-5-cache:test-key'], }), }), @@ -444,8 +451,8 @@ describeWithDockerCompose('redis cache auto instrumentation', { workingDirectory origin: redisOrigin, data: expect.objectContaining({ 'sentry.origin': redisOrigin, - 'db.system': 'redis', - 'db.statement': 'INCR redis-5-test-key', + ...redisSystemAttributes, + [dbQueryTextAttribute]: 'INCR redis-5-test-key', }), }), ]), diff --git a/dev-packages/node-integration-tests/suites/tracing/redis/test.ts b/dev-packages/node-integration-tests/suites/tracing/redis/test.ts index a3d6a8702052..e01403e7b2a5 100644 --- a/dev-packages/node-integration-tests/suites/tracing/redis/test.ts +++ b/dev-packages/node-integration-tests/suites/tracing/redis/test.ts @@ -11,49 +11,55 @@ describeWithDockerCompose('redis auto instrumentation', { workingDirectory: [__d // subscriber instead of the OTel monkey-patch, so the span origin differs. All // other attributes are identical. const origin = isOrchestrionEnabled() ? 'auto.db.redis' : 'auto.db.otel.redis'; + const redisSpanOp = isOrchestrionEnabled() ? 'db.query' : 'db'; + const redisData = isOrchestrionEnabled() + ? { + 'db.system.name': 'redis', + 'server.address': 'localhost', + 'server.port': 6380, + } + : { + 'db.system': 'redis', + 'net.peer.name': 'localhost', + 'net.peer.port': 6380, + }; const EXPECTED_TRANSACTION = { transaction: 'Test Span', spans: expect.arrayContaining([ expect.objectContaining({ description: 'set test-key [1 other arguments]', - op: 'db', + op: redisSpanOp, origin, data: expect.objectContaining({ - 'sentry.op': 'db', + 'sentry.op': redisSpanOp, 'sentry.origin': origin, - 'db.system': 'redis', - 'net.peer.name': 'localhost', - 'net.peer.port': 6380, - 'db.statement': 'set test-key [1 other arguments]', + ...redisData, + 'db.query.text': 'set test-key [1 other arguments]', }), }), expect.objectContaining({ description: 'get test-key', - op: 'db', + op: redisSpanOp, origin, data: expect.objectContaining({ - 'sentry.op': 'db', + 'sentry.op': redisSpanOp, 'sentry.origin': origin, - 'db.system': 'redis', - 'net.peer.name': 'localhost', - 'net.peer.port': 6380, - 'db.statement': 'get test-key', + ...redisData, + 'db.query.text': 'get test-key', }), }), // a failing command produces a span with an error status expect.objectContaining({ description: 'incr test-key', - op: 'db', + op: redisSpanOp, status: 'internal_error', origin, data: expect.objectContaining({ - 'sentry.op': 'db', + 'sentry.op': redisSpanOp, 'sentry.origin': origin, - 'db.system': 'redis', - 'net.peer.name': 'localhost', - 'net.peer.port': 6380, - 'db.statement': 'incr test-key', + ...redisData, + 'db.query.text': 'incr test-key', }), }), ]), diff --git a/docs/migration/v11-end-state.md b/docs/migration/v11-end-state.md index 28d140980547..69d54ee188f2 100644 --- a/docs/migration/v11-end-state.md +++ b/docs/migration/v11-end-state.md @@ -525,8 +525,9 @@ String and regular-expression matching for `tracePropagationTargets` is now case Affected SDKs: All SDKs. - The `http.query` and `http.fragment` span attributes were renamed to `url.query` and `url.fragment`. +- The AMQP tracing-channel instrumentation no longer emits deprecated messaging attributes. Use `messaging.destination.name`, `messaging.rabbitmq.destination.routing_key`, `messaging.message.id`, `messaging.message.conversation_id`, `messaging.operation.name`, `network.protocol.name`, `network.protocol.version`, and `url.full` instead of their legacy `messaging.*` equivalents. `messaging.destination_kind` is no longer emitted. +- The Redis and ioredis tracing-channel instrumentations now use `db.system.name`, `db.operation.name`, `db.query.text`, `server.address`, and `server.port` instead of `db.system`, `db.statement`, `db.connection_string`, `net.peer.name`, and `net.peer.port`. - `network.*` span attributes were aligned across SDKs. -- Legacy messaging (`messaging.*`) and database (`db.statement`, …) span attributes on the AMQP and Redis instrumentations were replaced by their current semantic-convention equivalents. - The gen_ai cache token attributes `gen_ai.usage.cache_creation_input_tokens` and `gen_ai.usage.cache_read_input_tokens` were renamed to `gen_ai.usage.cache_creation.input_tokens` and `gen_ai.usage.cache_read.input_tokens`. - The `gen_ai.system` span attribute was renamed to `gen_ai.provider.name` across all AI integrations. - The `gen_ai.request.available_tools` span attribute was renamed to `gen_ai.tool.definitions` across all AI integrations. diff --git a/packages/server-utils/src/integrations/tracing-channel/amqplib.ts b/packages/server-utils/src/integrations/tracing-channel/amqplib.ts index 4ca0c8342ee2..bfa5067e3e71 100644 --- a/packages/server-utils/src/integrations/tracing-channel/amqplib.ts +++ b/packages/server-utils/src/integrations/tracing-channel/amqplib.ts @@ -11,14 +11,12 @@ import { startInactiveSpan, timestampInSeconds, } from '@sentry/core'; -// eslint-disable-next-line typescript/no-deprecated -- NET_PEER_* emitted alongside SERVER_* for backwards compatibility (TODO(v11): remove) import { - MESSAGING_SYSTEM, + MESSAGING_DESTINATION_NAME, MESSAGING_MESSAGE_ID, + MESSAGING_OPERATION_NAME, MESSAGING_OPERATION_TYPE, - MESSAGING_DESTINATION_NAME, - NET_PEER_NAME, - NET_PEER_PORT, + MESSAGING_SYSTEM, NETWORK_PROTOCOL_NAME, NETWORK_PROTOCOL_VERSION, SENTRY_KIND, @@ -40,25 +38,9 @@ const INTEGRATION_NAME = 'Amqplib' as const; const PUBLISHER_ORIGIN = 'auto.amqplib.publisher'; const CONSUMER_ORIGIN = 'auto.amqplib.consumer'; -// Legacy messaging semantic-conventions, inlined to keep this integration free of `@opentelemetry/*` -// deps. These mirror what the vendored OTel amqplib instrumentation has always emitted. We keep -// emitting them alongside the current `@sentry/conventions` attributes for backwards compatibility. -// TODO(v11): remove these legacy attributes. -const ATTR_MESSAGING_OPERATION = 'messaging.operation'; -const ATTR_MESSAGING_DESTINATION = 'messaging.destination'; -const ATTR_MESSAGING_DESTINATION_KIND = 'messaging.destination_kind'; -const ATTR_MESSAGING_RABBITMQ_ROUTING_KEY = 'messaging.rabbitmq.routing_key'; -const ATTR_MESSAGING_PROTOCOL = 'messaging.protocol'; -const ATTR_MESSAGING_PROTOCOL_VERSION_LEGACY = 'messaging.protocol_version'; -const ATTR_MESSAGING_URL = 'messaging.url'; -const ATTR_MESSAGING_MESSAGE_ID = 'messaging.message_id'; -const ATTR_MESSAGING_CONVERSATION_ID_LEGACY = 'messaging.conversation_id'; - -// TODO(v11): replace with the corresponding attribute from `@sentry/conventions` once it is added there. const ATTR_MESSAGING_RABBITMQ_DESTINATION_ROUTING_KEY = 'messaging.rabbitmq.destination.routing_key'; const ATTR_MESSAGING_CONVERSATION_ID = 'messaging.message.conversation_id'; -const MESSAGING_DESTINATION_KIND_VALUE_TOPIC = 'topic'; const MESSAGING_OPERATION_VALUE_PROCESS = 'process'; const MESSAGING_OPERATION_VALUE_SEND = 'send'; @@ -468,15 +450,11 @@ function startPublishSpan(data: AmqpChannelContext): Span { [SENTRY_OP]: MESSAGING_QUEUE_PUBLISH_SPAN_OP, [SENTRY_KIND]: 'producer', ...getStoredConnectionAttributes(data.self), - [ATTR_MESSAGING_DESTINATION]: exchange, // TODO(v11) remove this attribute [MESSAGING_DESTINATION_NAME]: exchange, - [ATTR_MESSAGING_DESTINATION_KIND]: MESSAGING_DESTINATION_KIND_VALUE_TOPIC, // TODO(v11) remove this attribute - [ATTR_MESSAGING_RABBITMQ_ROUTING_KEY]: routingKey, // TODO(v11) remove this attribute [ATTR_MESSAGING_RABBITMQ_DESTINATION_ROUTING_KEY]: routingKey, + [MESSAGING_OPERATION_NAME]: MESSAGING_OPERATION_VALUE_SEND, [MESSAGING_OPERATION_TYPE]: MESSAGING_OPERATION_VALUE_SEND, - [ATTR_MESSAGING_MESSAGE_ID]: options?.messageId as string | undefined, // todo(v11) remove this attribute [MESSAGING_MESSAGE_ID]: options?.messageId as string | undefined, - [ATTR_MESSAGING_CONVERSATION_ID_LEGACY]: options?.correlationId as string | undefined, // todo(v11) remove this attribute [ATTR_MESSAGING_CONVERSATION_ID]: options?.correlationId as string | undefined, [SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: PUBLISHER_ORIGIN, }, @@ -507,16 +485,11 @@ function startConsumeSpan(queue: string, msg: ConsumeMessage, channel: ChannelLi [SENTRY_KIND]: 'consumer', [SEMANTIC_ATTRIBUTE_SENTRY_SOURCE]: 'component', ...getStoredConnectionAttributes(channel), - [ATTR_MESSAGING_DESTINATION]: msg.fields?.exchange, // TODO(v11) remove this attribute [MESSAGING_DESTINATION_NAME]: msg.fields?.exchange, - [ATTR_MESSAGING_DESTINATION_KIND]: MESSAGING_DESTINATION_KIND_VALUE_TOPIC, // TODO(v11) remove this attribute - [ATTR_MESSAGING_RABBITMQ_ROUTING_KEY]: msg.fields?.routingKey, // TODO(v11) remove this attribute [ATTR_MESSAGING_RABBITMQ_DESTINATION_ROUTING_KEY]: msg.fields?.routingKey, - [ATTR_MESSAGING_OPERATION]: MESSAGING_OPERATION_VALUE_PROCESS, // TODO(v11) remove this attribute + [MESSAGING_OPERATION_NAME]: MESSAGING_OPERATION_VALUE_PROCESS, [MESSAGING_OPERATION_TYPE]: MESSAGING_OPERATION_VALUE_PROCESS, - [ATTR_MESSAGING_MESSAGE_ID]: msg.properties?.messageId as string | undefined, // todo(v11) remove this attribute [MESSAGING_MESSAGE_ID]: msg.properties?.messageId as string | undefined, - [ATTR_MESSAGING_CONVERSATION_ID_LEGACY]: msg.properties?.correlationId as string | undefined, // todo(v11) remove this attribute [ATTR_MESSAGING_CONVERSATION_ID]: msg.properties?.correlationId as string | undefined, [SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: CONSUMER_ORIGIN, }, @@ -552,7 +525,6 @@ function getConnectionAttributesFromServer(conn: ConnectionLike): SpanAttributes function getConnectionAttributesFromUrl(url: unknown): SpanAttributes { const attributes: SpanAttributes = { // The only protocol supported by the instrumented library. - [ATTR_MESSAGING_PROTOCOL_VERSION_LEGACY]: '0.9.1', // TODO(v11): remove this attribute [NETWORK_PROTOCOL_VERSION]: '0.9.1', }; @@ -563,19 +535,12 @@ function getConnectionAttributesFromUrl(url: unknown): SpanAttributes { const hostname = getHostname(connectOptions.hostname); const port = getPort(connectOptions.port, protocol); - attributes[ATTR_MESSAGING_PROTOCOL] = protocol; // TODO(v11) remove this attribute attributes[NETWORK_PROTOCOL_NAME] = protocol; attributes[SERVER_ADDRESS] = hostname; attributes[SERVER_PORT] = port; - // TODO(v11): remove deprecated options - // eslint-disable-next-line typescript/no-deprecated -- emitted alongside SERVER_ADDRESS/SERVER_PORT for backwards compatibility - attributes[NET_PEER_NAME] = hostname; - // eslint-disable-next-line typescript/no-deprecated -- emitted alongside SERVER_ADDRESS/SERVER_PORT for backwards compatibility - attributes[NET_PEER_PORT] = port; } else if (typeof resolvedUrl === 'string') { const censoredUrl = censorPassword(resolvedUrl); - attributes[ATTR_MESSAGING_URL] = censoredUrl; // todo(v11) remove this attribute // oxlint-disable-next-line sdk/no-unfiltered-url-attributes -- AMQP connection URL, not an HTTP request URL attributes[URL_FULL] = censoredUrl; @@ -585,15 +550,10 @@ function getConnectionAttributesFromUrl(url: unknown): SpanAttributes { const hostname = getHostname(urlParts.hostname); const port = getPort(urlParts.port ? parseInt(urlParts.port, 10) : undefined, protocol); - attributes[ATTR_MESSAGING_PROTOCOL] = protocol; // TODO(v11) remove this attribute attributes[NETWORK_PROTOCOL_NAME] = protocol; attributes[SERVER_ADDRESS] = hostname; attributes[SERVER_PORT] = port; - // eslint-disable-next-line typescript/no-deprecated -- emitted alongside SERVER_ADDRESS/SERVER_PORT for backwards compatibility - attributes[NET_PEER_NAME] = hostname; - // eslint-disable-next-line typescript/no-deprecated -- emitted alongside SERVER_ADDRESS/SERVER_PORT for backwards compatibility - attributes[NET_PEER_PORT] = port; } catch { // best-effort: a malformed url simply yields fewer connection attributes } diff --git a/packages/server-utils/src/integrations/tracing-channel/ioredis.ts b/packages/server-utils/src/integrations/tracing-channel/ioredis.ts index 0acf0d00096e..9c40e57944bf 100644 --- a/packages/server-utils/src/integrations/tracing-channel/ioredis.ts +++ b/packages/server-utils/src/integrations/tracing-channel/ioredis.ts @@ -1,9 +1,14 @@ -/* eslint-disable @typescript-eslint/no-deprecated -- we intentionally emit the OLD db/net semconv - to match `@opentelemetry/instrumentation-ioredis` (and Sentry's `inferDbSpanData`, which keys off - `db.statement`). TODO(v11): switch to the non-deprecated `db.system.name`/`db.query.text`/ - `server.address`/`server.port` conventions and drop this disable. */ import * as diagnosticsChannel from 'node:diagnostics_channel'; -import { DB_STATEMENT, DB_SYSTEM, NET_PEER_NAME, NET_PEER_PORT } from '@sentry/conventions/attributes'; +import { + DB_OPERATION_NAME, + DB_QUERY_TEXT, + DB_SYSTEM_NAME, + SENTRY_KIND, + SENTRY_OP, + SERVER_ADDRESS, + SERVER_PORT, +} from '@sentry/conventions/attributes'; +import { DATABASE_DB_QUERY_SPAN_OP, DATABASE_DB_SPAN_OP } from '@sentry/conventions/op'; import type { IntegrationFn, Span } from '@sentry/core'; import { defineIntegration, SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN, startInactiveSpan } from '@sentry/core'; import { CHANNELS } from '../../orchestrion/channels'; @@ -19,8 +24,7 @@ const INTEGRATION_NAME = 'IORedis' as const; const ORIGIN = 'auto.db.redis'; -// todo(v11): Let's drop this as this is already covered with host and port -const ATTR_DB_CONNECTION_STRING = 'db.connection_string'; +const DB_SYSTEM_VALUE_REDIS = 'redis'; /** Mirrors `@opentelemetry/instrumentation-ioredis`' response hook. Not called for failed commands. */ export type IORedisResponseHook = (span: Span, command: string, args: Array, result: unknown) => void; @@ -54,10 +58,9 @@ function getConnectionOptions(self: RedisClientLike | undefined): { host?: strin function connectionAttributes(host: string | undefined, port: number | undefined): Record { return { - [DB_SYSTEM]: 'redis', - [ATTR_DB_CONNECTION_STRING]: `redis://${host}:${port}`, - [NET_PEER_NAME]: host, - [NET_PEER_PORT]: port, + [DB_SYSTEM_NAME]: DB_SYSTEM_VALUE_REDIS, + ...(host != null ? { [SERVER_ADDRESS]: host } : {}), + ...(port != null ? { [SERVER_PORT]: port } : {}), [SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: ORIGIN, }; } @@ -87,8 +90,13 @@ export function startIORedisCommandSpan(data: IORedisCommandContext): Span | und const statement = defaultDbStatementSerializer(command.name, command.args ?? []); return startInactiveSpan({ name: statement, - op: 'db', - attributes: { ...connectionAttributes(host, port), [DB_STATEMENT]: statement }, + attributes: { + [SENTRY_KIND]: 'client', + ...connectionAttributes(host, port), + [SENTRY_OP]: DATABASE_DB_QUERY_SPAN_OP, + [DB_OPERATION_NAME]: command.name, + [DB_QUERY_TEXT]: statement, + }, }); } @@ -131,8 +139,11 @@ function instrumentIoredis(options: IORedisChannelIntegrationOptions): void { const { host, port } = getConnectionOptions(data.self); return startInactiveSpan({ name: 'connect', - op: 'db', - attributes: { ...connectionAttributes(host, port), [DB_STATEMENT]: 'connect' }, + attributes: { + [SENTRY_KIND]: 'client', + ...connectionAttributes(host, port), + [SENTRY_OP]: DATABASE_DB_SPAN_OP, + }, }); }, { requiresParentSpan: true }, diff --git a/packages/server-utils/src/integrations/tracing-channel/redis.ts b/packages/server-utils/src/integrations/tracing-channel/redis.ts index e76fe8b18832..b3a05dab1c05 100644 --- a/packages/server-utils/src/integrations/tracing-channel/redis.ts +++ b/packages/server-utils/src/integrations/tracing-channel/redis.ts @@ -1,14 +1,9 @@ -/* eslint-disable @typescript-eslint/no-deprecated -- we intentionally emit the OLD db/net semconv - to match `@opentelemetry/instrumentation-redis`. TODO(v11): switch to the non-deprecated - `db.system.name`/`db.query.text`/`server.address`/`server.port` conventions and drop this disable. */ import * as diagnosticsChannel from 'node:diagnostics_channel'; import { DB_OPERATION_BATCH_SIZE, - DB_STATEMENT, - DB_SYSTEM, + DB_OPERATION_NAME, + DB_QUERY_TEXT, DB_SYSTEM_NAME, - NET_PEER_NAME, - NET_PEER_PORT, SENTRY_KIND, SERVER_ADDRESS, SERVER_PORT, @@ -39,8 +34,6 @@ const INTEGRATION_NAME = 'RedisChannel' as const; const ORIGIN = 'auto.db.redis'; -// todo(v11): drop this — it is already covered by host and port. -const ATTR_DB_CONNECTION_STRING = 'db.connection_string'; const DB_SYSTEM_VALUE_REDIS = 'redis'; /** Mirrors `@opentelemetry/instrumentation-redis`' response hook. Not called for failed commands. */ @@ -117,27 +110,11 @@ function stripCommandOptions(args: unknown[]): unknown[] { return args; } -function removeCredentialsFromConnectionString(url: string | undefined): string | undefined { - if (typeof url !== 'string' || !url) { - return undefined; - } - try { - const parsed = new URL(url); - parsed.searchParams.delete('user_pwd'); - parsed.username = ''; - parsed.password = ''; - return parsed.href; - } catch { - return undefined; - } -} - function nodeRedisAttributes(options: NodeRedisClientOptions | undefined): SpanAttributes { return { - [DB_SYSTEM]: DB_SYSTEM_VALUE_REDIS, - [NET_PEER_NAME]: options?.socket?.host, - [NET_PEER_PORT]: options?.socket?.port, - [ATTR_DB_CONNECTION_STRING]: removeCredentialsFromConnectionString(options?.url), + [DB_SYSTEM_NAME]: DB_SYSTEM_VALUE_REDIS, + ...(options?.socket?.host != null ? { [SERVER_ADDRESS]: options.socket.host } : {}), + ...(options?.socket?.port != null ? { [SERVER_PORT]: options.socket.port } : {}), [SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: ORIGIN, }; } @@ -150,7 +127,8 @@ function startCommandSpan(commandName: string, commandArgs: Array { vi.restoreAllMocks(); }); - it('builds a db span with the orchestrion origin and stable db/net attributes', () => { + it('builds a db query span with Sentry convention attributes', () => { startIORedisCommandSpan(ctx({ name: 'set', args: ['test-key', 'test-value'] })); expect(startInactiveSpanSpy).toHaveBeenCalledWith( expect.objectContaining({ name: 'set test-key [1 other arguments]', - op: 'db', attributes: expect.objectContaining({ - 'db.system': 'redis', - 'db.connection_string': 'redis://localhost:6379', - 'net.peer.name': 'localhost', - 'net.peer.port': 6379, - 'db.statement': 'set test-key [1 other arguments]', + 'sentry.op': 'db.query', + 'db.system.name': 'redis', + 'db.operation.name': 'set', + 'db.query.text': 'set test-key [1 other arguments]', + 'server.address': 'localhost', + 'server.port': 6379, 'sentry.origin': 'auto.db.redis', }), }), From 8b511ca813554d29a030c6b36012f71f643ac2a5 Mon Sep 17 00:00:00 2001 From: s1gr1d <32902192+s1gr1d@users.noreply.github.com> Date: Wed, 12 Aug 2026 13:06:31 +0200 Subject: [PATCH 2/3] fix tests --- .../astro-7-orchestrion/tests/db.test.ts | 14 ++++++++------ .../create-remix-app-v2/tests/db.test.ts | 14 ++++++++------ .../nextjs-16-orchestrion/tests/db-page.test.ts | 14 ++++++++++---- .../nextjs-16-orchestrion/tests/ioredis.test.ts | 14 ++++++++------ .../nuxt-4/tests/db-drivers.test.ts | 14 ++++++++------ .../tests/performance/db.server.test.ts | 2 +- .../test-applications/solidstart/tests/db.test.ts | 14 ++++++++------ .../sveltekit-2-orchestrion/tests/db.test.ts | 14 ++++++++------ .../tanstackstart-react/tests/db-drivers.test.ts | 14 ++++++++------ 9 files changed, 67 insertions(+), 47 deletions(-) diff --git a/dev-packages/e2e-tests/test-applications/astro-7-orchestrion/tests/db.test.ts b/dev-packages/e2e-tests/test-applications/astro-7-orchestrion/tests/db.test.ts index 5090e42f65aa..7c2621dded8a 100644 --- a/dev-packages/e2e-tests/test-applications/astro-7-orchestrion/tests/db.test.ts +++ b/dev-packages/e2e-tests/test-applications/astro-7-orchestrion/tests/db.test.ts @@ -17,25 +17,27 @@ test('Instruments ioredis automatically', async ({ baseURL }) => { expect(spans).toContainEqual( expect.objectContaining({ - op: 'db', + op: 'db.query', origin: 'auto.db.redis', description: 'set test-key [1 other arguments]', status: 'ok', data: expect.objectContaining({ - 'db.system': 'redis', - 'db.statement': 'set test-key [1 other arguments]', + 'db.system.name': 'redis', + 'db.operation.name': 'set', + 'db.query.text': 'set test-key [1 other arguments]', }), }), ); expect(spans).toContainEqual( expect.objectContaining({ - op: 'db', + op: 'db.query', origin: 'auto.db.redis', description: 'get test-key', status: 'ok', data: expect.objectContaining({ - 'db.system': 'redis', - 'db.statement': 'get test-key', + 'db.system.name': 'redis', + 'db.operation.name': 'get', + 'db.query.text': 'get test-key', }), }), ); diff --git a/dev-packages/e2e-tests/test-applications/create-remix-app-v2/tests/db.test.ts b/dev-packages/e2e-tests/test-applications/create-remix-app-v2/tests/db.test.ts index 8aebe04a9c5b..24139187a3b4 100644 --- a/dev-packages/e2e-tests/test-applications/create-remix-app-v2/tests/db.test.ts +++ b/dev-packages/e2e-tests/test-applications/create-remix-app-v2/tests/db.test.ts @@ -21,25 +21,27 @@ test.describe('orchestrion DB instrumentation', () => { expect(spans).toContainEqual( expect.objectContaining({ - op: 'db', + op: 'db.query', origin: 'auto.db.redis', description: 'set test-key [1 other arguments]', status: 'ok', data: expect.objectContaining({ - 'db.system': 'redis', - 'db.statement': 'set test-key [1 other arguments]', + 'db.system.name': 'redis', + 'db.operation.name': 'set', + 'db.query.text': 'set test-key [1 other arguments]', }), }), ); expect(spans).toContainEqual( expect.objectContaining({ - op: 'db', + op: 'db.query', origin: 'auto.db.redis', description: 'get test-key', status: 'ok', data: expect.objectContaining({ - 'db.system': 'redis', - 'db.statement': 'get test-key', + 'db.system.name': 'redis', + 'db.operation.name': 'get', + 'db.query.text': 'get test-key', }), }), ); diff --git a/dev-packages/e2e-tests/test-applications/nextjs-16-orchestrion/tests/db-page.test.ts b/dev-packages/e2e-tests/test-applications/nextjs-16-orchestrion/tests/db-page.test.ts index a908ee27063d..a343e14be475 100644 --- a/dev-packages/e2e-tests/test-applications/nextjs-16-orchestrion/tests/db-page.test.ts +++ b/dev-packages/e2e-tests/test-applications/nextjs-16-orchestrion/tests/db-page.test.ts @@ -30,22 +30,28 @@ test('Instruments DB calls made during server-side rendering of a page', async ( ); expect(spans).toContainEqual( expect.objectContaining({ - op: 'db', + op: 'db.query', origin: 'auto.db.redis', description: 'set page-key [1 other arguments]', status: 'ok', data: expect.objectContaining({ - 'db.system': 'redis', - 'db.statement': 'set page-key [1 other arguments]', + 'db.system.name': 'redis', + 'db.operation.name': 'set', + 'db.query.text': 'set page-key [1 other arguments]', }), }), ); expect(spans).toContainEqual( expect.objectContaining({ - op: 'db', + op: 'db.query', origin: 'auto.db.redis', description: 'get page-key', status: 'ok', + data: expect.objectContaining({ + 'db.system.name': 'redis', + 'db.operation.name': 'get', + 'db.query.text': 'get page-key', + }), }), ); }); diff --git a/dev-packages/e2e-tests/test-applications/nextjs-16-orchestrion/tests/ioredis.test.ts b/dev-packages/e2e-tests/test-applications/nextjs-16-orchestrion/tests/ioredis.test.ts index ba8ccc75f9fd..48cba0778b23 100644 --- a/dev-packages/e2e-tests/test-applications/nextjs-16-orchestrion/tests/ioredis.test.ts +++ b/dev-packages/e2e-tests/test-applications/nextjs-16-orchestrion/tests/ioredis.test.ts @@ -19,25 +19,27 @@ test('Instruments ioredis automatically via orchestrion', async ({ baseURL }) => expect(spans).toContainEqual( expect.objectContaining({ - op: 'db', + op: 'db.query', origin: 'auto.db.redis', description: 'set test-key [1 other arguments]', status: 'ok', data: expect.objectContaining({ - 'db.system': 'redis', - 'db.statement': 'set test-key [1 other arguments]', + 'db.system.name': 'redis', + 'db.operation.name': 'set', + 'db.query.text': 'set test-key [1 other arguments]', }), }), ); expect(spans).toContainEqual( expect.objectContaining({ - op: 'db', + op: 'db.query', origin: 'auto.db.redis', description: 'get test-key', status: 'ok', data: expect.objectContaining({ - 'db.system': 'redis', - 'db.statement': 'get test-key', + 'db.system.name': 'redis', + 'db.operation.name': 'get', + 'db.query.text': 'get test-key', }), }), ); diff --git a/dev-packages/e2e-tests/test-applications/nuxt-4/tests/db-drivers.test.ts b/dev-packages/e2e-tests/test-applications/nuxt-4/tests/db-drivers.test.ts index 464850a116dd..c87104ef9a76 100644 --- a/dev-packages/e2e-tests/test-applications/nuxt-4/tests/db-drivers.test.ts +++ b/dev-packages/e2e-tests/test-applications/nuxt-4/tests/db-drivers.test.ts @@ -25,25 +25,27 @@ test('Instruments ioredis automatically', async ({ baseURL }) => { expect(spans).toContainEqual( expect.objectContaining({ - op: 'db', + op: 'db.query', origin: 'auto.db.redis', description: 'set test-key [1 other arguments]', status: 'ok', data: expect.objectContaining({ - 'db.system': 'redis', - 'db.statement': 'set test-key [1 other arguments]', + 'db.system.name': 'redis', + 'db.operation.name': 'set', + 'db.query.text': 'set test-key [1 other arguments]', }), }), ); expect(spans).toContainEqual( expect.objectContaining({ - op: 'db', + op: 'db.query', origin: 'auto.db.redis', description: 'get test-key', status: 'ok', data: expect.objectContaining({ - 'db.system': 'redis', - 'db.statement': 'get test-key', + 'db.system.name': 'redis', + 'db.operation.name': 'get', + 'db.query.text': 'get test-key', }), }), ); diff --git a/dev-packages/e2e-tests/test-applications/react-router-7-framework-instrumentation/tests/performance/db.server.test.ts b/dev-packages/e2e-tests/test-applications/react-router-7-framework-instrumentation/tests/performance/db.server.test.ts index 7812077a547d..6a1c06ea77f5 100644 --- a/dev-packages/e2e-tests/test-applications/react-router-7-framework-instrumentation/tests/performance/db.server.test.ts +++ b/dev-packages/e2e-tests/test-applications/react-router-7-framework-instrumentation/tests/performance/db.server.test.ts @@ -59,7 +59,7 @@ test.describe('server - orchestrion build-time db instrumentation', () => { // Every db span nests under the native instrumentation-API http.server transaction. const rootSpanId = transactionEvent.contexts?.trace?.span_id; const spanIds = new Set([rootSpanId, ...spans.map(span => span.span_id)]); - const dbSpans = spans.filter(span => span.op === 'db'); + const dbSpans = spans.filter(span => span.origin === 'auto.db.redis'); expect(dbSpans.every(span => typeof span.parent_span_id === 'string' && spanIds.has(span.parent_span_id))).toBe( true, ); diff --git a/dev-packages/e2e-tests/test-applications/solidstart/tests/db.test.ts b/dev-packages/e2e-tests/test-applications/solidstart/tests/db.test.ts index 31d3569c77c5..c5ba07733bf9 100644 --- a/dev-packages/e2e-tests/test-applications/solidstart/tests/db.test.ts +++ b/dev-packages/e2e-tests/test-applications/solidstart/tests/db.test.ts @@ -15,25 +15,27 @@ test('Instruments ioredis automatically via build-time orchestrion', async ({ ba expect(spans).toContainEqual( expect.objectContaining({ - op: 'db', + op: 'db.query', origin: 'auto.db.redis', description: 'set test-key [1 other arguments]', status: 'ok', data: expect.objectContaining({ - 'db.system': 'redis', - 'db.statement': 'set test-key [1 other arguments]', + 'db.system.name': 'redis', + 'db.operation.name': 'set', + 'db.query.text': 'set test-key [1 other arguments]', }), }), ); expect(spans).toContainEqual( expect.objectContaining({ - op: 'db', + op: 'db.query', origin: 'auto.db.redis', description: 'get test-key', status: 'ok', data: expect.objectContaining({ - 'db.system': 'redis', - 'db.statement': 'get test-key', + 'db.system.name': 'redis', + 'db.operation.name': 'get', + 'db.query.text': 'get test-key', }), }), ); diff --git a/dev-packages/e2e-tests/test-applications/sveltekit-2-orchestrion/tests/db.test.ts b/dev-packages/e2e-tests/test-applications/sveltekit-2-orchestrion/tests/db.test.ts index c9928586cd23..f9585c774458 100644 --- a/dev-packages/e2e-tests/test-applications/sveltekit-2-orchestrion/tests/db.test.ts +++ b/dev-packages/e2e-tests/test-applications/sveltekit-2-orchestrion/tests/db.test.ts @@ -17,25 +17,27 @@ test('Instruments ioredis automatically', async ({ baseURL }) => { expect(spans).toContainEqual( expect.objectContaining({ - op: 'db', + op: 'db.query', origin: 'auto.db.redis', description: 'set test-key [1 other arguments]', status: 'ok', data: expect.objectContaining({ - 'db.system': 'redis', - 'db.statement': 'set test-key [1 other arguments]', + 'db.system.name': 'redis', + 'db.operation.name': 'set', + 'db.query.text': 'set test-key [1 other arguments]', }), }), ); expect(spans).toContainEqual( expect.objectContaining({ - op: 'db', + op: 'db.query', origin: 'auto.db.redis', description: 'get test-key', status: 'ok', data: expect.objectContaining({ - 'db.system': 'redis', - 'db.statement': 'get test-key', + 'db.system.name': 'redis', + 'db.operation.name': 'get', + 'db.query.text': 'get test-key', }), }), ); diff --git a/dev-packages/e2e-tests/test-applications/tanstackstart-react/tests/db-drivers.test.ts b/dev-packages/e2e-tests/test-applications/tanstackstart-react/tests/db-drivers.test.ts index 7fb3242a165a..5fa9faef0bf6 100644 --- a/dev-packages/e2e-tests/test-applications/tanstackstart-react/tests/db-drivers.test.ts +++ b/dev-packages/e2e-tests/test-applications/tanstackstart-react/tests/db-drivers.test.ts @@ -24,25 +24,27 @@ test('Instruments ioredis automatically', async ({ baseURL }) => { expect(spans).toContainEqual( expect.objectContaining({ - op: 'db', + op: 'db.query', origin: 'auto.db.redis', description: 'set test-key [1 other arguments]', status: 'ok', data: expect.objectContaining({ - 'db.system': 'redis', - 'db.statement': 'set test-key [1 other arguments]', + 'db.system.name': 'redis', + 'db.operation.name': 'set', + 'db.query.text': 'set test-key [1 other arguments]', }), }), ); expect(spans).toContainEqual( expect.objectContaining({ - op: 'db', + op: 'db.query', origin: 'auto.db.redis', description: 'get test-key', status: 'ok', data: expect.objectContaining({ - 'db.system': 'redis', - 'db.statement': 'get test-key', + 'db.system.name': 'redis', + 'db.operation.name': 'get', + 'db.query.text': 'get test-key', }), }), ); From b3076e603298c015403131a95f2863cca76e5775 Mon Sep 17 00:00:00 2001 From: s1gr1d <32902192+s1gr1d@users.noreply.github.com> Date: Wed, 12 Aug 2026 13:43:55 +0200 Subject: [PATCH 3/3] fix react-router tests --- .../tests/performance/db.server.test.ts | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/dev-packages/e2e-tests/test-applications/react-router-7-framework-instrumentation/tests/performance/db.server.test.ts b/dev-packages/e2e-tests/test-applications/react-router-7-framework-instrumentation/tests/performance/db.server.test.ts index 6a1c06ea77f5..2cb081533c5a 100644 --- a/dev-packages/e2e-tests/test-applications/react-router-7-framework-instrumentation/tests/performance/db.server.test.ts +++ b/dev-packages/e2e-tests/test-applications/react-router-7-framework-instrumentation/tests/performance/db.server.test.ts @@ -29,25 +29,27 @@ test.describe('server - orchestrion build-time db instrumentation', () => { expect(spans).toContainEqual( expect.objectContaining({ - op: 'db', + op: 'db.query', origin: 'auto.db.redis', description: 'set test-key [1 other arguments]', status: 'ok', data: expect.objectContaining({ - 'db.system': 'redis', - 'db.statement': 'set test-key [1 other arguments]', + 'db.system.name': 'redis', + 'db.operation.name': 'set', + 'db.query.text': 'set test-key [1 other arguments]', }), }), ); expect(spans).toContainEqual( expect.objectContaining({ - op: 'db', + op: 'db.query', origin: 'auto.db.redis', description: 'get test-key', status: 'ok', data: expect.objectContaining({ - 'db.system': 'redis', - 'db.statement': 'get test-key', + 'db.system.name': 'redis', + 'db.operation.name': 'get', + 'db.query.text': 'get test-key', }), }), );