Skip to content
File

Blob: src/cloudflare/internal/test/tracing/tracing-helpers-instrumentation-test.js

javascript88 lines
1// Copyright (c) 2025 Cloudflare, Inc.
2// Licensed under the Apache 2.0 license found in the LICENSE file or at:
3// https://opensource.org/licenses/Apache-2.0
4 
5import assert from 'node:assert';
6import {
7 createTailStreamCollector,
8 groupSpansBy,
9} from 'instrumentation-test-helper';
10 
11// Create the collector and export it for the tail worker
12const collector = createTailStreamCollector();
13export default collector;
14 
15// After all tests complete, validate the spans
16export const validateSpans = {
17 async test() {
18 // Wait for all the tailStream executions to finish
19 await collector.waitForCompletion();
20 
21 // Get all spans and prepare for validation
22 const allSpans = collector.spans.values();
23 const spansByTest = groupSpansBy(allSpans, 'test');
24 
25 // Core tests that validate withSpan produces a correctly-closed span of the given name.
26 const testValidations = [
27 { test: 'syncFunction', expectedSpan: 'sync-op' },
28 { test: 'asyncFunction', expectedSpan: 'async-op' },
29 { test: 'syncError', expectedSpan: 'sync-error-op' },
30 { test: 'asyncError', expectedSpan: 'async-error-op' },
31 { test: 'spanClassName', expectedSpan: 'class-name-op' },
32 { test: 'isTraced', expectedSpan: 'is-traced-op' },
33 {
34 test: 'setAttributeUndefined',
35 expectedSpan: 'undefined-attr-op',
36 },
37 { test: 'publicImportTracing', expectedSpan: 'public-import-op' },
38 { test: 'ctxTracing', expectedSpan: 'ctx-tracing-op' },
39 ];
40 
41 for (const { test, expectedSpan } of testValidations) {
42 const testSpans = spansByTest.get(test) || [];
43 const span = testSpans.find((s) => s.name === expectedSpan);
44 
45 assert(span, `${test}: Should have created span '${expectedSpan}'`);
46 assert(span.closed, `${test}: Span '${expectedSpan}' should be closed`);
47 }
48 
49 // setAttributeUndefined should NOT have a 'skipped' attribute recorded.
50 {
51 const span = (spansByTest.get('setAttributeUndefined') || []).find(
52 (s) => s.name === 'undefined-attr-op'
53 );
54 assert(span, 'setAttributeUndefined: span present');
55 assert(
56 !('skipped' in span),
57 'setAttribute(key, undefined) should not record the attribute'
58 );
59 }
60 
61 // Nested spans: verify both outer and inner spans exist and both are closed.
62 // This exercises the AsyncContextFrame push path used by enterSpan for nesting.
63 for (const testName of ['nestedSyncSpans', 'nestedAsyncSpans']) {
64 const testSpans = spansByTest.get(testName) || [];
65 const outerName =
66 testName === 'nestedSyncSpans'
67 ? 'nested-outer-op'
68 : 'nested-async-outer-op';
69 const innerName =
70 testName === 'nestedSyncSpans'
71 ? 'nested-inner-op'
72 : 'nested-async-inner-op';
73 
74 const outer = testSpans.find((s) => s.name === outerName);
75 const inner = testSpans.find((s) => s.name === innerName);
76 
77 assert(outer, `${testName}: outer span '${outerName}' should exist`);
78 assert(inner, `${testName}: inner span '${innerName}' should exist`);
79 assert(outer.closed, `${testName}: outer span should be closed`);
80 assert(inner.closed, `${testName}: inner span should be closed`);
81 assert.strictEqual(outer.level, 'outer');
82 assert.strictEqual(inner.level, 'inner');
83 }
84 
85 console.log('All tracing-helpers tests passed!');
86 },
87};