|
1 | 1 | import { expect, test } from '@playwright/test'; |
2 | | -import { waitForTransaction } from '@sentry-internal/test-utils'; |
3 | | - |
4 | | -test('Sends an HTTP transaction', async ({ baseURL }) => { |
5 | | - const transactionEventPromise = waitForTransaction('nestjs-microservices', transactionEvent => { |
6 | | - return ( |
7 | | - transactionEvent?.contexts?.trace?.op === 'http.server' && |
8 | | - transactionEvent?.transaction === 'GET /test-transaction' |
9 | | - ); |
| 2 | +import { collectStreamedSpansUntilSegment, getSpanOp, waitForStreamedSpan } from '@sentry-internal/test-utils'; |
| 3 | + |
| 4 | +const APP_NAME = 'nestjs-microservices'; |
| 5 | + |
| 6 | +test('Sends an HTTP segment span', async ({ baseURL }) => { |
| 7 | + const spanPromise = waitForStreamedSpan(APP_NAME, span => { |
| 8 | + return span.is_segment && span.name === 'GET /test-transaction'; |
10 | 9 | }); |
11 | 10 |
|
12 | 11 | const response = await fetch(`${baseURL}/test-transaction`); |
13 | 12 | expect(response.status).toBe(200); |
14 | 13 |
|
15 | | - const transactionEvent = await transactionEventPromise; |
| 14 | + const span = await spanPromise; |
16 | 15 |
|
17 | | - expect(transactionEvent.contexts?.trace).toEqual( |
18 | | - expect.objectContaining({ |
19 | | - op: 'http.server', |
20 | | - status: 'ok', |
21 | | - }), |
22 | | - ); |
| 16 | + expect(getSpanOp(span)).toBe('http.server'); |
| 17 | + expect(span.status).toBe('ok'); |
23 | 18 | }); |
24 | 19 |
|
25 | 20 | // Trace context does not propagate over NestJS TCP transport, so RPC spans are disconnected from |
26 | | -// the HTTP transaction. Instead of appearing as child spans of the HTTP transaction, auto-instrumented |
27 | | -// NestJS guard/interceptor/pipe spans become separate standalone transactions. |
| 21 | +// the HTTP trace. Instead of appearing as child spans of the HTTP segment span, auto-instrumented |
| 22 | +// NestJS guard/interceptor/pipe spans become segment spans of their own traces. |
28 | 23 | // This documents the current (broken) behavior — ideally these should be connected to the HTTP trace. |
29 | 24 |
|
30 | | -test('Microservice spans are not connected to the HTTP transaction', async ({ baseURL }) => { |
31 | | - const httpTransactionPromise = waitForTransaction('nestjs-microservices', transactionEvent => { |
32 | | - return ( |
33 | | - transactionEvent?.contexts?.trace?.op === 'http.server' && |
34 | | - transactionEvent?.transaction === 'GET /test-microservice-sum' |
35 | | - ); |
36 | | - }); |
| 25 | +test('Microservice spans are not connected to the HTTP trace', async ({ baseURL }) => { |
| 26 | + const spansPromise = collectStreamedSpansUntilSegment(APP_NAME, 'GET /test-microservice-sum'); |
37 | 27 |
|
38 | 28 | const response = await fetch(`${baseURL}/test-microservice-sum`); |
39 | 29 | expect(response.status).toBe(200); |
40 | 30 |
|
41 | | - const httpTransaction = await httpTransactionPromise; |
| 31 | + const spans = await spansPromise; |
42 | 32 |
|
43 | | - // The microservice span should be part of this transaction but isn't due to missing trace propagation |
44 | | - const microserviceSpan = httpTransaction.spans?.find(span => span.description === 'microservice-sum-operation'); |
45 | | - expect(microserviceSpan).toBeUndefined(); |
| 33 | + // The microservice span should be part of this trace but isn't due to missing trace propagation |
| 34 | + expect(spans.find(span => span.name === 'microservice-sum-operation')).toBeUndefined(); |
46 | 35 | }); |
47 | 36 |
|
48 | | -test('Microservice guard is emitted as a standalone transaction instead of being part of the HTTP trace', async ({ |
| 37 | +test('Microservice guard is emitted as a segment span of its own trace instead of being part of the HTTP trace', async ({ |
49 | 38 | baseURL, |
50 | 39 | }) => { |
51 | | - const guardTransactionPromise = waitForTransaction('nestjs-microservices', transactionEvent => { |
52 | | - return transactionEvent?.transaction === 'ExampleGuard'; |
| 40 | + const guardSpanPromise = waitForStreamedSpan(APP_NAME, span => { |
| 41 | + return span.is_segment && span.name === 'ExampleGuard'; |
53 | 42 | }); |
54 | 43 |
|
55 | 44 | await fetch(`${baseURL}/test-microservice-guard`); |
56 | 45 |
|
57 | | - const guardTransaction = await guardTransactionPromise; |
58 | | - expect(guardTransaction).toBeDefined(); |
| 46 | + expect(await guardSpanPromise).toBeDefined(); |
59 | 47 | }); |
60 | 48 |
|
61 | | -test('Microservice interceptor is emitted as a standalone transaction instead of being part of the HTTP trace', async ({ |
| 49 | +test('Microservice interceptor is emitted as a segment span of its own trace instead of being part of the HTTP trace', async ({ |
62 | 50 | baseURL, |
63 | 51 | }) => { |
64 | | - const interceptorTransactionPromise = waitForTransaction('nestjs-microservices', transactionEvent => { |
65 | | - return transactionEvent?.transaction === 'ExampleInterceptor'; |
| 52 | + const interceptorSpanPromise = waitForStreamedSpan(APP_NAME, span => { |
| 53 | + return span.is_segment && span.name === 'ExampleInterceptor'; |
66 | 54 | }); |
67 | 55 |
|
68 | 56 | await fetch(`${baseURL}/test-microservice-interceptor`); |
69 | 57 |
|
70 | | - const interceptorTransaction = await interceptorTransactionPromise; |
71 | | - expect(interceptorTransaction).toBeDefined(); |
| 58 | + expect(await interceptorSpanPromise).toBeDefined(); |
72 | 59 | }); |
73 | 60 |
|
74 | | -test('Microservice pipe is emitted as a standalone transaction instead of being part of the HTTP trace', async ({ |
| 61 | +test('Microservice pipe is emitted as a segment span of its own trace instead of being part of the HTTP trace', async ({ |
75 | 62 | baseURL, |
76 | 63 | }) => { |
77 | | - const pipeTransactionPromise = waitForTransaction('nestjs-microservices', transactionEvent => { |
78 | | - return transactionEvent?.transaction === 'ExamplePipe'; |
| 64 | + const pipeSpanPromise = waitForStreamedSpan(APP_NAME, span => { |
| 65 | + return span.is_segment && span.name === 'ExamplePipe'; |
79 | 66 | }); |
80 | 67 |
|
81 | 68 | await fetch(`${baseURL}/test-microservice-pipe`); |
82 | 69 |
|
83 | | - const pipeTransaction = await pipeTransactionPromise; |
84 | | - expect(pipeTransaction).toBeDefined(); |
| 70 | + expect(await pipeSpanPromise).toBeDefined(); |
85 | 71 | }); |
0 commit comments