| FazBrowse GitHub Viewer | Trending | | Home |
| Tools: [Download Repo ZIP] [Original HTTPS Page] |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -2,7 +2,6 @@ import * as Sentry from '@sentry/node'; | |||
| 2 | 2 | import { loggingTransport } from '@sentry-internal/node-integration-tests'; | |
| 3 | 3 | ||
| 4 | 4 | Sentry.init({ | |
| 5 | - traceLifecycle: 'static', | ||
| 6 | 5 | dsn: 'https://public@dsn.ingest.sentry.io/1337', | |
| 7 | 6 | release: '1.0', | |
| 8 | 7 | tracesSampleRate: 1.0, | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -1,4 +1,19 @@ | |||
| 1 | - import type { TransactionEvent } from '@sentry/core'; | ||
| 1 | + import { | ||
| 2 | + MESSAGING_DESTINATION_NAME, | ||
| 3 | + MESSAGING_OPERATION_NAME, | ||
| 4 | + MESSAGING_OPERATION_TYPE, | ||
| 5 | + MESSAGING_RABBITMQ_DESTINATION_ROUTING_KEY, | ||
| 6 | + MESSAGING_SYSTEM, | ||
| 7 | + NETWORK_PROTOCOL_NAME, | ||
| 8 | + NETWORK_PROTOCOL_VERSION, | ||
| 9 | + SENTRY_KIND, | ||
| 10 | + SENTRY_OP, | ||
| 11 | + SENTRY_ORIGIN, | ||
| 12 | + SERVER_ADDRESS, | ||
| 13 | + SERVER_PORT, | ||
| 14 | + URL_FULL, | ||
| 15 | + } from '@sentry/conventions/attributes'; | ||
| 16 | + import { QUEUE_PROCESS, QUEUE_PUBLISH } from '@sentry/conventions/op'; | ||
| 2 | 17 | import { afterAll, describe, expect } from 'vitest'; | |
| 3 | 18 | import { cleanupChildProcesses, createEsmAndCjsTests, describeWithDockerCompose } from '../../../utils/runner'; | |
| 4 | 19 | ||
@@ -8,37 +23,35 @@ import { cleanupChildProcesses, createEsmAndCjsTests, describeWithDockerCompose | |||
| 8 | 23 | // default (empty) exchange with the queue name as the routing key. | |
| 9 | 24 | const expectedProducerSpan = (routingKey: string) => | |
| 10 | 25 | expect.objectContaining({ | |
| 11 | - op: 'queue.publish', | ||
| 12 | - data: expect.objectContaining({ | ||
| 13 | - 'messaging.system': 'rabbitmq', | ||
| 14 | - 'messaging.operation.name': 'send', | ||
| 15 | - 'messaging.operation.type': 'send', | ||
| 16 | - 'messaging.destination.name': routingKey, | ||
| 17 | - 'messaging.rabbitmq.destination.routing_key': routingKey, | ||
| 18 | - 'network.protocol.name': 'AMQP', | ||
| 19 | - 'network.protocol.version': '0.9.1', | ||
| 20 | - 'server.address': 'localhost', | ||
| 21 | - 'server.port': 5672, | ||
| 22 | - 'url.full': 'amqp://sentry:***@localhost:5672/', | ||
| 23 | - 'sentry.kind': 'producer', | ||
| 24 | - 'sentry.op': 'queue.publish', | ||
| 25 | - 'sentry.origin': 'auto.amqplib.publisher', | ||
| 26 | + attributes: expect.objectContaining({ | ||
| 27 | + [MESSAGING_SYSTEM]: { type: 'string', value: 'rabbitmq' }, | ||
| 28 | + [MESSAGING_OPERATION_NAME]: { type: 'string', value: 'send' }, | ||
| 29 | + [MESSAGING_OPERATION_TYPE]: { type: 'string', value: 'send' }, | ||
| 30 | + [MESSAGING_DESTINATION_NAME]: { type: 'string', value: routingKey }, | ||
| 31 | + [MESSAGING_RABBITMQ_DESTINATION_ROUTING_KEY]: { type: 'string', value: routingKey }, | ||
| 32 | + [NETWORK_PROTOCOL_NAME]: { type: 'string', value: 'AMQP' }, | ||
| 33 | + [NETWORK_PROTOCOL_VERSION]: { type: 'string', value: '0.9.1' }, | ||
| 34 | + [SERVER_ADDRESS]: { type: 'string', value: 'localhost' }, | ||
| 35 | + [SERVER_PORT]: { type: 'integer', value: 5672 }, | ||
| 36 | + [URL_FULL]: { type: 'string', value: 'amqp://sentry:***@localhost:5672/' }, | ||
| 37 | + [SENTRY_KIND]: { type: 'string', value: 'producer' }, | ||
| 38 | + [SENTRY_OP]: { type: 'string', value: QUEUE_PUBLISH }, | ||
| 39 | + [SENTRY_ORIGIN]: { type: 'string', value: 'auto.amqplib.publisher' }, | ||
| 26 | 40 | }), | |
| 27 | 41 | status: 'ok', | |
| 28 | 42 | }); | |
| 29 | 43 | ||
| 30 | 44 | const EXPECTED_MESSAGE_SPAN_CONSUMER = expect.objectContaining({ | |
| 31 | - op: 'queue.process', | ||
| 32 | - data: expect.objectContaining({ | ||
| 33 | - 'messaging.system': 'rabbitmq', | ||
| 45 | + attributes: expect.objectContaining({ | ||
| 46 | + [MESSAGING_SYSTEM]: { type: 'string', value: 'rabbitmq' }, | ||
| 34 | 47 | // The delivery carries the default exchange (''), so the routing key is the destination. | |
| 35 | - 'messaging.destination.name': 'queue1', | ||
| 36 | - 'messaging.rabbitmq.destination.routing_key': 'queue1', | ||
| 37 | - 'messaging.operation.name': 'process', | ||
| 38 | - 'messaging.operation.type': 'process', | ||
| 39 | - 'sentry.kind': 'consumer', | ||
| 40 | - 'sentry.op': 'queue.process', | ||
| 41 | - 'sentry.origin': 'auto.amqplib.consumer', | ||
| 48 | + [MESSAGING_DESTINATION_NAME]: { type: 'string', value: 'queue1' }, | ||
| 49 | + [MESSAGING_RABBITMQ_DESTINATION_ROUTING_KEY]: { type: 'string', value: 'queue1' }, | ||
| 50 | + [MESSAGING_OPERATION_NAME]: { type: 'string', value: 'process' }, | ||
| 51 | + [MESSAGING_OPERATION_TYPE]: { type: 'string', value: 'process' }, | ||
| 52 | + [SENTRY_KIND]: { type: 'string', value: 'consumer' }, | ||
| 53 | + [SENTRY_OP]: { type: 'string', value: QUEUE_PROCESS }, | ||
| 54 | + [SENTRY_ORIGIN]: { type: 'string', value: 'auto.amqplib.consumer' }, | ||
| 42 | 55 | }), | |
| 43 | 56 | status: 'ok', | |
| 44 | 57 | }); | |
@@ -59,40 +72,27 @@ describeWithDockerCompose('amqplib auto-instrumentation', { workingDirectory: [_ | |||
| 59 | 72 | 'instrument.mjs', | |
| 60 | 73 | (createTestRunner, test) => { | |
| 61 | 74 | test('should be able to send and receive messages', { timeout: 60_000 }, async () => { | |
| 62 | - // The producer ('root span') and consumer ('queue1 process') transactions can | ||
| 63 | - // arrive in any order, so we collect them and assert after both are received. | ||
| 64 | - const receivedTransactions: TransactionEvent[] = []; | ||
| 65 | - | ||
| 66 | 75 | await createTestRunner() | |
| 67 | 76 | .expect({ | |
| 68 | - transaction: (transaction: TransactionEvent) => { | ||
| 69 | - receivedTransactions.push(transaction); | ||
| 70 | - }, | ||
| 71 | - }) | ||
| 72 | - .expect({ | ||
| 73 | - transaction: (transaction: TransactionEvent) => { | ||
| 74 | - receivedTransactions.push(transaction); | ||
| 75 | - | ||
| 76 | - // The producer span is a child of the manually-started 'root span' transaction, so we | ||
| 77 | - // identify it by its origin rather than by transaction name. The consumer span is its | ||
| 78 | - // own transaction, identified by the origin on its trace context. | ||
| 79 | - const producer = receivedTransactions.find(t => | ||
| 80 | - t.spans?.some(s => s.data?.['sentry.origin'] === 'auto.amqplib.publisher'), | ||
| 81 | - ); | ||
| 82 | - const consumer = receivedTransactions.find( | ||
| 83 | - t => t.contexts?.trace?.data?.['sentry.origin'] === 'auto.amqplib.consumer', | ||
| 77 | + span: container => { | ||
| 78 | + const producer = container.items.find(span => span.is_segment && span.name === 'root span'); | ||
| 79 | + const consumer = container.items.find( | ||
| 80 | + t => t.attributes[SENTRY_ORIGIN]?.value === 'auto.amqplib.consumer', | ||
| 84 | 81 | ); | |
| 85 | 82 | ||
| 86 | 83 | expect(producer).toBeDefined(); | |
| 87 | 84 | expect(consumer).toBeDefined(); | |
| 88 | 85 | ||
| 89 | - expect(producer!.transaction).toBe('root span'); | ||
| 90 | - expect(consumer!.transaction).toBe('queue1 process'); | ||
| 86 | + expect(producer!.name).toBe('root span'); | ||
| 87 | + expect(consumer!.name).toBe('process queue1'); | ||
| 91 | 88 | ||
| 92 | - const producerSpan = producer!.spans?.find(s => s.data?.['sentry.origin'] === 'auto.amqplib.publisher'); | ||
| 89 | + const producerSpan = container.items.find( | ||
| 90 | + s => s.attributes[SENTRY_ORIGIN]?.value === 'auto.amqplib.publisher', | ||
| 91 | + ); | ||
| 92 | + expect(producerSpan?.name).toBe('send queue1'); | ||
| 93 | 93 | expect(producerSpan).toMatchObject(expectedProducerSpan('queue1')); | |
| 94 | 94 | ||
| 95 | - expect(consumer!.contexts?.trace).toMatchObject(EXPECTED_MESSAGE_SPAN_CONSUMER); | ||
| 95 | + expect(consumer!).toMatchObject(EXPECTED_MESSAGE_SPAN_CONSUMER); | ||
| 96 | 96 | }, | |
| 97 | 97 | }) | |
| 98 | 98 | .start() | |
@@ -108,35 +108,23 @@ describeWithDockerCompose('amqplib auto-instrumentation', { workingDirectory: [_ | |||
| 108 | 108 | 'instrument.mjs', | |
| 109 | 109 | (createTestRunner, test) => { | |
| 110 | 110 | test('marks the consumer span as errored when the message is rejected', { timeout: 60_000 }, async () => { | |
| 111 | - // The error scenario emits the producer ('root span') and the rejected consumer | ||
| 112 | - // ('queue1 process') transactions in any order, so we collect both and assert on the consumer. | ||
| 113 | - const receivedTransactions: TransactionEvent[] = []; | ||
| 114 | - | ||
| 115 | 111 | await createTestRunner() | |
| 116 | 112 | .expect({ | |
| 117 | - transaction: (transaction: TransactionEvent) => { | ||
| 118 | - receivedTransactions.push(transaction); | ||
| 119 | - }, | ||
| 120 | - }) | ||
| 121 | - .expect({ | ||
| 122 | - transaction: (transaction: TransactionEvent) => { | ||
| 123 | - receivedTransactions.push(transaction); | ||
| 124 | - | ||
| 125 | - const consumer = receivedTransactions.find( | ||
| 126 | - t => t.contexts?.trace?.data?.['sentry.origin'] === 'auto.amqplib.consumer', | ||
| 113 | + span: container => { | ||
| 114 | + const consumer = container.items.find( | ||
| 115 | + t => t.attributes[SENTRY_ORIGIN]?.value === 'auto.amqplib.consumer', | ||
| 127 | 116 | ); | |
| 128 | 117 | ||
| 129 | 118 | expect(consumer).toBeDefined(); | |
| 130 | - expect(consumer!.transaction).toBe('queue-error process'); | ||
| 131 | - expect(consumer!.contexts?.trace).toMatchObject( | ||
| 119 | + expect(consumer!.name).toBe('process queue-error'); | ||
| 120 | + expect(consumer!).toMatchObject( | ||
| 132 | 121 | expect.objectContaining({ | |
| 133 | - op: 'queue.process', | ||
| 134 | - status: 'internal_error', | ||
| 135 | - data: expect.objectContaining({ | ||
| 136 | - 'messaging.system': 'rabbitmq', | ||
| 137 | - 'sentry.kind': 'consumer', | ||
| 138 | - 'sentry.op': 'queue.process', | ||
| 139 | - 'sentry.origin': 'auto.amqplib.consumer', | ||
| 122 | + status: 'error', | ||
| 123 | + attributes: expect.objectContaining({ | ||
| 124 | + [MESSAGING_SYSTEM]: { type: 'string', value: 'rabbitmq' }, | ||
| 125 | + [SENTRY_KIND]: { type: 'string', value: 'consumer' }, | ||
| 126 | + [SENTRY_OP]: { type: 'string', value: QUEUE_PROCESS }, | ||
| 127 | + [SENTRY_ORIGIN]: { type: 'string', value: 'auto.amqplib.consumer' }, | ||
| 140 | 128 | }), | |
| 141 | 129 | }), | |
| 142 | 130 | ); | |
@@ -160,11 +148,11 @@ describeWithDockerCompose('amqplib auto-instrumentation', { workingDirectory: [_ | |||
| 160 | 148 | async () => { | |
| 161 | 149 | await createTestRunner() | |
| 162 | 150 | .expect({ | |
| 163 | - transaction: (transaction: TransactionEvent) => { | ||
| 164 | - expect(transaction.transaction).toBe('root span'); | ||
| 151 | + span: container => { | ||
| 152 | + expect(container.items.find(span => span.is_segment)?.name).toBe('root span'); | ||
| 165 | 153 | ||
| 166 | - const producerSpans = transaction.spans?.filter( | ||
| 167 | - s => s.data?.['sentry.origin'] === 'auto.amqplib.publisher', | ||
| 154 | + const producerSpans = container.items.filter( | ||
| 155 | + s => s.attributes[SENTRY_ORIGIN]?.value === 'auto.amqplib.publisher', | ||
| 168 | 156 | ); | |
| 169 | 157 | ||
| 170 | 158 | // The confirm channel internally calls the base publish; the instrumentation must not | |
@@ -181,35 +169,4 @@ describeWithDockerCompose('amqplib auto-instrumentation', { workingDirectory: [_ | |||
| 181 | 169 | { additionalDependencies }, | |
| 182 | 170 | ); | |
| 183 | 171 | }); | |
| 184 | - | ||
| 185 | - createEsmAndCjsTests(__dirname, 'scenario.mjs', 'instrument-span-streaming.mjs', (createTestRunner, test) => { | ||
| 186 | - test('names streamed spans after the messaging conventions', { timeout: 60_000 }, async () => { | ||
| 187 | - await createTestRunner() | ||
| 188 | - .ignore('event') | ||
| 189 | - .expect({ | ||
| 190 | - span: container => { | ||
| 191 | - // `sendToQueue` publishes to the default exchange, which has no name. Its routing key is the | ||
| 192 | - // queue name, so it is the destination rather than per-message data. | ||
| 193 | - for (const origin of ['auto.amqplib.publisher', 'auto.amqplib.consumer']) { | ||
| 194 | - const span = container.items.find(item => item.attributes['sentry.origin']?.value === origin); | ||
| 195 | - expect(span).toBeDefined(); | ||
| 196 | - expect(span!.attributes['messaging.destination.name']?.value).toBe('queue1'); | ||
| 197 | - expect(span!.attributes['messaging.rabbitmq.destination.routing_key']?.value).toBe('queue1'); | ||
| 198 | - } | ||
| 199 | - | ||
| 200 | - const producerSpan = container.items.find( | ||
| 201 | - span => span.attributes['sentry.origin']?.value === 'auto.amqplib.publisher', | ||
| 202 | - ); | ||
| 203 | - expect(producerSpan!.name).toBe('send queue1'); | ||
| 204 | - | ||
| 205 | - const consumerSpan = container.items.find( | ||
| 206 | - span => span.attributes['sentry.origin']?.value === 'auto.amqplib.consumer', | ||
| 207 | - ); | ||
| 208 | - expect(consumerSpan!.name).toBe('process queue1'); | ||
| 209 | - }, | ||
| 210 | - }) | ||
| 211 | - .start() | ||
| 212 | - .completed(); | ||
| 213 | - }); | ||
| 214 | - }); | ||
| 215 | 172 | }); | |
| Back | FazBrowse Home | New Git URL |
0 commit comments