|
1 | | -import type { TransactionEvent } from '@sentry/core'; |
2 | 1 | import { expect, it } from 'vitest'; |
3 | 2 | import { createRunner } from '../../../runner'; |
| 3 | +import { getSpanOp, getSpansFromEnvelope } from '../../../spanUtils'; |
4 | 4 |
|
5 | 5 | // `MyWorkflow` is hand-wrapped in `./workflow` and only re-exported by the |
6 | 6 | // entry, so the transform's emitted `_INTERNAL_wrapUnlessInstrumented` guard |
7 | 7 | // must hand the manual wrap back instead of nesting a second wrapper. Nested |
8 | 8 | // workflow wrappers each run the step through their own client, producing TWO |
9 | | -// identical `step-one` transactions, each individually well-formed, so the |
10 | | -// real check is the count assertion at the end. |
| 9 | +// identical `step-one` spans, each individually well-formed, so the real check |
| 10 | +// is the count assertion at the end. |
11 | 11 | // |
12 | 12 | // Ordering is anchored by a sentinel rather than by waiting: `/trigger` |
13 | 13 | // responds only after the workflow finished (every step envelope, including a |
14 | 14 | // duplicate, is flushed before then), and `/sentinel` is requested after that, |
15 | | -// so its transaction arrives a full request/response cycle behind any |
16 | | -// duplicate. Once the sentinel envelope has been matched, everything sent |
17 | | -// before it is known to have been delivered. |
| 15 | +// so its span arrives a full request/response cycle behind any duplicate. Once |
| 16 | +// the sentinel envelope has been matched, everything sent before it is known to |
| 17 | +// have been delivered. |
18 | 18 | it('does not double-instrument an imported, already-wrapped Workflow', async ({ signal }) => { |
19 | 19 | const runner = createRunner(__dirname) |
20 | 20 | .unordered() |
21 | 21 | .expect(envelope => { |
22 | | - const transactionEvent = envelope[1]?.[0]?.[1] as TransactionEvent; |
23 | | - expect(transactionEvent.transaction).toBe('step-one'); |
24 | | - expect(transactionEvent.contexts?.trace?.op).toBe('function'); |
25 | | - expect(transactionEvent.contexts?.trace?.origin).toBe('auto.faas.cloudflare.workflow'); |
| 22 | + const stepSpan = getSpansFromEnvelope(envelope).find(span => span.is_segment && span.name === 'step-one'); |
| 23 | + expect(getSpanOp(stepSpan!)).toBe('function'); |
| 24 | + expect(stepSpan?.attributes['sentry.origin']).toEqual({ |
| 25 | + type: 'string', |
| 26 | + value: 'auto.faas.cloudflare.workflow', |
| 27 | + }); |
26 | 28 | }) |
27 | 29 | .expect(envelope => { |
28 | | - const transactionEvent = envelope[1]?.[0]?.[1] as TransactionEvent; |
29 | | - // The auto-wrapped default export's own transaction. |
30 | | - expect(transactionEvent.transaction).toBe('GET /trigger'); |
31 | | - expect(transactionEvent.contexts?.trace?.op).toBe('http.server'); |
| 30 | + // The auto-wrapped default export's own segment span. `/trigger` is a raw URL, so the streamed |
| 31 | + // segment name keeps the method only. |
| 32 | + const segmentSpan = getSpansFromEnvelope(envelope).find(span => span.is_segment); |
| 33 | + expect(segmentSpan?.name).toBe('GET'); |
| 34 | + expect(getSpanOp(segmentSpan!)).toBe('http.server'); |
| 35 | + expect(segmentSpan?.attributes['url.path']).toEqual({ type: 'string', value: '/trigger' }); |
32 | 36 | }) |
33 | 37 | // The sentinel is part of the expected set, so the runner keeps everything |
34 | 38 | // alive (and keeps receiving envelopes) until it has arrived. |
35 | 39 | .expect(envelope => { |
36 | | - expect((envelope[1]?.[0]?.[1] as TransactionEvent).transaction).toBe('GET /sentinel'); |
| 40 | + const segmentSpan = getSpansFromEnvelope(envelope).find(span => span.is_segment); |
| 41 | + expect(segmentSpan?.attributes['url.path']).toEqual({ type: 'string', value: '/sentinel' }); |
37 | 42 | }) |
38 | 43 | .start(signal); |
39 | 44 |
|
40 | 45 | await runner.makeRequest('get', '/trigger'); |
41 | 46 | await runner.makeRequest('get', '/sentinel'); |
42 | 47 | await runner.completed(); |
43 | 48 |
|
44 | | - const stepTransactions = runner |
| 49 | + const stepSpans = runner |
45 | 50 | .getReceivedEnvelopes() |
46 | | - .filter(envelope => (envelope[1]?.[0]?.[1] as TransactionEvent | undefined)?.transaction === 'step-one'); |
47 | | - expect(stepTransactions).toHaveLength(1); |
| 51 | + .flatMap(envelope => getSpansFromEnvelope(envelope)) |
| 52 | + .filter(span => span.name === 'step-one'); |
| 53 | + expect(stepSpans).toHaveLength(1); |
48 | 54 | }); |
0 commit comments