|
1 | 1 | import { expect, it } from 'vitest'; |
2 | | -import type { Event } from '@sentry/core'; |
| 2 | +import type { SerializedStreamedSpan } from '@sentry/core'; |
3 | 3 | import { createRunner } from '../../../../runner'; |
| 4 | +import { getSpanOp, getSpansFromEnvelope } from '../../../../spanUtils'; |
4 | 5 |
|
5 | 6 | it('propagates trace from worker to durable object over stub.fetch() when rpcTracePropagationBindings is empty', async ({ |
6 | 7 | signal, |
7 | 8 | }) => { |
8 | | - let workerTraceId: string | undefined; |
9 | | - let workerSpanId: string | undefined; |
10 | | - let doTraceId: string | undefined; |
11 | | - let doParentSpanId: string | undefined; |
| 9 | + let workerSpan: SerializedStreamedSpan | undefined; |
| 10 | + let doSpan: SerializedStreamedSpan | undefined; |
12 | 11 |
|
13 | 12 | const runner = createRunner(__dirname) |
14 | 13 | .expect(envelope => { |
15 | | - const transactionEvent = envelope[1]?.[0]?.[1] as Event; |
16 | | - |
17 | | - expect(transactionEvent).toEqual( |
18 | | - expect.objectContaining({ |
19 | | - contexts: expect.objectContaining({ |
20 | | - trace: expect.objectContaining({ |
21 | | - op: 'http.server', |
22 | | - data: expect.objectContaining({ |
23 | | - 'sentry.origin': 'auto.http.cloudflare', |
24 | | - }), |
25 | | - origin: 'auto.http.cloudflare', |
26 | | - }), |
27 | | - }), |
28 | | - transaction: 'GET /hello', |
29 | | - }), |
30 | | - ); |
31 | | - doTraceId = transactionEvent.contexts?.trace?.trace_id as string; |
32 | | - doParentSpanId = transactionEvent.contexts?.trace?.parent_span_id as string; |
| 14 | + const segmentSpan = getSpansFromEnvelope(envelope).find(span => span.is_segment); |
| 15 | + |
| 16 | + expect(getSpanOp(segmentSpan!)).toBe('http.server'); |
| 17 | + expect(segmentSpan?.attributes['sentry.origin']).toEqual({ type: 'string', value: 'auto.http.cloudflare' }); |
| 18 | + // `/hello` is a raw URL, so the streamed segment name keeps the method only. |
| 19 | + expect(segmentSpan?.attributes['url.path']).toEqual({ type: 'string', value: '/hello' }); |
| 20 | + doSpan = segmentSpan; |
33 | 21 | }) |
34 | 22 | .expect(envelope => { |
35 | | - const transactionEvent = envelope[1]?.[0]?.[1] as Event; |
36 | | - |
37 | | - expect(transactionEvent).toEqual( |
38 | | - expect.objectContaining({ |
39 | | - contexts: expect.objectContaining({ |
40 | | - trace: expect.objectContaining({ |
41 | | - op: 'http.server', |
42 | | - data: expect.objectContaining({ |
43 | | - 'sentry.origin': 'auto.http.cloudflare', |
44 | | - }), |
45 | | - origin: 'auto.http.cloudflare', |
46 | | - }), |
47 | | - }), |
48 | | - transaction: 'GET /', |
49 | | - }), |
50 | | - ); |
51 | | - workerTraceId = transactionEvent.contexts?.trace?.trace_id as string; |
52 | | - workerSpanId = transactionEvent.contexts?.trace?.span_id as string; |
| 23 | + const segmentSpan = getSpansFromEnvelope(envelope).find(span => span.is_segment); |
| 24 | + |
| 25 | + expect(getSpanOp(segmentSpan!)).toBe('http.server'); |
| 26 | + expect(segmentSpan?.attributes['sentry.origin']).toEqual({ type: 'string', value: 'auto.http.cloudflare' }); |
| 27 | + expect(segmentSpan?.name).toBe('GET /'); |
| 28 | + workerSpan = segmentSpan; |
53 | 29 | }) |
54 | 30 | .unordered() |
55 | 31 | .start(signal); |
56 | 32 | await runner.makeRequest('get', '/'); |
57 | 33 | await runner.completed(); |
58 | 34 |
|
59 | | - expect(workerTraceId).toBeDefined(); |
60 | | - expect(doTraceId).toBe(workerTraceId); |
61 | | - |
62 | | - expect(workerSpanId).toBeDefined(); |
63 | | - expect(doParentSpanId).toBe(workerSpanId); |
| 35 | + expect(workerSpan?.trace_id).toBeDefined(); |
| 36 | + expect(doSpan?.trace_id).toBe(workerSpan?.trace_id); |
| 37 | + expect(doSpan?.parent_span_id).toBe(workerSpan?.span_id); |
64 | 38 | }); |
65 | 39 |
|
66 | 40 | it('propagates trace from queue handler to durable object over stub.fetch() when rpcTracePropagationBindings is empty', async ({ |
67 | 41 | signal, |
68 | 42 | }) => { |
69 | | - let queueTraceId: string | undefined; |
70 | | - let queueSpanId: string | undefined; |
71 | | - let doTraceId: string | undefined; |
72 | | - let doParentSpanId: string | undefined; |
| 43 | + let queueSpan: SerializedStreamedSpan | undefined; |
| 44 | + let doSpan: SerializedStreamedSpan | undefined; |
73 | 45 |
|
74 | 46 | const runner = createRunner(__dirname) |
75 | 47 | .expect(envelope => { |
76 | | - const transactionEvent = envelope[1]?.[0]?.[1] as Event; |
77 | | - |
78 | | - expect(transactionEvent).toEqual( |
79 | | - expect.objectContaining({ |
80 | | - contexts: expect.objectContaining({ |
81 | | - trace: expect.objectContaining({ |
82 | | - op: 'http.server', |
83 | | - data: expect.objectContaining({ |
84 | | - 'sentry.origin': 'auto.http.cloudflare', |
85 | | - }), |
86 | | - origin: 'auto.http.cloudflare', |
87 | | - }), |
88 | | - }), |
89 | | - transaction: 'GET /hello', |
90 | | - }), |
91 | | - ); |
92 | | - doTraceId = transactionEvent.contexts?.trace?.trace_id as string; |
93 | | - doParentSpanId = transactionEvent.contexts?.trace?.parent_span_id as string; |
| 48 | + const segmentSpan = getSpansFromEnvelope(envelope).find(span => span.is_segment); |
| 49 | + |
| 50 | + expect(getSpanOp(segmentSpan!)).toBe('http.server'); |
| 51 | + expect(segmentSpan?.attributes['sentry.origin']).toEqual({ type: 'string', value: 'auto.http.cloudflare' }); |
| 52 | + expect(segmentSpan?.attributes['url.path']).toEqual({ type: 'string', value: '/hello' }); |
| 53 | + doSpan = segmentSpan; |
94 | 54 | }) |
95 | 55 | .expect(envelope => { |
96 | | - const transactionEvent = envelope[1]?.[0]?.[1] as Event; |
97 | | - |
98 | | - expect(transactionEvent).toEqual( |
99 | | - expect.objectContaining({ |
100 | | - contexts: expect.objectContaining({ |
101 | | - trace: expect.objectContaining({ |
102 | | - op: 'queue.process', |
103 | | - data: expect.objectContaining({ |
104 | | - 'sentry.origin': 'auto.faas.cloudflare.queue', |
105 | | - }), |
106 | | - origin: 'auto.faas.cloudflare.queue', |
107 | | - }), |
108 | | - }), |
109 | | - transaction: 'process my-queue', |
110 | | - }), |
111 | | - ); |
112 | | - queueTraceId = transactionEvent.contexts?.trace?.trace_id as string; |
113 | | - queueSpanId = transactionEvent.contexts?.trace?.span_id as string; |
| 56 | + const segmentSpan = getSpansFromEnvelope(envelope).find(span => span.is_segment); |
| 57 | + |
| 58 | + expect(segmentSpan?.name).toBe('process my-queue'); |
| 59 | + expect(getSpanOp(segmentSpan!)).toBe('queue.process'); |
| 60 | + expect(segmentSpan?.attributes['sentry.origin']).toEqual({ |
| 61 | + type: 'string', |
| 62 | + value: 'auto.faas.cloudflare.queue', |
| 63 | + }); |
| 64 | + queueSpan = segmentSpan; |
114 | 65 | }) |
115 | | - // Also expect the fetch transaction from the /queue/send request |
| 66 | + // Also expect the fetch span from the /queue/send request |
116 | 67 | .expect(envelope => { |
117 | | - const transactionEvent = envelope[1]?.[0]?.[1] as Event; |
118 | | - |
119 | | - expect(transactionEvent).toEqual( |
120 | | - expect.objectContaining({ |
121 | | - contexts: expect.objectContaining({ |
122 | | - trace: expect.objectContaining({ |
123 | | - op: 'http.server', |
124 | | - data: expect.objectContaining({ |
125 | | - 'sentry.origin': 'auto.http.cloudflare', |
126 | | - }), |
127 | | - origin: 'auto.http.cloudflare', |
128 | | - }), |
129 | | - }), |
130 | | - transaction: 'GET /queue/send', |
131 | | - }), |
132 | | - ); |
| 68 | + const segmentSpan = getSpansFromEnvelope(envelope).find(span => span.is_segment); |
| 69 | + |
| 70 | + expect(getSpanOp(segmentSpan!)).toBe('http.server'); |
| 71 | + expect(segmentSpan?.attributes['sentry.origin']).toEqual({ type: 'string', value: 'auto.http.cloudflare' }); |
| 72 | + expect(segmentSpan?.attributes['url.path']).toEqual({ type: 'string', value: '/queue/send' }); |
133 | 73 | }) |
134 | 74 | .unordered() |
135 | 75 | .start(signal); |
136 | 76 | // The fetch handler sends a message to the queue, which triggers the queue consumer |
137 | 77 | await runner.makeRequest('get', '/queue/send'); |
138 | 78 | await runner.completed(); |
139 | 79 |
|
140 | | - expect(queueTraceId).toBeDefined(); |
141 | | - expect(doTraceId).toBe(queueTraceId); |
142 | | - |
143 | | - expect(queueSpanId).toBeDefined(); |
144 | | - expect(doParentSpanId).toBe(queueSpanId); |
| 80 | + expect(queueSpan?.trace_id).toBeDefined(); |
| 81 | + expect(doSpan?.trace_id).toBe(queueSpan?.trace_id); |
| 82 | + expect(doSpan?.parent_span_id).toBe(queueSpan?.span_id); |
145 | 83 | }); |
146 | 84 |
|
147 | 85 | it('propagates trace from scheduled handler to durable object over stub.fetch() when rpcTracePropagationBindings is empty', async ({ |
148 | 86 | signal, |
149 | 87 | }) => { |
150 | | - let scheduledTraceId: string | undefined; |
151 | | - let scheduledSpanId: string | undefined; |
152 | | - let doTraceId: string | undefined; |
153 | | - let doParentSpanId: string | undefined; |
| 88 | + let scheduledSpan: SerializedStreamedSpan | undefined; |
| 89 | + let doSpan: SerializedStreamedSpan | undefined; |
154 | 90 |
|
155 | 91 | const runner = createRunner(__dirname) |
156 | 92 | .withWranglerArgs('--test-scheduled') |
157 | 93 | .expect(envelope => { |
158 | | - const transactionEvent = envelope[1]?.[0]?.[1] as Event; |
159 | | - |
160 | | - expect(transactionEvent).toEqual( |
161 | | - expect.objectContaining({ |
162 | | - contexts: expect.objectContaining({ |
163 | | - trace: expect.objectContaining({ |
164 | | - op: 'http.server', |
165 | | - data: expect.objectContaining({ |
166 | | - 'sentry.origin': 'auto.http.cloudflare', |
167 | | - }), |
168 | | - origin: 'auto.http.cloudflare', |
169 | | - }), |
170 | | - }), |
171 | | - transaction: 'GET /hello', |
172 | | - }), |
173 | | - ); |
174 | | - doTraceId = transactionEvent.contexts?.trace?.trace_id as string; |
175 | | - doParentSpanId = transactionEvent.contexts?.trace?.parent_span_id as string; |
| 94 | + const segmentSpan = getSpansFromEnvelope(envelope).find(span => span.is_segment); |
| 95 | + |
| 96 | + expect(getSpanOp(segmentSpan!)).toBe('http.server'); |
| 97 | + expect(segmentSpan?.attributes['sentry.origin']).toEqual({ type: 'string', value: 'auto.http.cloudflare' }); |
| 98 | + expect(segmentSpan?.attributes['url.path']).toEqual({ type: 'string', value: '/hello' }); |
| 99 | + doSpan = segmentSpan; |
176 | 100 | }) |
177 | 101 | .expect(envelope => { |
178 | | - const transactionEvent = envelope[1]?.[0]?.[1] as Event; |
179 | | - |
180 | | - expect(transactionEvent).toEqual( |
181 | | - expect.objectContaining({ |
182 | | - contexts: expect.objectContaining({ |
183 | | - trace: expect.objectContaining({ |
184 | | - op: 'function', |
185 | | - data: expect.objectContaining({ |
186 | | - 'sentry.origin': 'auto.faas.cloudflare.scheduled', |
187 | | - }), |
188 | | - origin: 'auto.faas.cloudflare.scheduled', |
189 | | - }), |
190 | | - }), |
191 | | - }), |
192 | | - ); |
193 | | - scheduledTraceId = transactionEvent.contexts?.trace?.trace_id as string; |
194 | | - scheduledSpanId = transactionEvent.contexts?.trace?.span_id as string; |
| 102 | + const segmentSpan = getSpansFromEnvelope(envelope).find(span => span.is_segment); |
| 103 | + |
| 104 | + expect(getSpanOp(segmentSpan!)).toBe('function'); |
| 105 | + expect(segmentSpan?.attributes['sentry.origin']).toEqual({ |
| 106 | + type: 'string', |
| 107 | + value: 'auto.faas.cloudflare.scheduled', |
| 108 | + }); |
| 109 | + scheduledSpan = segmentSpan; |
195 | 110 | }) |
196 | 111 | .unordered() |
197 | 112 | .start(signal); |
198 | 113 | await runner.makeRequest('get', '/__scheduled?cron=*+*+*+*+*'); |
199 | 114 | await runner.completed(); |
200 | 115 |
|
201 | | - expect(scheduledTraceId).toBeDefined(); |
202 | | - expect(doTraceId).toBe(scheduledTraceId); |
203 | | - |
204 | | - expect(scheduledSpanId).toBeDefined(); |
205 | | - expect(doParentSpanId).toBe(scheduledSpanId); |
| 116 | + expect(scheduledSpan?.trace_id).toBeDefined(); |
| 117 | + expect(doSpan?.trace_id).toBe(scheduledSpan?.trace_id); |
| 118 | + expect(doSpan?.parent_span_id).toBe(scheduledSpan?.span_id); |
206 | 119 | }); |
0 commit comments