@stainlessdev/xray-core 0.5.1 → 0.6.0-branch.bg-fix-req-id-gen.e29953f
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.
- package/dist/{chunk-XI5E6C7G.js → chunk-HGFCHC7O.js} +21 -1
- package/dist/chunk-HGFCHC7O.js.map +1 -0
- package/dist/index.cjs +207 -25
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +2 -2
- package/dist/index.d.ts +2 -2
- package/dist/index.js +211 -46
- package/dist/index.js.map +1 -1
- package/dist/internal.cjs +23 -2
- package/dist/internal.cjs.map +1 -1
- package/dist/internal.d.cts +9 -2
- package/dist/internal.d.ts +9 -2
- package/dist/internal.js +5 -3
- package/dist/internal.js.map +1 -1
- package/dist/{types-BA4cE85r.d.cts → types-Z1nirh-F.d.cts} +12 -1
- package/dist/{types-BA4cE85r.d.ts → types-Z1nirh-F.d.ts} +12 -1
- package/package.json +1 -1
- package/dist/chunk-XI5E6C7G.js.map +0 -1
|
@@ -109,6 +109,25 @@ function makeCapturedBody(bytes, totalBytes, truncated, mode) {
|
|
|
109
109
|
};
|
|
110
110
|
}
|
|
111
111
|
|
|
112
|
+
// src/uuid.ts
|
|
113
|
+
function uuidv7() {
|
|
114
|
+
const bytes = new Uint8Array(16);
|
|
115
|
+
crypto.getRandomValues(bytes);
|
|
116
|
+
const timestamp = BigInt(Date.now());
|
|
117
|
+
bytes[0] = Number(timestamp >> 40n & 0xffn);
|
|
118
|
+
bytes[1] = Number(timestamp >> 32n & 0xffn);
|
|
119
|
+
bytes[2] = Number(timestamp >> 24n & 0xffn);
|
|
120
|
+
bytes[3] = Number(timestamp >> 16n & 0xffn);
|
|
121
|
+
bytes[4] = Number(timestamp >> 8n & 0xffn);
|
|
122
|
+
bytes[5] = Number(timestamp & 0xffn);
|
|
123
|
+
const byte6 = bytes[6] ?? 0;
|
|
124
|
+
const byte8 = bytes[8] ?? 0;
|
|
125
|
+
bytes[6] = byte6 & 15 | 112;
|
|
126
|
+
bytes[8] = byte8 & 63 | 128;
|
|
127
|
+
const hex = Array.from(bytes, (b) => b.toString(16).padStart(2, "0"));
|
|
128
|
+
return `${hex.slice(0, 4).join("")}-${hex.slice(4, 6).join("")}-${hex.slice(6, 8).join("")}-${hex.slice(8, 10).join("")}-${hex.slice(10).join("")}`;
|
|
129
|
+
}
|
|
130
|
+
|
|
112
131
|
// src/state.ts
|
|
113
132
|
var contextMap = /* @__PURE__ */ new WeakMap();
|
|
114
133
|
var objectMap = /* @__PURE__ */ new WeakMap();
|
|
@@ -165,9 +184,10 @@ export {
|
|
|
165
184
|
sanitizeLogString,
|
|
166
185
|
sanitizeHeaderValues,
|
|
167
186
|
makeCapturedBody,
|
|
187
|
+
uuidv7,
|
|
168
188
|
bindContext,
|
|
169
189
|
getContextState,
|
|
170
190
|
bindObject,
|
|
171
191
|
getContextFromObject
|
|
172
192
|
};
|
|
173
|
-
//# sourceMappingURL=chunk-
|
|
193
|
+
//# sourceMappingURL=chunk-HGFCHC7O.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/logger.ts","../src/encoding.ts","../src/request_log.ts","../src/uuid.ts","../src/state.ts"],"sourcesContent":["import type { Logger, LogLevel } from './types';\n\nconst logLevelOrder: Record<LogLevel, number> = {\n debug: 10,\n info: 20,\n warn: 30,\n error: 40,\n};\n\nexport function logWithLevel(\n logger: Logger,\n level: LogLevel,\n threshold: LogLevel,\n message: string,\n fields?: Record<string, unknown>,\n): void {\n if (logLevelOrder[level] < logLevelOrder[threshold]) {\n return;\n }\n\n const fn =\n logger[level] ?? logger.warn ?? logger.info ?? logger.debug ?? logger.error ?? console.log;\n\n try {\n fn.call(logger, message, fields);\n } catch {\n // Logging should never disrupt instrumentation.\n }\n}\n","const utf8Decoder =\n typeof TextDecoder !== 'undefined' ? new TextDecoder('utf-8', { fatal: true }) : null;\nconst utf8DecoderLenient = typeof TextDecoder !== 'undefined' ? new TextDecoder('utf-8') : null;\nconst maybeBuffer = (\n globalThis as typeof globalThis & {\n Buffer?: { from(data: Uint8Array): { toString(encoding?: string): string } };\n }\n).Buffer;\n\nexport function encodeBase64(bytes: Uint8Array): string {\n if (maybeBuffer) {\n return maybeBuffer.from(bytes).toString('base64');\n }\n let binary = '';\n for (let i = 0; i < bytes.length; i += 1) {\n const byte = bytes[i];\n if (byte === undefined) {\n continue;\n }\n binary += String.fromCharCode(byte);\n }\n if (typeof btoa !== 'undefined') {\n return btoa(binary);\n }\n return '';\n}\n\nexport function isValidUtf8(bytes: Uint8Array): boolean {\n if (!utf8Decoder) {\n return false;\n }\n try {\n utf8Decoder.decode(bytes);\n return true;\n } catch {\n return false;\n }\n}\n\nexport function decodeUtf8(bytes: Uint8Array): string {\n if (utf8DecoderLenient) {\n return utf8DecoderLenient.decode(bytes);\n }\n if (maybeBuffer) {\n return maybeBuffer.from(bytes).toString('utf8');\n }\n return '';\n}\n","import type { CapturedBody } from './types';\nimport { decodeUtf8, encodeBase64, isValidUtf8 } from './encoding';\n\n// eslint-disable-next-line no-control-regex\nconst controlChars = /[\\x00-\\x1F\\x7F]/g;\n\nexport function sanitizeLogString(value: string): string {\n if (!value) {\n return value;\n }\n return value.replace(controlChars, '');\n}\n\nexport function sanitizeHeaderValues(\n headers: Record<string, string | string[]> | undefined,\n): Record<string, string | string[]> | undefined {\n if (!headers) {\n return undefined;\n }\n\n const sanitized: Record<string, string | string[]> = {};\n for (const [key, value] of Object.entries(headers)) {\n const name = sanitizeLogString(key);\n if (Array.isArray(value)) {\n sanitized[name] = value.map((entry) => sanitizeLogString(entry));\n } else {\n sanitized[name] = sanitizeLogString(value);\n }\n }\n return sanitized;\n}\n\nexport function makeCapturedBody(\n bytes: Uint8Array | undefined,\n totalBytes: number,\n truncated: boolean,\n mode: 'text' | 'base64',\n): CapturedBody | undefined {\n if (!bytes) {\n return undefined;\n }\n\n if (mode === 'base64') {\n return {\n bytes: totalBytes,\n encoding: 'base64',\n truncated,\n value: encodeBase64(bytes),\n };\n }\n\n if (isValidUtf8(bytes)) {\n return {\n bytes: totalBytes,\n encoding: 'utf8',\n truncated,\n value: decodeUtf8(bytes),\n };\n }\n\n return {\n bytes: totalBytes,\n encoding: 'base64',\n truncated,\n value: encodeBase64(bytes),\n };\n}\n","/**\n * Generates a UUIDv7 string.\n * Uses crypto.getRandomValues which is available in all modern JS runtimes\n * (browsers, Node.js 15+, Deno, Bun, Cloudflare Workers, Vercel Edge, etc.)\n */\nexport function uuidv7(): string {\n const bytes = new Uint8Array(16);\n crypto.getRandomValues(bytes);\n\n // Encode timestamp in first 48 bits\n const timestamp = BigInt(Date.now());\n bytes[0] = Number((timestamp >> 40n) & 0xffn);\n bytes[1] = Number((timestamp >> 32n) & 0xffn);\n bytes[2] = Number((timestamp >> 24n) & 0xffn);\n bytes[3] = Number((timestamp >> 16n) & 0xffn);\n bytes[4] = Number((timestamp >> 8n) & 0xffn);\n bytes[5] = Number(timestamp & 0xffn);\n\n // Set version (7) and variant (RFC 4122)\n const byte6 = bytes[6] ?? 0;\n const byte8 = bytes[8] ?? 0;\n bytes[6] = (byte6 & 0x0f) | 0x70;\n bytes[8] = (byte8 & 0x3f) | 0x80;\n\n // Format as UUID string\n const hex = Array.from(bytes, (b) => b.toString(16).padStart(2, '0'));\n return `${hex.slice(0, 4).join('')}-${hex.slice(4, 6).join('')}-${hex.slice(6, 8).join('')}-${hex.slice(8, 10).join('')}-${hex.slice(10).join('')}`;\n}\n","import type { Span } from '@opentelemetry/api';\nimport type { AttributeValue, NormalizedRequest, XrayContext } from './types';\nimport type { CaptureConfig, RedactionConfig, ResolvedXrayConfig } from './config';\n\nexport type RequestState = {\n request: NormalizedRequest;\n config: ResolvedXrayConfig;\n span?: Span;\n context: XrayContext;\n attributes: Record<string, AttributeValue>;\n events: Array<{ name: string; attributes?: Record<string, AttributeValue> }>;\n userId?: string;\n sessionId?: string;\n error?: unknown;\n captureOverride?: Partial<CaptureConfig>;\n redactionOverride?: Partial<RedactionConfig>;\n};\n\nconst contextMap = new WeakMap<XrayContext, RequestState>();\nconst objectMap = new WeakMap<object, RequestState>();\n\nexport function bindContext(ctx: XrayContext, state: RequestState): void {\n contextMap.set(ctx, state);\n}\n\nexport function getContextState(ctx: XrayContext): RequestState | undefined {\n return contextMap.get(ctx);\n}\n\nexport function bindObject(target: object, state: RequestState): void {\n objectMap.set(target, state);\n}\n\nexport function getContextFromObject(target: unknown): XrayContext | undefined {\n const state = getStateFromObject(target);\n return state?.context;\n}\n\nexport function getStateFromObject(target: unknown): RequestState | undefined {\n if (!target || typeof target !== 'object') {\n return undefined;\n }\n if (objectMap.has(target)) {\n return objectMap.get(target);\n }\n\n const fallback = findNestedTarget(target as Record<string, unknown>);\n if (fallback && objectMap.has(fallback)) {\n return objectMap.get(fallback);\n }\n return undefined;\n}\n\nfunction findNestedTarget(obj: Record<string, unknown>): object | null {\n if (obj.raw && typeof obj.raw === 'object') {\n return obj.raw as object;\n }\n if (obj.req && typeof obj.req === 'object') {\n const req = obj.req as Record<string, unknown>;\n if (req.raw && typeof req.raw === 'object') {\n return req.raw as object;\n }\n return req as object;\n }\n if (obj.request && typeof obj.request === 'object') {\n const request = obj.request as Record<string, unknown>;\n if (request.raw && typeof request.raw === 'object') {\n return request.raw as object;\n }\n return request as object;\n }\n return null;\n}\n"],"mappings":"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","names":[]}
|
package/dist/index.cjs
CHANGED
|
@@ -152,8 +152,7 @@ var defaultRedaction = {
|
|
|
152
152
|
replacement: "[REDACTED]"
|
|
153
153
|
};
|
|
154
154
|
var defaultRequestId = {
|
|
155
|
-
header: "
|
|
156
|
-
generate: true
|
|
155
|
+
header: "request-id"
|
|
157
156
|
};
|
|
158
157
|
var defaultRoute = {
|
|
159
158
|
normalize: true,
|
|
@@ -768,15 +767,24 @@ function setHeaderAttributes(span, headers, prefix) {
|
|
|
768
767
|
span.setAttribute(prefix + key.toLowerCase(), Array.isArray(values) ? values : [values]);
|
|
769
768
|
}
|
|
770
769
|
}
|
|
771
|
-
function setRequestAttributes(span,
|
|
772
|
-
span.setAttribute(import_incubating.ATTR_HTTP_REQUEST_METHOD, method);
|
|
773
|
-
|
|
774
|
-
|
|
775
|
-
|
|
770
|
+
function setRequestAttributes(span, request, urlFull) {
|
|
771
|
+
span.setAttribute(import_incubating.ATTR_HTTP_REQUEST_METHOD, request.method);
|
|
772
|
+
const effectiveUrl = urlFull ?? request.url;
|
|
773
|
+
if (effectiveUrl) {
|
|
774
|
+
span.setAttribute(import_incubating.ATTR_URL_FULL, effectiveUrl);
|
|
775
|
+
const path = extractPath(effectiveUrl);
|
|
776
776
|
if (path) {
|
|
777
777
|
span.setAttribute(import_incubating.ATTR_URL_PATH, path);
|
|
778
778
|
}
|
|
779
779
|
}
|
|
780
|
+
const clientAddress = clientAddressForRequest(
|
|
781
|
+
request.headers,
|
|
782
|
+
request.remoteAddress,
|
|
783
|
+
request.redactionReplacement
|
|
784
|
+
);
|
|
785
|
+
if (clientAddress) {
|
|
786
|
+
span.setAttribute(import_incubating.ATTR_CLIENT_ADDRESS, clientAddress);
|
|
787
|
+
}
|
|
780
788
|
}
|
|
781
789
|
function extractPath(url) {
|
|
782
790
|
try {
|
|
@@ -786,6 +794,144 @@ function extractPath(url) {
|
|
|
786
794
|
return match?.[0] || void 0;
|
|
787
795
|
}
|
|
788
796
|
}
|
|
797
|
+
function clientAddressForRequest(headers, remoteAddress, redactionReplacement) {
|
|
798
|
+
const forwarded = forwardedClientAddress(
|
|
799
|
+
headerValues(headers, "forwarded"),
|
|
800
|
+
redactionReplacement
|
|
801
|
+
);
|
|
802
|
+
if (forwarded) {
|
|
803
|
+
return forwarded;
|
|
804
|
+
}
|
|
805
|
+
const xForwarded = xForwardedForClientAddress(
|
|
806
|
+
headerValues(headers, "x-forwarded-for"),
|
|
807
|
+
redactionReplacement
|
|
808
|
+
);
|
|
809
|
+
if (xForwarded) {
|
|
810
|
+
return xForwarded;
|
|
811
|
+
}
|
|
812
|
+
const xRealIp = xRealIpClientAddress(headerValues(headers, "x-real-ip"), redactionReplacement);
|
|
813
|
+
if (xRealIp) {
|
|
814
|
+
return xRealIp;
|
|
815
|
+
}
|
|
816
|
+
if (!remoteAddress) {
|
|
817
|
+
return void 0;
|
|
818
|
+
}
|
|
819
|
+
return remoteAddrHost(remoteAddress);
|
|
820
|
+
}
|
|
821
|
+
function forwardedClientAddress(values, redactionReplacement) {
|
|
822
|
+
for (const value of values) {
|
|
823
|
+
if (!value) {
|
|
824
|
+
continue;
|
|
825
|
+
}
|
|
826
|
+
const entries = value.split(",");
|
|
827
|
+
for (const entry of entries) {
|
|
828
|
+
const params = entry.split(";");
|
|
829
|
+
for (const param of params) {
|
|
830
|
+
const [rawKey, ...rest] = param.split("=");
|
|
831
|
+
if (!rawKey) {
|
|
832
|
+
continue;
|
|
833
|
+
}
|
|
834
|
+
if (rawKey.trim().toLowerCase() !== "for") {
|
|
835
|
+
continue;
|
|
836
|
+
}
|
|
837
|
+
const rawValue = rest.join("=").trim();
|
|
838
|
+
const normalized = normalizeKnownAddress(rawValue, redactionReplacement);
|
|
839
|
+
if (normalized) {
|
|
840
|
+
return normalized;
|
|
841
|
+
}
|
|
842
|
+
}
|
|
843
|
+
}
|
|
844
|
+
}
|
|
845
|
+
return void 0;
|
|
846
|
+
}
|
|
847
|
+
function xForwardedForClientAddress(values, redactionReplacement) {
|
|
848
|
+
for (const value of values) {
|
|
849
|
+
if (!value) {
|
|
850
|
+
continue;
|
|
851
|
+
}
|
|
852
|
+
const entries = value.split(",");
|
|
853
|
+
for (const entry of entries) {
|
|
854
|
+
const normalized = normalizeKnownAddress(entry, redactionReplacement);
|
|
855
|
+
if (normalized) {
|
|
856
|
+
return normalized;
|
|
857
|
+
}
|
|
858
|
+
}
|
|
859
|
+
}
|
|
860
|
+
return void 0;
|
|
861
|
+
}
|
|
862
|
+
function xRealIpClientAddress(values, redactionReplacement) {
|
|
863
|
+
for (const value of values) {
|
|
864
|
+
if (!value) {
|
|
865
|
+
continue;
|
|
866
|
+
}
|
|
867
|
+
const normalized = normalizeKnownAddress(value, redactionReplacement);
|
|
868
|
+
if (normalized) {
|
|
869
|
+
return normalized;
|
|
870
|
+
}
|
|
871
|
+
}
|
|
872
|
+
return void 0;
|
|
873
|
+
}
|
|
874
|
+
function normalizeKnownAddress(value, redactionReplacement) {
|
|
875
|
+
const normalized = normalizeAddress(value, redactionReplacement);
|
|
876
|
+
if (!normalized) {
|
|
877
|
+
return void 0;
|
|
878
|
+
}
|
|
879
|
+
if (normalized.toLowerCase() === "unknown") {
|
|
880
|
+
return void 0;
|
|
881
|
+
}
|
|
882
|
+
return normalized;
|
|
883
|
+
}
|
|
884
|
+
function normalizeAddress(value, redactionReplacement) {
|
|
885
|
+
if (!value) {
|
|
886
|
+
return void 0;
|
|
887
|
+
}
|
|
888
|
+
let trimmed = value.trim();
|
|
889
|
+
if (!trimmed) {
|
|
890
|
+
return void 0;
|
|
891
|
+
}
|
|
892
|
+
if (redactionReplacement && trimmed === redactionReplacement) {
|
|
893
|
+
return void 0;
|
|
894
|
+
}
|
|
895
|
+
if (trimmed.startsWith('"') && trimmed.endsWith('"') && trimmed.length > 1) {
|
|
896
|
+
trimmed = trimmed.slice(1, -1).trim();
|
|
897
|
+
}
|
|
898
|
+
if (!trimmed) {
|
|
899
|
+
return void 0;
|
|
900
|
+
}
|
|
901
|
+
if (trimmed.startsWith("[")) {
|
|
902
|
+
const end = trimmed.indexOf("]");
|
|
903
|
+
if (end !== -1) {
|
|
904
|
+
return trimmed.slice(1, end);
|
|
905
|
+
}
|
|
906
|
+
}
|
|
907
|
+
const colonCount = (trimmed.match(/:/g) ?? []).length;
|
|
908
|
+
if (colonCount === 1) {
|
|
909
|
+
const host = trimmed.split(":")[0];
|
|
910
|
+
return host || void 0;
|
|
911
|
+
}
|
|
912
|
+
return trimmed;
|
|
913
|
+
}
|
|
914
|
+
function remoteAddrHost(value) {
|
|
915
|
+
return normalizeAddress(value);
|
|
916
|
+
}
|
|
917
|
+
function headerValues(headers, name) {
|
|
918
|
+
if (!headers) {
|
|
919
|
+
return [];
|
|
920
|
+
}
|
|
921
|
+
const target = name.toLowerCase();
|
|
922
|
+
const values = [];
|
|
923
|
+
for (const [key, value] of Object.entries(headers)) {
|
|
924
|
+
if (key.toLowerCase() !== target) {
|
|
925
|
+
continue;
|
|
926
|
+
}
|
|
927
|
+
if (Array.isArray(value)) {
|
|
928
|
+
values.push(...value);
|
|
929
|
+
} else {
|
|
930
|
+
values.push(value);
|
|
931
|
+
}
|
|
932
|
+
}
|
|
933
|
+
return values;
|
|
934
|
+
}
|
|
789
935
|
function setRequestBodyAttributes(span, body) {
|
|
790
936
|
if (!body.value) {
|
|
791
937
|
return;
|
|
@@ -915,7 +1061,7 @@ function createSpanProcessor(mode, exporter) {
|
|
|
915
1061
|
}
|
|
916
1062
|
function sdkVersion() {
|
|
917
1063
|
if (true) {
|
|
918
|
-
return "0.
|
|
1064
|
+
return "0.6.0";
|
|
919
1065
|
}
|
|
920
1066
|
return "unknown";
|
|
921
1067
|
}
|
|
@@ -981,14 +1127,14 @@ function createEmitter(config, exporter) {
|
|
|
981
1127
|
function startRequest(config, tracer, req) {
|
|
982
1128
|
const startTimeMs = Number.isFinite(req.startTimeMs) ? req.startTimeMs : Date.now();
|
|
983
1129
|
req.startTimeMs = startTimeMs;
|
|
984
|
-
const
|
|
985
|
-
req.requestId =
|
|
1130
|
+
const explicitRequestId = normalizeRequestIdCandidate(req.requestId);
|
|
1131
|
+
req.requestId = explicitRequestId;
|
|
986
1132
|
if (req.route && config.route.normalize) {
|
|
987
1133
|
req.route = config.route.normalizer ? config.route.normalizer(req.route) : normalizeRoutePattern(req.route);
|
|
988
1134
|
}
|
|
989
1135
|
const span = spanFromTracer(tracer, spanNameFromRequest(req));
|
|
990
1136
|
const context = {
|
|
991
|
-
requestId,
|
|
1137
|
+
requestId: explicitRequestId ?? "",
|
|
992
1138
|
traceId: span?.spanContext().traceId,
|
|
993
1139
|
spanId: span?.spanContext().spanId,
|
|
994
1140
|
setUserId: (id) => {
|
|
@@ -1067,8 +1213,10 @@ function endRequest(config, ctx, res, err) {
|
|
|
1067
1213
|
const endTimeMs = Number.isFinite(res.endTimeMs) ? res.endTimeMs : Date.now();
|
|
1068
1214
|
res.endTimeMs = endTimeMs;
|
|
1069
1215
|
if (!state) {
|
|
1216
|
+
const resolvedRequestId2 = resolveFinalRequestId(config, ctx.requestId, res.headers);
|
|
1217
|
+
ctx.requestId = resolvedRequestId2;
|
|
1070
1218
|
const fallbackLog = {
|
|
1071
|
-
requestId:
|
|
1219
|
+
requestId: resolvedRequestId2,
|
|
1072
1220
|
serviceName: config.serviceName,
|
|
1073
1221
|
method: res.statusCode ? "UNKNOWN" : "UNKNOWN",
|
|
1074
1222
|
url: "",
|
|
@@ -1079,12 +1227,19 @@ function endRequest(config, ctx, res, err) {
|
|
|
1079
1227
|
return fallbackLog;
|
|
1080
1228
|
}
|
|
1081
1229
|
const request = state.request;
|
|
1230
|
+
const resolvedRequestId = resolveFinalRequestId(
|
|
1231
|
+
config,
|
|
1232
|
+
request.requestId || ctx.requestId,
|
|
1233
|
+
res.headers
|
|
1234
|
+
);
|
|
1235
|
+
request.requestId = resolvedRequestId;
|
|
1236
|
+
ctx.requestId = resolvedRequestId;
|
|
1082
1237
|
const capture = resolveCapture(config.capture, state.captureOverride);
|
|
1083
1238
|
const redaction = resolveRedaction(config.redaction, state.redactionOverride);
|
|
1084
1239
|
const route = request.route;
|
|
1085
1240
|
const url = sanitizeLogString(request.url);
|
|
1086
1241
|
const log = {
|
|
1087
|
-
requestId:
|
|
1242
|
+
requestId: resolvedRequestId,
|
|
1088
1243
|
traceId: state.span?.spanContext().traceId,
|
|
1089
1244
|
spanId: state.span?.spanContext().spanId,
|
|
1090
1245
|
serviceName: config.serviceName,
|
|
@@ -1111,7 +1266,16 @@ function endRequest(config, ctx, res, err) {
|
|
|
1111
1266
|
const span = state.span;
|
|
1112
1267
|
if (span) {
|
|
1113
1268
|
try {
|
|
1114
|
-
|
|
1269
|
+
const clientAddressHeaders = redactHeaders(request.headers, redaction);
|
|
1270
|
+
setRequestAttributes(
|
|
1271
|
+
span,
|
|
1272
|
+
{
|
|
1273
|
+
...request,
|
|
1274
|
+
headers: clientAddressHeaders,
|
|
1275
|
+
redactionReplacement: redaction.replacement
|
|
1276
|
+
},
|
|
1277
|
+
redacted.url
|
|
1278
|
+
);
|
|
1115
1279
|
setRequestIdAttribute(span, redacted.requestId);
|
|
1116
1280
|
span.setAttribute("service.name", config.serviceName);
|
|
1117
1281
|
if (redacted.statusCode != null) {
|
|
@@ -1152,22 +1316,40 @@ function endRequest(config, ctx, res, err) {
|
|
|
1152
1316
|
}
|
|
1153
1317
|
return redacted;
|
|
1154
1318
|
}
|
|
1155
|
-
function
|
|
1156
|
-
|
|
1157
|
-
|
|
1319
|
+
function resolveFinalRequestId(config, explicitRequestId, responseHeaders) {
|
|
1320
|
+
const explicit = normalizeRequestIdCandidate(explicitRequestId);
|
|
1321
|
+
if (explicit) {
|
|
1322
|
+
return explicit;
|
|
1158
1323
|
}
|
|
1159
|
-
const
|
|
1160
|
-
const headerValue = headers[headerName];
|
|
1324
|
+
const headerValue = resolveHeaderRequestId(config.requestId.header, responseHeaders);
|
|
1161
1325
|
if (headerValue) {
|
|
1162
|
-
|
|
1163
|
-
|
|
1164
|
-
|
|
1326
|
+
return headerValue;
|
|
1327
|
+
}
|
|
1328
|
+
return uuidv7();
|
|
1329
|
+
}
|
|
1330
|
+
function resolveHeaderRequestId(headerName, headers) {
|
|
1331
|
+
if (!headers) {
|
|
1332
|
+
return void 0;
|
|
1333
|
+
}
|
|
1334
|
+
const target = headerName.toLowerCase();
|
|
1335
|
+
for (const [name, value] of Object.entries(headers)) {
|
|
1336
|
+
if (name.toLowerCase() !== target) {
|
|
1337
|
+
continue;
|
|
1338
|
+
}
|
|
1339
|
+
const entry = Array.isArray(value) ? value[0] : value;
|
|
1340
|
+
const normalized = normalizeRequestIdCandidate(entry);
|
|
1341
|
+
if (normalized) {
|
|
1342
|
+
return normalized;
|
|
1165
1343
|
}
|
|
1166
1344
|
}
|
|
1167
|
-
|
|
1168
|
-
|
|
1345
|
+
return void 0;
|
|
1346
|
+
}
|
|
1347
|
+
function normalizeRequestIdCandidate(value) {
|
|
1348
|
+
if (!value) {
|
|
1349
|
+
return void 0;
|
|
1169
1350
|
}
|
|
1170
|
-
|
|
1351
|
+
const trimmed = value.trim();
|
|
1352
|
+
return trimmed ? trimmed : void 0;
|
|
1171
1353
|
}
|
|
1172
1354
|
function resolveCapture(base, override) {
|
|
1173
1355
|
if (!override) {
|