FazBrowse GitHub Viewer | Trending |
URL:
| Home
Tools: [Download Repo ZIP]   [Original HTTPS Page]

test(node): Port AMQP integration tests to span streaming (#25158) · getsentry/sentry-javascript@b6616ce · GitHub

Repository navigation

Commit b6616ce

Browse files
andauthored
test(node): Port AMQP integration tests to span streaming (#25158)
Port AMQP tests to span streaming. Part of #24137 --------- Co-authored-by: GPT-6 <codex@openai.com>
1 parent b1638a0 commit b6616ce

3 files changed

Lines changed: 65 additions & 119 deletions

File tree

‎dev-packages/node-integration-tests/suites/tracing/amqplib/instrument-span-streaming.mjs‎

Lines changed: 0 additions & 10 deletions
This file was deleted.

‎dev-packages/node-integration-tests/suites/tracing/amqplib/instrument.mjs‎

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@ import * as Sentry from '@sentry/node';
22
import { loggingTransport } from '@sentry-internal/node-integration-tests';
33

44
Sentry.init({
5-
traceLifecycle: 'static',
65
dsn: 'https://public@dsn.ingest.sentry.io/1337',
76
release: '1.0',
87
tracesSampleRate: 1.0,
Lines changed: 65 additions & 108 deletions
Original file line numberDiff line numberDiff 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';
217
import { afterAll, describe, expect } from 'vitest';
318
import { cleanupChildProcesses, createEsmAndCjsTests, describeWithDockerCompose } from '../../../utils/runner';
419

@@ -8,37 +23,35 @@ import { cleanupChildProcesses, createEsmAndCjsTests, describeWithDockerCompose
823
// default (empty) exchange with the queue name as the routing key.
924
const expectedProducerSpan = (routingKey: string) =>
1025
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' },
2640
}),
2741
status: 'ok',
2842
});
2943

3044
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' },
3447
// 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' },
4255
}),
4356
status: 'ok',
4457
});
@@ -59,40 +72,27 @@ describeWithDockerCompose('amqplib auto-instrumentation', { workingDirectory: [_
5972
'instrument.mjs',
6073
(createTestRunner, test) => {
6174
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-
6675
await createTestRunner()
6776
.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',
8481
);
8582

8683
expect(producer).toBeDefined();
8784
expect(consumer).toBeDefined();
8885

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');
9188

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');
9393
expect(producerSpan).toMatchObject(expectedProducerSpan('queue1'));
9494

95-
expect(consumer!.contexts?.trace).toMatchObject(EXPECTED_MESSAGE_SPAN_CONSUMER);
95+
expect(consumer!).toMatchObject(EXPECTED_MESSAGE_SPAN_CONSUMER);
9696
},
9797
})
9898
.start()
@@ -108,35 +108,23 @@ describeWithDockerCompose('amqplib auto-instrumentation', { workingDirectory: [_
108108
'instrument.mjs',
109109
(createTestRunner, test) => {
110110
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-
115111
await createTestRunner()
116112
.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',
127116
);
128117

129118
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(
132121
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' },
140128
}),
141129
}),
142130
);
@@ -160,11 +148,11 @@ describeWithDockerCompose('amqplib auto-instrumentation', { workingDirectory: [_
160148
async () => {
161149
await createTestRunner()
162150
.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');
165153

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',
168156
);
169157

170158
// The confirm channel internally calls the base publish; the instrumentation must not
@@ -181,35 +169,4 @@ describeWithDockerCompose('amqplib auto-instrumentation', { workingDirectory: [_
181169
{ additionalDependencies },
182170
);
183171
});
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-
});
215172
});

0 commit comments

Comments
 (0)

Back | FazBrowse Home | New Git URL