-
Notifications
You must be signed in to change notification settings - Fork 212
Expand file tree
/
Copy pathopentelemetry-b3-tracing.spec.js
More file actions
148 lines (121 loc) · 5.01 KB
/
opentelemetry-b3-tracing.spec.js
File metadata and controls
148 lines (121 loc) · 5.01 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
/*
* Copyright (c) 2025, Salesforce, Inc.
* All rights reserved.
* SPDX-License-Identifier: BSD-3-Clause
* For full license text, see the LICENSE file in the repo root or https://opensource.org/licenses/BSD-3-Clause
*/
const {test, expect} = require('@playwright/test')
const config = require('../config')
const {answerConsentTrackingForm} = require('../scripts/pageHelpers.js')
test.beforeEach(async ({page}) => {
// Enable request interception to capture headers
await page.route('**/*', async (route) => {
await route.continue()
})
})
test('should inject B3 headers when __server_timing param is passed', async ({page}) => {
const url = `${config.RETAIL_APP_HOME}?__server_timing=true`
const responseHeaders = []
page.on('response', (response) => {
if (response.url().includes(config.RETAIL_APP_HOME)) {
const headers = response.headers()
responseHeaders.push({
url: response.url(),
headers: headers
})
}
})
await page.goto(url)
await answerConsentTrackingForm(page)
expect(responseHeaders.length).toBeGreaterThan(0)
const mainResponse = responseHeaders.find(
(r) => r.url.includes(config.RETAIL_APP_HOME) && !r.url.includes('static')
)
if (mainResponse) {
expect(mainResponse.headers).toBeDefined()
expect(mainResponse.headers['x-b3-traceid']).toBeDefined()
expect(mainResponse.headers['x-b3-spanid']).toBeDefined()
expect(mainResponse.headers['x-b3-sampled']).toBe('1')
// Verify trace ID format (should be 16 or 32 character hex string)
const traceId = mainResponse.headers['x-b3-traceid']
expect(traceId).toMatch(/^[0-9a-f]{16}$|^[0-9a-f]{32}$/)
// Verify span ID format (should be 16 character hex string)
const spanId = mainResponse.headers['x-b3-spanid']
expect(spanId).toMatch(/^[0-9a-f]{16}$/)
}
})
test('should not show Server Timing header if __server_timing param is not passed', async ({
page
}) => {
const url = config.RETAIL_APP_HOME // No __server_timing param
const responseHeaders = []
page.on('response', (response) => {
if (response.url().includes(config.RETAIL_APP_HOME)) {
const headers = response.headers()
responseHeaders.push({
url: response.url(),
headers: headers
})
}
})
await page.goto(url)
await answerConsentTrackingForm(page)
expect(responseHeaders.length).toBeGreaterThan(0)
const mainResponse = responseHeaders.find(
(r) => r.url.includes(config.RETAIL_APP_HOME) && !r.url.includes('static')
)
expect(mainResponse).toBeDefined()
expect(mainResponse.headers['server-timing']).toBeUndefined()
})
test('should validate performance marks in Server-Timing header have numeric durations', async ({
page
}) => {
const url = `${config.RETAIL_APP_HOME}?__server_timing=true`
const responseHeaders = []
page.on('response', (response) => {
if (response.url().includes(config.RETAIL_APP_HOME)) {
const headers = response.headers()
responseHeaders.push({
url: response.url(),
headers: headers
})
}
})
await page.goto(url)
await answerConsentTrackingForm(page)
expect(responseHeaders.length).toBeGreaterThan(0)
const mainResponse = responseHeaders.find(
(r) => r.url.includes(config.RETAIL_APP_HOME) && !r.url.includes('static')
)
if (mainResponse && mainResponse.headers['server-timing']) {
const serverTiming = mainResponse.headers['server-timing']
// Parse timing entries and validate durations
const timingEntries = serverTiming.split(', ')
timingEntries.forEach((entry) => {
const match = entry.match(/^([^;]+);dur=(\d+\.\d+)$/)
expect(match).toBeTruthy()
const markName = match[1]
const duration = parseFloat(match[2])
// Duration should be a positive number
expect(duration).toBeGreaterThan(0)
expect(duration).toBeLessThan(10000) // Reasonable upper bound
// Should be one of the expected performance marks
// Handle various suffixes by extracting the base mark name
// Remove any suffix after the base mark name (e.g., .1, .useCategory-0, .useProductSearch-2)
const baseMarkName = markName
.replace(/\.(useCategory|useProductSearch|useQuery)-\d+$/, '')
.replace(/\.\d+$/, '')
const expectedMarks = [
'ssr.total',
'ssr.render-to-string',
'ssr.route-matching',
'ssr.load-component',
'ssr.fetch-strategies',
'ssr.fetch-strategies.react-query.pre-render',
'ssr.fetch-strategies.react-query.use-query',
'ssr.fetch-strategies.get-prop'
]
expect(expectedMarks).toContain(baseMarkName)
})
}
})