@stainlessdev/xray-emitter 0.1.0-branch.pedro-unify.20f830a

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (78) hide show
  1. package/README.md +79 -0
  2. package/dist/chunk-2NR6RZEP.js +1339 -0
  3. package/dist/chunk-2NR6RZEP.js.map +1 -0
  4. package/dist/chunk-3MVVO5I7.cjs +1339 -0
  5. package/dist/chunk-3MVVO5I7.cjs.map +1 -0
  6. package/dist/chunk-6UH43LVD.js +281 -0
  7. package/dist/chunk-6UH43LVD.js.map +1 -0
  8. package/dist/chunk-AHXNYJ5A.cjs +621 -0
  9. package/dist/chunk-AHXNYJ5A.cjs.map +1 -0
  10. package/dist/chunk-GNSXLLEC.cjs +281 -0
  11. package/dist/chunk-GNSXLLEC.cjs.map +1 -0
  12. package/dist/chunk-JKW6E4L3.cjs +304 -0
  13. package/dist/chunk-JKW6E4L3.cjs.map +1 -0
  14. package/dist/chunk-MPQTI5AX.js +621 -0
  15. package/dist/chunk-MPQTI5AX.js.map +1 -0
  16. package/dist/chunk-QUH3LJ5M.cjs +634 -0
  17. package/dist/chunk-QUH3LJ5M.cjs.map +1 -0
  18. package/dist/chunk-VGRLHYDA.js +634 -0
  19. package/dist/chunk-VGRLHYDA.js.map +1 -0
  20. package/dist/chunk-YVMMCTXW.js +304 -0
  21. package/dist/chunk-YVMMCTXW.js.map +1 -0
  22. package/dist/express.cjs +45 -0
  23. package/dist/express.cjs.map +1 -0
  24. package/dist/express.d.cts +17 -0
  25. package/dist/express.d.ts +17 -0
  26. package/dist/express.js +45 -0
  27. package/dist/express.js.map +1 -0
  28. package/dist/fastify.cjs +64 -0
  29. package/dist/fastify.cjs.map +1 -0
  30. package/dist/fastify.d.cts +21 -0
  31. package/dist/fastify.d.ts +21 -0
  32. package/dist/fastify.js +64 -0
  33. package/dist/fastify.js.map +1 -0
  34. package/dist/fetch.cjs +16 -0
  35. package/dist/fetch.cjs.map +1 -0
  36. package/dist/fetch.d.cts +19 -0
  37. package/dist/fetch.d.ts +19 -0
  38. package/dist/fetch.js +16 -0
  39. package/dist/fetch.js.map +1 -0
  40. package/dist/hono.cjs +71 -0
  41. package/dist/hono.cjs.map +1 -0
  42. package/dist/hono.d.cts +30 -0
  43. package/dist/hono.d.ts +30 -0
  44. package/dist/hono.js +71 -0
  45. package/dist/hono.js.map +1 -0
  46. package/dist/index.cjs +12 -0
  47. package/dist/index.cjs.map +1 -0
  48. package/dist/index.d.cts +7 -0
  49. package/dist/index.d.ts +7 -0
  50. package/dist/index.js +12 -0
  51. package/dist/index.js.map +1 -0
  52. package/dist/internal.cjs +45 -0
  53. package/dist/internal.cjs.map +1 -0
  54. package/dist/internal.d.cts +53 -0
  55. package/dist/internal.d.ts +53 -0
  56. package/dist/internal.js +45 -0
  57. package/dist/internal.js.map +1 -0
  58. package/dist/next.cjs +30 -0
  59. package/dist/next.cjs.map +1 -0
  60. package/dist/next.d.cts +18 -0
  61. package/dist/next.d.ts +18 -0
  62. package/dist/next.js +30 -0
  63. package/dist/next.js.map +1 -0
  64. package/dist/node.cjs +14 -0
  65. package/dist/node.cjs.map +1 -0
  66. package/dist/node.d.cts +20 -0
  67. package/dist/node.d.ts +20 -0
  68. package/dist/node.js +14 -0
  69. package/dist/node.js.map +1 -0
  70. package/dist/remix.cjs +30 -0
  71. package/dist/remix.cjs.map +1 -0
  72. package/dist/remix.d.cts +15 -0
  73. package/dist/remix.d.ts +15 -0
  74. package/dist/remix.js +30 -0
  75. package/dist/remix.js.map +1 -0
  76. package/dist/types-Z1nirh-F.d.cts +149 -0
  77. package/dist/types-Z1nirh-F.d.ts +149 -0
  78. package/package.json +94 -0
@@ -0,0 +1,1339 @@
1
+ "use strict";Object.defineProperty(exports, "__esModule", {value: true}); function _nullishCoalesce(lhs, rhsFn) { if (lhs != null) { return lhs; } else { return rhsFn(); } } function _optionalChain(ops) { let lastAccessLHS = undefined; let value = ops[0]; let i = 1; while (i < ops.length) { const op = ops[i]; const fn = ops[i + 1]; i += 2; if ((op === 'optionalAccess' || op === 'optionalCall') && value == null) { return undefined; } if (op === 'access' || op === 'optionalAccess') { lastAccessLHS = value; value = fn(value); } else if (op === 'call' || op === 'optionalCall') { value = fn((...args) => value.call(lastAccessLHS, ...args)); lastAccessLHS = undefined; } } return value; }
2
+
3
+
4
+
5
+
6
+
7
+
8
+
9
+ var _chunkJKW6E4L3cjs = require('./chunk-JKW6E4L3.cjs');
10
+
11
+ // src/core/route.ts
12
+ function normalizeRoutePattern(route) {
13
+ if (!route) {
14
+ return "/";
15
+ }
16
+ const cleaned = stripQueryAndFragment(route).trim();
17
+ if (!cleaned) {
18
+ return "/";
19
+ }
20
+ const withoutMethod = stripMethodPrefix(cleaned);
21
+ const leading = withoutMethod.startsWith("/") ? withoutMethod : `/${withoutMethod}`;
22
+ const segments = leading.split("/").filter(Boolean);
23
+ if (segments.length === 0) {
24
+ return "/";
25
+ }
26
+ const normalized = segments.map(normalizeRouteSegment).join("/");
27
+ return `/${normalized}`;
28
+ }
29
+ function stripMethodPrefix(value) {
30
+ if (!/^[A-Z]+\s+\//.test(value)) {
31
+ return value;
32
+ }
33
+ const spaceIndex = value.search(/\s+/);
34
+ if (spaceIndex < 0) {
35
+ return value;
36
+ }
37
+ return value.slice(spaceIndex).trim();
38
+ }
39
+ function stripQueryAndFragment(value) {
40
+ const hashIndex = value.indexOf("#");
41
+ const beforeHash = hashIndex >= 0 ? value.slice(0, hashIndex) : value;
42
+ const queryIndex = beforeHash.indexOf("?");
43
+ return queryIndex >= 0 ? beforeHash.slice(0, queryIndex) : beforeHash;
44
+ }
45
+ function normalizeRouteSegment(segment) {
46
+ if (segment === "*") {
47
+ return "{wildcard}";
48
+ }
49
+ const param = extractRouteParam(segment);
50
+ if (param) {
51
+ return `{${param}}`;
52
+ }
53
+ return segment;
54
+ }
55
+ function extractRouteParam(segment) {
56
+ if (!segment) {
57
+ return null;
58
+ }
59
+ if (segment.startsWith("[") && segment.endsWith("]")) {
60
+ return normalizeNextParam(segment);
61
+ }
62
+ if (segment.startsWith("{") && segment.endsWith("}")) {
63
+ const inner = segment.slice(1, -1);
64
+ const trimmed = stripParamDecorators(inner);
65
+ return extractParamName(trimmed);
66
+ }
67
+ if (segment.startsWith(":") || segment.startsWith("$")) {
68
+ return extractParamName(segment.slice(1));
69
+ }
70
+ return null;
71
+ }
72
+ function normalizeNextParam(segment) {
73
+ let inner = segment.slice(1, -1);
74
+ if (inner.startsWith("[") && inner.endsWith("]")) {
75
+ inner = inner.slice(1, -1);
76
+ }
77
+ if (inner.startsWith("...")) {
78
+ inner = inner.slice(3);
79
+ }
80
+ return extractParamName(inner);
81
+ }
82
+ function stripParamDecorators(value) {
83
+ let trimmed = value.trim();
84
+ if (!trimmed) {
85
+ return trimmed;
86
+ }
87
+ if (trimmed.endsWith("...")) {
88
+ trimmed = trimmed.slice(0, -3);
89
+ }
90
+ return trimmed.replace(/[?*+]+$/, "");
91
+ }
92
+ function extractParamName(value) {
93
+ if (!value) {
94
+ return null;
95
+ }
96
+ const match = value.match(/^[A-Za-z0-9_-]+/);
97
+ return _nullishCoalesce(_optionalChain([match, 'optionalAccess', _ => _[0]]), () => ( null));
98
+ }
99
+
100
+ // src/core/config.ts
101
+ var defaultCapture = {
102
+ requestHeaders: true,
103
+ responseHeaders: true,
104
+ requestBody: "text",
105
+ responseBody: "text",
106
+ maxBodyBytes: 65536
107
+ };
108
+ var defaultRedaction = {
109
+ headers: ["authorization", "cookie", "set-cookie", "x-api-key"],
110
+ queryParams: [],
111
+ bodyJsonPaths: [],
112
+ replacement: "[REDACTED]"
113
+ };
114
+ var defaultRequestId = {
115
+ header: "request-id"
116
+ };
117
+ var defaultRoute = {
118
+ normalize: true,
119
+ normalizer: normalizeRoutePattern
120
+ };
121
+ var defaultExporterBase = {
122
+ headers: {},
123
+ timeoutMs: 3e4,
124
+ spanProcessor: "batch"
125
+ };
126
+ var XrayConfigError = class extends Error {
127
+ constructor(code, message) {
128
+ super(message);
129
+ this.code = code;
130
+ }
131
+ };
132
+ function normalizeConfig(config) {
133
+ if (!config || !config.serviceName || !config.serviceName.trim()) {
134
+ throw new XrayConfigError("INVALID_CONFIG", "serviceName is required");
135
+ }
136
+ const logger = _nullishCoalesce(config.logger, () => ( console));
137
+ const logLevel = _nullishCoalesce(config.logLevel, () => ( "warn"));
138
+ const capture = normalizeCapture(config.capture);
139
+ const redaction = normalizeRedaction(config.redaction);
140
+ const requestId = normalizeRequestId(config.requestId);
141
+ const route = normalizeRoute(config.route);
142
+ const exporter = normalizeExporter(config.endpointUrl, config.exporter);
143
+ return {
144
+ serviceName: config.serviceName.trim(),
145
+ environment: _optionalChain([config, 'access', _2 => _2.environment, 'optionalAccess', _3 => _3.trim, 'call', _4 => _4()]) || void 0,
146
+ version: _optionalChain([config, 'access', _5 => _5.version, 'optionalAccess', _6 => _6.trim, 'call', _7 => _7()]) || void 0,
147
+ logger,
148
+ logLevel,
149
+ exporter,
150
+ capture,
151
+ redaction,
152
+ requestId,
153
+ route
154
+ };
155
+ }
156
+ function normalizeCapture(cfg) {
157
+ const capture = {
158
+ ...defaultCapture,
159
+ ...cfg
160
+ };
161
+ if (!["none", "text", "base64"].includes(capture.requestBody)) {
162
+ throw new XrayConfigError(
163
+ "INVALID_CONFIG",
164
+ "capture.requestBody must be none, text, or base64"
165
+ );
166
+ }
167
+ if (!["none", "text", "base64"].includes(capture.responseBody)) {
168
+ throw new XrayConfigError(
169
+ "INVALID_CONFIG",
170
+ "capture.responseBody must be none, text, or base64"
171
+ );
172
+ }
173
+ if (!Number.isFinite(capture.maxBodyBytes) || capture.maxBodyBytes < 0) {
174
+ throw new XrayConfigError("INVALID_CONFIG", "capture.maxBodyBytes must be >= 0");
175
+ }
176
+ return capture;
177
+ }
178
+ function normalizeRedaction(cfg) {
179
+ const redaction = {
180
+ ...defaultRedaction,
181
+ ...cfg
182
+ };
183
+ redaction.headers = normalizeStringList(redaction.headers);
184
+ redaction.queryParams = normalizeStringList(redaction.queryParams);
185
+ redaction.bodyJsonPaths = normalizeStringList(redaction.bodyJsonPaths);
186
+ redaction.replacement = redaction.replacement || defaultRedaction.replacement;
187
+ if (!redaction.replacement) {
188
+ throw new XrayConfigError("INVALID_REDACTION", "redaction.replacement must be non-empty");
189
+ }
190
+ return redaction;
191
+ }
192
+ function normalizeRequestId(cfg) {
193
+ const requestId = {
194
+ ...defaultRequestId,
195
+ ...cfg
196
+ };
197
+ requestId.header = requestId.header.trim().toLowerCase();
198
+ if (!requestId.header) {
199
+ throw new XrayConfigError("INVALID_CONFIG", "requestId.header must be non-empty");
200
+ }
201
+ return requestId;
202
+ }
203
+ function normalizeRoute(cfg) {
204
+ const route = {
205
+ ...defaultRoute,
206
+ ...cfg
207
+ };
208
+ if (route.normalize && !route.normalizer) {
209
+ route.normalizer = normalizeRoutePattern;
210
+ }
211
+ return route;
212
+ }
213
+ function normalizeExporter(endpointUrl, cfg) {
214
+ const resolvedEndpoint = normalizeExporterEndpoint(_nullishCoalesce(_optionalChain([cfg, 'optionalAccess', _8 => _8.endpointUrl]), () => ( endpointUrl)));
215
+ const rawHeaders = _nullishCoalesce(_nullishCoalesce(_optionalChain([cfg, 'optionalAccess', _9 => _9.headers]), () => ( defaultExporterBase.headers)), () => ( {}));
216
+ const parsed = applyEndpointAuth(resolvedEndpoint, rawHeaders);
217
+ const exporter = {
218
+ endpointUrl: parsed.endpointUrl,
219
+ headers: parsed.headers,
220
+ timeoutMs: _nullishCoalesce(_optionalChain([cfg, 'optionalAccess', _10 => _10.timeoutMs]), () => ( defaultExporterBase.timeoutMs)),
221
+ spanProcessor: _nullishCoalesce(_optionalChain([cfg, 'optionalAccess', _11 => _11.spanProcessor]), () => ( defaultExporterBase.spanProcessor))
222
+ };
223
+ return exporter;
224
+ }
225
+ function normalizeExporterEndpoint(endpointUrl) {
226
+ const envUrl = typeof process !== "undefined" ? _optionalChain([process, 'access', _12 => _12.env, 'optionalAccess', _13 => _13["STAINLESS_XRAY_ENDPOINT_URL"]]) : void 0;
227
+ const resolved = _nullishCoalesce(endpointUrl, () => ( envUrl));
228
+ if (!resolved || !resolved.trim()) {
229
+ throw new XrayConfigError(
230
+ "INVALID_CONFIG",
231
+ "endpointUrl is required (set endpointUrl or STAINLESS_XRAY_ENDPOINT_URL)"
232
+ );
233
+ }
234
+ const trimmed = resolved.trim();
235
+ const withoutTrailingSlash = trimmed.endsWith("/") ? trimmed.slice(0, -1) : trimmed;
236
+ if (withoutTrailingSlash.endsWith("/v1/traces")) {
237
+ return withoutTrailingSlash;
238
+ }
239
+ return `${withoutTrailingSlash}/v1/traces`;
240
+ }
241
+ function normalizeStringList(values) {
242
+ if (!values) {
243
+ return [];
244
+ }
245
+ return values.map((entry) => entry.trim()).filter(Boolean);
246
+ }
247
+ var textEncoder = typeof TextEncoder !== "undefined" ? new TextEncoder() : null;
248
+ var maybeBuffer = globalThis.Buffer;
249
+ function applyEndpointAuth(endpointUrl, headers) {
250
+ const resolvedHeaders = _nullishCoalesce(headers, () => ( {}));
251
+ let url;
252
+ try {
253
+ url = new URL(endpointUrl);
254
+ } catch (e) {
255
+ return { endpointUrl, headers: resolvedHeaders };
256
+ }
257
+ const username = decodeUserInfo(url.username);
258
+ const password = decodeUserInfo(url.password);
259
+ if (!username && !password) {
260
+ return { endpointUrl, headers: resolvedHeaders };
261
+ }
262
+ url.username = "";
263
+ url.password = "";
264
+ const sanitizedUrl = url.toString();
265
+ if (hasAuthorizationHeader(resolvedHeaders)) {
266
+ return { endpointUrl: sanitizedUrl, headers: resolvedHeaders };
267
+ }
268
+ const authorization = encodeBasicAuth(username, password);
269
+ if (!authorization) {
270
+ return { endpointUrl: sanitizedUrl, headers: resolvedHeaders };
271
+ }
272
+ return {
273
+ endpointUrl: sanitizedUrl,
274
+ headers: {
275
+ ...resolvedHeaders,
276
+ Authorization: authorization
277
+ }
278
+ };
279
+ }
280
+ function decodeUserInfo(value) {
281
+ if (!value) {
282
+ return value;
283
+ }
284
+ try {
285
+ return decodeURIComponent(value);
286
+ } catch (e2) {
287
+ return value;
288
+ }
289
+ }
290
+ function hasAuthorizationHeader(headers) {
291
+ return Object.keys(headers).some((key) => key.toLowerCase() === "authorization");
292
+ }
293
+ function encodeBasicAuth(username, password) {
294
+ const raw = `${username}:${password}`;
295
+ let bytes;
296
+ if (textEncoder) {
297
+ bytes = textEncoder.encode(raw);
298
+ } else if (maybeBuffer) {
299
+ bytes = maybeBuffer.from(raw, "utf8");
300
+ }
301
+ if (!bytes) {
302
+ return void 0;
303
+ }
304
+ const encoded = _chunkJKW6E4L3cjs.encodeBase64.call(void 0, bytes);
305
+ if (!encoded) {
306
+ return void 0;
307
+ }
308
+ return `Basic ${encoded}`;
309
+ }
310
+
311
+ // src/core/header_redaction.ts
312
+ var headerNameCompactor = /[-_.]/g;
313
+ var defaultHeaderMatcher = newHeaderRedactionMatcher(
314
+ defaultSensitiveHeaderNames(),
315
+ defaultSensitiveKeywords()
316
+ );
317
+ function authSchemePrefix(value) {
318
+ if (!value) {
319
+ return "";
320
+ }
321
+ const lower = value.toLowerCase();
322
+ if (lower.startsWith("basic")) {
323
+ return value.slice(0, "basic".length);
324
+ }
325
+ if (lower.startsWith("bearer")) {
326
+ return value.slice(0, "bearer".length);
327
+ }
328
+ if (lower.startsWith("digest")) {
329
+ return value.slice(0, "digest".length);
330
+ }
331
+ if (lower.startsWith("negotiate")) {
332
+ return value.slice(0, "negotiate".length);
333
+ }
334
+ return "";
335
+ }
336
+ function redactCookieValue(value, replacement) {
337
+ if (!value) {
338
+ return replacement;
339
+ }
340
+ const parts = value.split(";");
341
+ const redacted = [];
342
+ for (const part of parts) {
343
+ const segment = part.trim();
344
+ if (!segment) {
345
+ redacted.push(replacement);
346
+ continue;
347
+ }
348
+ const idx = segment.indexOf("=");
349
+ if (idx <= 0) {
350
+ redacted.push(replacement);
351
+ continue;
352
+ }
353
+ const name = segment.slice(0, idx);
354
+ if (!name) {
355
+ redacted.push(replacement);
356
+ continue;
357
+ }
358
+ redacted.push(`${name}=${replacement}`);
359
+ }
360
+ return redacted.join("; ");
361
+ }
362
+ function redactSetCookieValue(value, replacement) {
363
+ if (!value) {
364
+ return replacement;
365
+ }
366
+ const parts = value.split(";");
367
+ const first = _nullishCoalesce(parts.shift(), () => ( ""));
368
+ const idx = first.indexOf("=");
369
+ if (idx <= 0) {
370
+ return replacement;
371
+ }
372
+ const name = first.slice(0, idx);
373
+ if (!name) {
374
+ return replacement;
375
+ }
376
+ const redacted = `${name}=${replacement}`;
377
+ if (parts.length === 0) {
378
+ return redacted;
379
+ }
380
+ return `${redacted};${parts.join(";")}`;
381
+ }
382
+ function addSensitiveHeaderNames(target, headers) {
383
+ for (const header of headers) {
384
+ const normalized = normalizeHeaderName(header);
385
+ if (normalized) {
386
+ target.add(normalized);
387
+ }
388
+ }
389
+ }
390
+ function buildKeywordSets(keywords) {
391
+ const tokens = /* @__PURE__ */ new Set();
392
+ const compacted = /* @__PURE__ */ new Set();
393
+ for (const keyword of keywords) {
394
+ const normalized = normalizeHeaderName(keyword);
395
+ if (!normalized) {
396
+ continue;
397
+ }
398
+ const compactedKeyword = compactNormalizedHeaderName(normalized);
399
+ if (compactedKeyword) {
400
+ compacted.add(compactedKeyword);
401
+ }
402
+ if (!normalized.includes("-") && !normalized.includes("_") && !normalized.includes(".")) {
403
+ tokens.add(normalized);
404
+ }
405
+ }
406
+ return {
407
+ compacted: Array.from(compacted).sort(),
408
+ tokens
409
+ };
410
+ }
411
+ function compactNormalizedHeaderName(normalized) {
412
+ if (!normalized) {
413
+ return "";
414
+ }
415
+ return normalized.replace(headerNameCompactor, "");
416
+ }
417
+ function defaultSensitiveHeaderNames() {
418
+ return [
419
+ "authorization",
420
+ "cookie",
421
+ "proxy-authenticate",
422
+ "proxy-authorization",
423
+ "set-cookie",
424
+ "www-authenticate"
425
+ ];
426
+ }
427
+ function defaultSensitiveKeywords() {
428
+ return [
429
+ "api-key",
430
+ "api_key",
431
+ "apikey",
432
+ "auth",
433
+ "authenticate",
434
+ "authorization",
435
+ "credential",
436
+ "password",
437
+ "passwd",
438
+ "private-key",
439
+ "private_key",
440
+ "privatekey",
441
+ "secret",
442
+ "session",
443
+ "sessionid",
444
+ "signature",
445
+ "token"
446
+ ];
447
+ }
448
+ function newHeaderRedactionMatcher(names, keywords) {
449
+ const exactSensitive = /* @__PURE__ */ new Set();
450
+ addSensitiveHeaderNames(exactSensitive, names);
451
+ const { compacted, tokens } = buildKeywordSets(keywords);
452
+ return {
453
+ exactSensitive,
454
+ keywordCompacted: compacted,
455
+ keywordTokens: tokens
456
+ };
457
+ }
458
+ function normalizeHeaderName(name) {
459
+ return name.trim().toLowerCase();
460
+ }
461
+
462
+ // src/core/redaction.ts
463
+ function applyRedaction(config, log) {
464
+ const redacted = { ...log };
465
+ if (redacted.requestHeaders) {
466
+ redacted.requestHeaders = redactHeaders(redacted.requestHeaders, config);
467
+ }
468
+ if (redacted.responseHeaders) {
469
+ redacted.responseHeaders = redactHeaders(redacted.responseHeaders, config);
470
+ }
471
+ redacted.url = redactUrl(redacted.url, config);
472
+ if (redacted.requestBody) {
473
+ redacted.requestBody = redactBody(redacted.requestBody, redacted.requestHeaders, config);
474
+ }
475
+ if (redacted.responseBody) {
476
+ redacted.responseBody = redactBody(redacted.responseBody, redacted.responseHeaders, config);
477
+ }
478
+ return redacted;
479
+ }
480
+ function redactHeaders(headers, config) {
481
+ const list = new Set(config.headers.map((name) => name.toLowerCase()));
482
+ const result = {};
483
+ for (const [name, value] of Object.entries(headers)) {
484
+ const lower = name.toLowerCase();
485
+ if (!list.has(lower)) {
486
+ result[name] = value;
487
+ continue;
488
+ }
489
+ const redactValue = (entry) => redactHeaderValue(lower, entry, config.replacement);
490
+ if (Array.isArray(value)) {
491
+ result[name] = value.map(redactValue);
492
+ } else {
493
+ result[name] = redactValue(value);
494
+ }
495
+ }
496
+ return result;
497
+ }
498
+ function redactHeaderValue(name, value, replacement) {
499
+ switch (name) {
500
+ case "authorization":
501
+ case "proxy-authorization": {
502
+ const scheme = authSchemePrefix(value);
503
+ if (!scheme) {
504
+ return replacement;
505
+ }
506
+ return `${scheme} ${replacement}`;
507
+ }
508
+ case "cookie":
509
+ return redactCookieValue(value, replacement);
510
+ case "set-cookie":
511
+ return redactSetCookieValue(value, replacement);
512
+ default:
513
+ return replacement;
514
+ }
515
+ }
516
+ function redactUrl(value, config) {
517
+ if (!value || config.queryParams.length === 0) {
518
+ return value;
519
+ }
520
+ try {
521
+ const parsed = new URL(value);
522
+ const params = parsed.searchParams;
523
+ if (!params || params.size === 0) {
524
+ return value;
525
+ }
526
+ const redact = new Set(config.queryParams.map((key) => key.toLowerCase()));
527
+ const next = new URLSearchParams();
528
+ params.forEach((val, key) => {
529
+ if (redact.has(key.toLowerCase())) {
530
+ next.append(key, config.replacement);
531
+ } else {
532
+ next.append(key, val);
533
+ }
534
+ });
535
+ parsed.search = next.toString();
536
+ return parsed.toString();
537
+ } catch (e3) {
538
+ return value;
539
+ }
540
+ }
541
+ function redactBody(body, headers, config) {
542
+ if (config.bodyJsonPaths.length === 0) {
543
+ return body;
544
+ }
545
+ if (!body.value || body.encoding !== "utf8") {
546
+ return body;
547
+ }
548
+ if (!isJsonContentType(headers)) {
549
+ return body;
550
+ }
551
+ let parsed;
552
+ try {
553
+ parsed = JSON.parse(body.value);
554
+ } catch (e4) {
555
+ return body;
556
+ }
557
+ for (const path of config.bodyJsonPaths) {
558
+ const segments = parseJsonPath(path);
559
+ if (!segments) {
560
+ continue;
561
+ }
562
+ redactJsonPath(parsed, segments, config.replacement);
563
+ }
564
+ const next = { ...body };
565
+ next.value = JSON.stringify(parsed);
566
+ return next;
567
+ }
568
+ function isJsonContentType(headers) {
569
+ if (!headers) {
570
+ return false;
571
+ }
572
+ const contentType = headers["content-type"] || headers["Content-Type"];
573
+ const value = Array.isArray(contentType) ? contentType[0] : contentType;
574
+ if (!value) {
575
+ return false;
576
+ }
577
+ const normalized = value.split(";")[0];
578
+ if (!normalized) {
579
+ return false;
580
+ }
581
+ const trimmed = normalized.trim().toLowerCase();
582
+ return trimmed === "application/json" || trimmed.endsWith("+json");
583
+ }
584
+ function parseJsonPath(path) {
585
+ const trimmed = path.trim();
586
+ if (!trimmed) {
587
+ return null;
588
+ }
589
+ const normalized = trimmed.startsWith("$.") ? trimmed.slice(2) : trimmed;
590
+ if (!normalized) {
591
+ return null;
592
+ }
593
+ const segments = [];
594
+ const parts = normalized.split(".");
595
+ for (const part of parts) {
596
+ if (!part) {
597
+ continue;
598
+ }
599
+ let cursor = part;
600
+ const bracketIndex = cursor.indexOf("[");
601
+ if (bracketIndex === -1) {
602
+ segments.push(cursor);
603
+ continue;
604
+ }
605
+ const name = cursor.slice(0, bracketIndex);
606
+ if (name) {
607
+ segments.push(name);
608
+ }
609
+ cursor = cursor.slice(bracketIndex);
610
+ const matches = cursor.match(/\[(\d+)\]/g);
611
+ if (!matches) {
612
+ continue;
613
+ }
614
+ for (const match of matches) {
615
+ const indexValue = match.slice(1, -1);
616
+ const index = Number.parseInt(indexValue, 10);
617
+ if (Number.isFinite(index)) {
618
+ segments.push(index);
619
+ }
620
+ }
621
+ }
622
+ return segments.length > 0 ? segments : null;
623
+ }
624
+ function redactJsonPath(value, segments, replacement) {
625
+ if (!value || segments.length === 0) {
626
+ return;
627
+ }
628
+ let current = value;
629
+ for (let i = 0; i < segments.length; i += 1) {
630
+ const segment = segments[i];
631
+ if (segment === void 0) {
632
+ return;
633
+ }
634
+ const isLast = i === segments.length - 1;
635
+ if (typeof segment === "number") {
636
+ if (!Array.isArray(current) || segment < 0 || segment >= current.length) {
637
+ return;
638
+ }
639
+ if (isLast) {
640
+ current[segment] = replacement;
641
+ return;
642
+ }
643
+ current = current[segment];
644
+ continue;
645
+ }
646
+ if (!current || typeof current !== "object") {
647
+ return;
648
+ }
649
+ const record = current;
650
+ if (!(segment in record)) {
651
+ return;
652
+ }
653
+ if (isLast) {
654
+ record[segment] = replacement;
655
+ return;
656
+ }
657
+ current = record[segment];
658
+ }
659
+ }
660
+
661
+ // src/core/attributes.ts
662
+
663
+
664
+
665
+
666
+
667
+
668
+
669
+
670
+
671
+
672
+ var _incubating = require('@opentelemetry/semantic-conventions/incubating');
673
+
674
+ // src/core/attrkey.ts
675
+ var AttributeKeyRequestBody = "http.request.body";
676
+ var AttributeKeyRequestBodyEncoding = "http.request.body.encoding";
677
+ var AttributeKeyRequestBodyTruncated = "http.request.body.truncated";
678
+ var AttributeKeyRequestID = "http.request.id";
679
+ var AttributeKeyResponseBody = "http.response.body";
680
+ var AttributeKeyResponseBodyEncoding = "http.response.body.encoding";
681
+ var AttributeKeyResponseBodyTruncated = "http.response.body.truncated";
682
+ var AttributeKeySpanDrop = "stainlessxray.internal.drop";
683
+
684
+ // src/core/attributes.ts
685
+ function setHeaderAttributes(span, headers, prefix) {
686
+ if (!headers) {
687
+ return;
688
+ }
689
+ const keys = Object.keys(headers).sort((a, b) => a.toLowerCase().localeCompare(b.toLowerCase()));
690
+ for (const key of keys) {
691
+ const values = headers[key];
692
+ if (!values || Array.isArray(values) && values.length === 0) {
693
+ continue;
694
+ }
695
+ span.setAttribute(prefix + key.toLowerCase(), Array.isArray(values) ? values : [values]);
696
+ }
697
+ }
698
+ function setRequestAttributes(span, request, urlFull) {
699
+ span.setAttribute(_incubating.ATTR_HTTP_REQUEST_METHOD, request.method);
700
+ const effectiveUrl = _nullishCoalesce(urlFull, () => ( request.url));
701
+ if (effectiveUrl) {
702
+ span.setAttribute(_incubating.ATTR_URL_FULL, effectiveUrl);
703
+ const path = extractPath(effectiveUrl);
704
+ if (path) {
705
+ span.setAttribute(_incubating.ATTR_URL_PATH, path);
706
+ }
707
+ }
708
+ const clientAddress = clientAddressForRequest(
709
+ request.headers,
710
+ request.remoteAddress,
711
+ request.redactionReplacement
712
+ );
713
+ if (clientAddress) {
714
+ span.setAttribute(_incubating.ATTR_CLIENT_ADDRESS, clientAddress);
715
+ }
716
+ }
717
+ function extractPath(url) {
718
+ try {
719
+ return new URL(url).pathname;
720
+ } catch (e5) {
721
+ const match = url.match(/^[^?#]*/);
722
+ return _optionalChain([match, 'optionalAccess', _14 => _14[0]]) || void 0;
723
+ }
724
+ }
725
+ function clientAddressForRequest(headers, remoteAddress, redactionReplacement) {
726
+ const forwarded = forwardedClientAddress(
727
+ headerValues(headers, "forwarded"),
728
+ redactionReplacement
729
+ );
730
+ if (forwarded) {
731
+ return forwarded;
732
+ }
733
+ const xForwarded = xForwardedForClientAddress(
734
+ headerValues(headers, "x-forwarded-for"),
735
+ redactionReplacement
736
+ );
737
+ if (xForwarded) {
738
+ return xForwarded;
739
+ }
740
+ const xRealIp = xRealIpClientAddress(headerValues(headers, "x-real-ip"), redactionReplacement);
741
+ if (xRealIp) {
742
+ return xRealIp;
743
+ }
744
+ if (!remoteAddress) {
745
+ return void 0;
746
+ }
747
+ return remoteAddrHost(remoteAddress);
748
+ }
749
+ function forwardedClientAddress(values, redactionReplacement) {
750
+ for (const value of values) {
751
+ if (!value) {
752
+ continue;
753
+ }
754
+ const entries = value.split(",");
755
+ for (const entry of entries) {
756
+ const params = entry.split(";");
757
+ for (const param of params) {
758
+ const [rawKey, ...rest] = param.split("=");
759
+ if (!rawKey) {
760
+ continue;
761
+ }
762
+ if (rawKey.trim().toLowerCase() !== "for") {
763
+ continue;
764
+ }
765
+ const rawValue = rest.join("=").trim();
766
+ const normalized = normalizeKnownAddress(rawValue, redactionReplacement);
767
+ if (normalized) {
768
+ return normalized;
769
+ }
770
+ }
771
+ }
772
+ }
773
+ return void 0;
774
+ }
775
+ function xForwardedForClientAddress(values, redactionReplacement) {
776
+ for (const value of values) {
777
+ if (!value) {
778
+ continue;
779
+ }
780
+ const entries = value.split(",");
781
+ for (const entry of entries) {
782
+ const normalized = normalizeKnownAddress(entry, redactionReplacement);
783
+ if (normalized) {
784
+ return normalized;
785
+ }
786
+ }
787
+ }
788
+ return void 0;
789
+ }
790
+ function xRealIpClientAddress(values, redactionReplacement) {
791
+ for (const value of values) {
792
+ if (!value) {
793
+ continue;
794
+ }
795
+ const normalized = normalizeKnownAddress(value, redactionReplacement);
796
+ if (normalized) {
797
+ return normalized;
798
+ }
799
+ }
800
+ return void 0;
801
+ }
802
+ function normalizeKnownAddress(value, redactionReplacement) {
803
+ const normalized = normalizeAddress(value, redactionReplacement);
804
+ if (!normalized) {
805
+ return void 0;
806
+ }
807
+ if (normalized.toLowerCase() === "unknown") {
808
+ return void 0;
809
+ }
810
+ return normalized;
811
+ }
812
+ function normalizeAddress(value, redactionReplacement) {
813
+ if (!value) {
814
+ return void 0;
815
+ }
816
+ let trimmed = value.trim();
817
+ if (!trimmed) {
818
+ return void 0;
819
+ }
820
+ if (redactionReplacement && trimmed === redactionReplacement) {
821
+ return void 0;
822
+ }
823
+ if (trimmed.startsWith('"') && trimmed.endsWith('"') && trimmed.length > 1) {
824
+ trimmed = trimmed.slice(1, -1).trim();
825
+ }
826
+ if (!trimmed) {
827
+ return void 0;
828
+ }
829
+ if (trimmed.startsWith("[")) {
830
+ const end = trimmed.indexOf("]");
831
+ if (end !== -1) {
832
+ return trimmed.slice(1, end);
833
+ }
834
+ }
835
+ const colonCount = (_nullishCoalesce(trimmed.match(/:/g), () => ( []))).length;
836
+ if (colonCount === 1) {
837
+ const host = trimmed.split(":")[0];
838
+ return host || void 0;
839
+ }
840
+ return trimmed;
841
+ }
842
+ function remoteAddrHost(value) {
843
+ return normalizeAddress(value);
844
+ }
845
+ function headerValues(headers, name) {
846
+ if (!headers) {
847
+ return [];
848
+ }
849
+ const target = name.toLowerCase();
850
+ const values = [];
851
+ for (const [key, value] of Object.entries(headers)) {
852
+ if (key.toLowerCase() !== target) {
853
+ continue;
854
+ }
855
+ if (Array.isArray(value)) {
856
+ values.push(...value);
857
+ } else {
858
+ values.push(value);
859
+ }
860
+ }
861
+ return values;
862
+ }
863
+ function setRequestBodyAttributes(span, body) {
864
+ if (!body.value) {
865
+ return;
866
+ }
867
+ span.setAttribute(AttributeKeyRequestBody, body.value);
868
+ span.setAttribute(AttributeKeyRequestBodyEncoding, body.encoding);
869
+ if (body.truncated) {
870
+ span.setAttribute(AttributeKeyRequestBodyTruncated, true);
871
+ }
872
+ }
873
+ function setRequestBodySizeAttribute(span, size) {
874
+ span.setAttribute(_incubating.ATTR_HTTP_REQUEST_BODY_SIZE, size);
875
+ }
876
+ function setResponseBodyAttributes(span, body) {
877
+ if (!body.value) {
878
+ return;
879
+ }
880
+ span.setAttribute(AttributeKeyResponseBody, body.value);
881
+ span.setAttribute(AttributeKeyResponseBodyEncoding, body.encoding);
882
+ if (body.truncated) {
883
+ span.setAttribute(AttributeKeyResponseBodyTruncated, true);
884
+ }
885
+ }
886
+ function setResponseBodySizeAttribute(span, size) {
887
+ span.setAttribute(_incubating.ATTR_HTTP_RESPONSE_BODY_SIZE, size);
888
+ }
889
+ function setResponseStatusAttribute(span, statusCode) {
890
+ span.setAttribute(_incubating.ATTR_HTTP_RESPONSE_STATUS_CODE, statusCode);
891
+ }
892
+ function setRouteAttribute(span, route) {
893
+ if (route) {
894
+ span.setAttribute(_incubating.ATTR_HTTP_ROUTE, route);
895
+ }
896
+ }
897
+ function setUserIdAttribute(span, userId) {
898
+ span.setAttribute(_incubating.ATTR_USER_ID, userId);
899
+ }
900
+ function setRequestIdAttribute(span, requestId) {
901
+ span.setAttribute(AttributeKeyRequestID, requestId);
902
+ }
903
+
904
+ // src/core/otel.ts
905
+
906
+
907
+
908
+
909
+
910
+ var _api = require('@opentelemetry/api');
911
+
912
+
913
+
914
+
915
+
916
+ var _sdktracebase = require('@opentelemetry/sdk-trace-base');
917
+ var _resources = require('@opentelemetry/resources');
918
+
919
+
920
+
921
+
922
+
923
+ var _semanticconventions = require('@opentelemetry/semantic-conventions');
924
+ var defaultAttributeCountLimit = 128;
925
+ function createTracerProvider(config, exporter) {
926
+ if (config.exporter.endpointUrl.startsWith("http://")) {
927
+ _api.diag.warn("xray: OTLP endpoint uses plaintext HTTP");
928
+ }
929
+ const attributeValueLengthLimit = Math.max(1, Math.ceil(config.capture.maxBodyBytes * 4 / 3));
930
+ const resource = _resources.resourceFromAttributes.call(void 0, {
931
+ [_semanticconventions.ATTR_SERVICE_NAME]: config.serviceName,
932
+ [_semanticconventions.ATTR_TELEMETRY_SDK_LANGUAGE]: isNodeRuntime() ? "nodejs" : "webjs",
933
+ [_semanticconventions.ATTR_TELEMETRY_SDK_NAME]: "stainless-xray",
934
+ [_semanticconventions.ATTR_TELEMETRY_SDK_VERSION]: sdkVersion()
935
+ });
936
+ const spanProcessor = createSpanProcessor(config.exporter.spanProcessor, exporter);
937
+ const dropProcessor = new DropFilterSpanProcessor(spanProcessor);
938
+ const provider = new (0, _sdktracebase.BasicTracerProvider)({
939
+ forceFlushTimeoutMillis: 3e4,
940
+ generalLimits: {
941
+ attributeCountLimit: defaultAttributeCountLimit,
942
+ attributeValueLengthLimit
943
+ },
944
+ resource,
945
+ sampler: new (0, _sdktracebase.AlwaysOnSampler)(),
946
+ spanLimits: {
947
+ attributeCountLimit: defaultAttributeCountLimit,
948
+ attributePerEventCountLimit: defaultAttributeCountLimit,
949
+ attributePerLinkCountLimit: defaultAttributeCountLimit,
950
+ attributeValueLengthLimit,
951
+ eventCountLimit: defaultAttributeCountLimit,
952
+ linkCountLimit: defaultAttributeCountLimit
953
+ },
954
+ spanProcessors: [dropProcessor]
955
+ });
956
+ return provider;
957
+ }
958
+ function tracerFromProvider(provider) {
959
+ return provider.getTracer("stainless-xray");
960
+ }
961
+ function spanFromTracer(tracer, name) {
962
+ return tracer.startSpan(name, { kind: _api.SpanKind.SERVER }, _api.ROOT_CONTEXT);
963
+ }
964
+ function spanStatusFromError(span, err) {
965
+ if (err instanceof Error) {
966
+ span.recordException(err);
967
+ } else if (typeof err === "string") {
968
+ span.recordException(err);
969
+ } else {
970
+ span.recordException({ message: String(err) });
971
+ }
972
+ span.setStatus({ code: _api.SpanStatusCode.ERROR });
973
+ }
974
+ var DropFilterSpanProcessor = class {
975
+ constructor(next) {
976
+ this.next = next;
977
+ }
978
+ forceFlush() {
979
+ return this.next.forceFlush();
980
+ }
981
+ onEnd(span) {
982
+ if (span.attributes[AttributeKeySpanDrop] === true) {
983
+ return;
984
+ }
985
+ this.next.onEnd(span);
986
+ }
987
+ onStart(span, parentContext) {
988
+ this.next.onStart(span, parentContext);
989
+ }
990
+ shutdown() {
991
+ return this.next.shutdown();
992
+ }
993
+ };
994
+ function createSpanProcessor(mode, exporter) {
995
+ if (mode === "simple") {
996
+ return new (0, _sdktracebase.SimpleSpanProcessor)(exporter);
997
+ }
998
+ return new (0, _sdktracebase.BatchSpanProcessor)(exporter, {
999
+ maxQueueSize: 2048,
1000
+ maxExportBatchSize: 512,
1001
+ scheduledDelayMillis: 5e3,
1002
+ exportTimeoutMillis: 3e4
1003
+ });
1004
+ }
1005
+ function sdkVersion() {
1006
+ if (typeof __XRAY_VERSION__ !== "undefined") {
1007
+ return __XRAY_VERSION__;
1008
+ }
1009
+ return "unknown";
1010
+ }
1011
+ function isNodeRuntime() {
1012
+ const maybeProcess = globalThis.process;
1013
+ return !!_optionalChain([maybeProcess, 'optionalAccess', _15 => _15.versions, 'optionalAccess', _16 => _16.node]);
1014
+ }
1015
+
1016
+ // src/core/emitter.ts
1017
+ function createEmitter(config, exporter) {
1018
+ const resolved = normalizeConfig(config);
1019
+ if (!exporter) {
1020
+ throw new XrayConfigError(
1021
+ "INVALID_CONFIG",
1022
+ "exporter is required (use @stainlessdev/xray-node or @stainlessdev/xray-fetch)"
1023
+ );
1024
+ }
1025
+ _chunkJKW6E4L3cjs.logWithLevel.call(void 0, resolved.logger, "info", resolved.logLevel, "xray: emitter configured", {
1026
+ serviceName: resolved.serviceName,
1027
+ environment: resolved.environment,
1028
+ version: resolved.version,
1029
+ exporterEndpoint: resolved.exporter.endpointUrl,
1030
+ spanProcessor: resolved.exporter.spanProcessor
1031
+ });
1032
+ const tracerProvider = createTracerProvider(resolved, exporter);
1033
+ const tracer = tracerFromProvider(tracerProvider);
1034
+ return {
1035
+ config: resolved,
1036
+ startRequest: (req) => startRequest(resolved, tracer, req),
1037
+ endRequest: (ctx, res, err) => endRequest(resolved, ctx, res, err),
1038
+ flush: () => tracerProvider.forceFlush(),
1039
+ shutdown: () => tracerProvider.shutdown()
1040
+ };
1041
+ }
1042
+ function startRequest(config, tracer, req) {
1043
+ const startTimeMs = Number.isFinite(req.startTimeMs) ? req.startTimeMs : Date.now();
1044
+ req.startTimeMs = startTimeMs;
1045
+ const explicitRequestId = normalizeRequestIdCandidate(req.requestId);
1046
+ req.requestId = explicitRequestId;
1047
+ if (req.route && config.route.normalize) {
1048
+ req.route = config.route.normalizer ? config.route.normalizer(req.route) : normalizeRoutePattern(req.route);
1049
+ }
1050
+ const span = spanFromTracer(tracer, spanNameFromRequest(req));
1051
+ const context = {
1052
+ requestId: _nullishCoalesce(explicitRequestId, () => ( "")),
1053
+ traceId: _optionalChain([span, 'optionalAccess', _17 => _17.spanContext, 'call', _18 => _18(), 'access', _19 => _19.traceId]),
1054
+ spanId: _optionalChain([span, 'optionalAccess', _20 => _20.spanContext, 'call', _21 => _21(), 'access', _22 => _22.spanId]),
1055
+ setUserId: (id) => {
1056
+ const state2 = _chunkJKW6E4L3cjs.getContextState.call(void 0, context);
1057
+ if (!state2) {
1058
+ return;
1059
+ }
1060
+ state2.userId = id;
1061
+ if (span && id) {
1062
+ try {
1063
+ setUserIdAttribute(span, id);
1064
+ } catch (e6) {
1065
+ }
1066
+ }
1067
+ },
1068
+ setSessionId: (id) => {
1069
+ const state2 = _chunkJKW6E4L3cjs.getContextState.call(void 0, context);
1070
+ if (!state2) {
1071
+ return;
1072
+ }
1073
+ state2.sessionId = id;
1074
+ },
1075
+ setAttribute: (key, value) => {
1076
+ const state2 = _chunkJKW6E4L3cjs.getContextState.call(void 0, context);
1077
+ if (!state2) {
1078
+ return;
1079
+ }
1080
+ state2.attributes[key] = value;
1081
+ if (span) {
1082
+ try {
1083
+ span.setAttribute(key, value);
1084
+ } catch (e7) {
1085
+ }
1086
+ }
1087
+ },
1088
+ addEvent: (name, attributes) => {
1089
+ const state2 = _chunkJKW6E4L3cjs.getContextState.call(void 0, context);
1090
+ if (!state2) {
1091
+ return;
1092
+ }
1093
+ state2.events.push({ name, attributes });
1094
+ if (span) {
1095
+ try {
1096
+ span.addEvent(name, attributes);
1097
+ } catch (e8) {
1098
+ }
1099
+ }
1100
+ },
1101
+ setError: (err) => {
1102
+ const state2 = _chunkJKW6E4L3cjs.getContextState.call(void 0, context);
1103
+ if (!state2) {
1104
+ return;
1105
+ }
1106
+ state2.error = err;
1107
+ if (span) {
1108
+ try {
1109
+ spanStatusFromError(span, err);
1110
+ } catch (e9) {
1111
+ }
1112
+ }
1113
+ }
1114
+ };
1115
+ const state = {
1116
+ request: req,
1117
+ config,
1118
+ span,
1119
+ context,
1120
+ attributes: {},
1121
+ events: []
1122
+ };
1123
+ _chunkJKW6E4L3cjs.bindContext.call(void 0, context, state);
1124
+ return context;
1125
+ }
1126
+ function endRequest(config, ctx, res, err) {
1127
+ const state = _chunkJKW6E4L3cjs.getContextState.call(void 0, ctx);
1128
+ const endTimeMs = Number.isFinite(res.endTimeMs) ? res.endTimeMs : Date.now();
1129
+ res.endTimeMs = endTimeMs;
1130
+ if (!state) {
1131
+ const resolvedRequestId2 = resolveFinalRequestId(config, ctx.requestId, res.headers);
1132
+ ctx.requestId = resolvedRequestId2;
1133
+ const fallbackLog = {
1134
+ requestId: resolvedRequestId2,
1135
+ serviceName: config.serviceName,
1136
+ method: res.statusCode ? "UNKNOWN" : "UNKNOWN",
1137
+ url: "",
1138
+ durationMs: 0,
1139
+ statusCode: res.statusCode,
1140
+ timestamp: new Date(endTimeMs).toISOString()
1141
+ };
1142
+ return fallbackLog;
1143
+ }
1144
+ const request = state.request;
1145
+ const resolvedRequestId = resolveFinalRequestId(
1146
+ config,
1147
+ request.requestId || ctx.requestId,
1148
+ res.headers
1149
+ );
1150
+ request.requestId = resolvedRequestId;
1151
+ ctx.requestId = resolvedRequestId;
1152
+ const capture = resolveCapture(config.capture, state.captureOverride);
1153
+ const redaction = resolveRedaction(config.redaction, state.redactionOverride);
1154
+ const route = request.route;
1155
+ const url = _chunkJKW6E4L3cjs.sanitizeLogString.call(void 0, request.url);
1156
+ const log = {
1157
+ requestId: resolvedRequestId,
1158
+ traceId: _optionalChain([state, 'access', _23 => _23.span, 'optionalAccess', _24 => _24.spanContext, 'call', _25 => _25(), 'access', _26 => _26.traceId]),
1159
+ spanId: _optionalChain([state, 'access', _27 => _27.span, 'optionalAccess', _28 => _28.spanContext, 'call', _29 => _29(), 'access', _30 => _30.spanId]),
1160
+ serviceName: config.serviceName,
1161
+ method: request.method,
1162
+ url,
1163
+ route,
1164
+ statusCode: res.statusCode,
1165
+ durationMs: Math.max(0, endTimeMs - request.startTimeMs),
1166
+ requestHeaders: capture.requestHeaders ? _chunkJKW6E4L3cjs.sanitizeHeaderValues.call(void 0, request.headers) : void 0,
1167
+ responseHeaders: capture.responseHeaders ? _chunkJKW6E4L3cjs.sanitizeHeaderValues.call(void 0, res.headers) : void 0,
1168
+ requestBody: capture.requestBody === "none" ? void 0 : request.body,
1169
+ responseBody: capture.responseBody === "none" ? void 0 : res.body,
1170
+ userId: _nullishCoalesce(state.userId, () => ( void 0)),
1171
+ sessionId: _nullishCoalesce(state.sessionId, () => ( void 0)),
1172
+ error: buildError(_nullishCoalesce(err, () => ( state.error))),
1173
+ attributes: Object.keys(state.attributes).length > 0 ? { ...state.attributes } : void 0,
1174
+ timestamp: new Date(endTimeMs).toISOString()
1175
+ };
1176
+ const redacted = applyRedaction(redaction, log);
1177
+ if (redacted.route && config.route.normalize) {
1178
+ const normalized = config.route.normalizer ? config.route.normalizer(redacted.route) : normalizeRoutePattern(redacted.route);
1179
+ redacted.route = normalized;
1180
+ }
1181
+ const span = state.span;
1182
+ if (span) {
1183
+ try {
1184
+ const clientAddressHeaders = redactHeaders(request.headers, redaction);
1185
+ setRequestAttributes(
1186
+ span,
1187
+ {
1188
+ ...request,
1189
+ headers: clientAddressHeaders,
1190
+ redactionReplacement: redaction.replacement
1191
+ },
1192
+ redacted.url
1193
+ );
1194
+ setRequestIdAttribute(span, redacted.requestId);
1195
+ span.setAttribute("service.name", config.serviceName);
1196
+ if (redacted.statusCode != null) {
1197
+ setResponseStatusAttribute(span, redacted.statusCode);
1198
+ }
1199
+ if (redacted.route) {
1200
+ setRouteAttribute(span, redacted.route);
1201
+ span.updateName(`${request.method} ${redacted.route}`);
1202
+ } else {
1203
+ span.updateName(spanNameFromRequest(request));
1204
+ }
1205
+ if (redacted.requestHeaders) {
1206
+ setHeaderAttributes(span, redacted.requestHeaders, "http.request.header.");
1207
+ }
1208
+ if (redacted.responseHeaders) {
1209
+ setHeaderAttributes(span, redacted.responseHeaders, "http.response.header.");
1210
+ }
1211
+ if (redacted.requestBody) {
1212
+ setRequestBodyAttributes(span, redacted.requestBody);
1213
+ setRequestBodySizeAttribute(span, redacted.requestBody.bytes);
1214
+ }
1215
+ if (redacted.responseBody) {
1216
+ setResponseBodyAttributes(span, redacted.responseBody);
1217
+ setResponseBodySizeAttribute(span, redacted.responseBody.bytes);
1218
+ }
1219
+ if (state.userId) {
1220
+ setUserIdAttribute(span, state.userId);
1221
+ }
1222
+ if (_nullishCoalesce(err, () => ( state.error))) {
1223
+ spanStatusFromError(span, _nullishCoalesce(err, () => ( state.error)));
1224
+ }
1225
+ span.end();
1226
+ } catch (spanErr) {
1227
+ _chunkJKW6E4L3cjs.logWithLevel.call(void 0, config.logger, "warn", config.logLevel, "xray: span finalize failed", {
1228
+ error: spanErr instanceof Error ? spanErr.message : String(spanErr)
1229
+ });
1230
+ }
1231
+ }
1232
+ return redacted;
1233
+ }
1234
+ function resolveFinalRequestId(config, explicitRequestId, responseHeaders) {
1235
+ const explicit = normalizeRequestIdCandidate(explicitRequestId);
1236
+ if (explicit) {
1237
+ return explicit;
1238
+ }
1239
+ const headerValue = resolveHeaderRequestId(config.requestId.header, responseHeaders);
1240
+ if (headerValue) {
1241
+ return headerValue;
1242
+ }
1243
+ return _chunkJKW6E4L3cjs.generateRequestId.call(void 0, );
1244
+ }
1245
+ function resolveHeaderRequestId(headerName, headers) {
1246
+ if (!headers) {
1247
+ return void 0;
1248
+ }
1249
+ const target = headerName.toLowerCase();
1250
+ for (const [name, value] of Object.entries(headers)) {
1251
+ if (name.toLowerCase() !== target) {
1252
+ continue;
1253
+ }
1254
+ const entry = Array.isArray(value) ? value[0] : value;
1255
+ const normalized = normalizeRequestIdCandidate(entry);
1256
+ if (normalized) {
1257
+ return normalized;
1258
+ }
1259
+ }
1260
+ return void 0;
1261
+ }
1262
+ function normalizeRequestIdCandidate(value) {
1263
+ if (!value) {
1264
+ return void 0;
1265
+ }
1266
+ const trimmed = value.trim();
1267
+ return trimmed ? trimmed : void 0;
1268
+ }
1269
+ function resolveCapture(base, override) {
1270
+ if (!override) {
1271
+ return base;
1272
+ }
1273
+ return {
1274
+ ...base,
1275
+ ...override
1276
+ };
1277
+ }
1278
+ function resolveRedaction(base, override) {
1279
+ const merged = {
1280
+ ...base,
1281
+ ...override
1282
+ };
1283
+ merged.headers = normalizeLowercaseList(merged.headers);
1284
+ merged.queryParams = normalizeLowercaseList(merged.queryParams);
1285
+ merged.bodyJsonPaths = normalizeList(merged.bodyJsonPaths);
1286
+ merged.replacement = merged.replacement || base.replacement;
1287
+ return merged;
1288
+ }
1289
+ function normalizeLowercaseList(values) {
1290
+ if (!values) {
1291
+ return [];
1292
+ }
1293
+ return values.map((entry) => entry.trim().toLowerCase()).filter(Boolean);
1294
+ }
1295
+ function normalizeList(values) {
1296
+ if (!values) {
1297
+ return [];
1298
+ }
1299
+ return values.map((entry) => entry.trim()).filter(Boolean);
1300
+ }
1301
+ function buildError(err) {
1302
+ if (!err) {
1303
+ return void 0;
1304
+ }
1305
+ if (err instanceof Error) {
1306
+ return {
1307
+ message: err.message || "Error",
1308
+ type: err.name || "Error",
1309
+ stack: err.stack
1310
+ };
1311
+ }
1312
+ return {
1313
+ message: String(err)
1314
+ };
1315
+ }
1316
+ function spanNameFromRequest(req) {
1317
+ const method = req.method || "GET";
1318
+ if (req.route) {
1319
+ return `${method} ${req.route}`;
1320
+ }
1321
+ const path = safePath(req.url);
1322
+ return `${method} ${path}`;
1323
+ }
1324
+ function safePath(url) {
1325
+ try {
1326
+ const parsed = new URL(url);
1327
+ return parsed.pathname || "/";
1328
+ } catch (e10) {
1329
+ const rawPath = url.split("?")[0] || "/";
1330
+ return rawPath || "/";
1331
+ }
1332
+ }
1333
+
1334
+
1335
+
1336
+
1337
+
1338
+ exports.XrayConfigError = XrayConfigError; exports.normalizeConfig = normalizeConfig; exports.createEmitter = createEmitter;
1339
+ //# sourceMappingURL=chunk-3MVVO5I7.cjs.map