UNPKG

@dash0/sdk-web

Version:

Dash0's Web SDK to collect telemetry from end-users' web browsers

86 lines (85 loc) 3.47 kB
import { doc } from "../globals"; import { perf } from "../globals"; const TRACE_PARENT_HEADER = "traceparent"; /** * See https://www.w3.org/TR/trace-context/#traceparent-header */ const w3cTraceparentFormat = /^00-([a-f0-9]{32})-([a-f0-9]{16})-[0-9]{1,2}$/; export function getTraceContextForPageLoad() { const match = getTraceparentFromMetaElement().match(w3cTraceparentFormat) || getTraceparentFromNavigationTiming().match(w3cTraceparentFormat); if (match) { return { traceId: match[1], spanId: match[2], }; } return undefined; } function getTraceparentFromMetaElement() { return (Array.from(doc?.getElementsByTagName("meta") ?? []) .find((e) => e.getAttribute("name")?.toLowerCase() === TRACE_PARENT_HEADER) ?.content.trim() || ""); } function getTraceparentFromNavigationTiming() { const nt = perf.getEntriesByType("navigation")[0]; if (!nt) { return ""; } if (!nt.serverTiming) { return ""; } return getTraceparentFromServerTiming(nt.serverTiming); } function getTraceparentFromServerTiming(serverTimings) { for (const serverEntry of serverTimings) { if (serverEntry.name === TRACE_PARENT_HEADER) { return serverEntry.description.trim(); } } return ""; } export function addW3CTraceContextHttpHeaders(fn, ctx, span) { /** * W3C Traceparent header. * General format is ${version}-${trace-id}-${parent-id}-${trace-flags} * * The only spec'd version is currently 00 * Trace flags are an 8 bit field of bit flags: * Sampled: 00000001 - Should only be set if a definite decision to record the trace was made. * If set downstream processors should also record the trace * Random Trace ID: 00000010 - IF set the component guarantees that the seven right most bytes of the trace-id * are randomly generated. Downstream processors are then able to rely on this for technical things like shard keys. * * NOTE: For now we just send the "sampled" flag because not all components support the random trace ID flag. * * References: * https://www.w3.org/TR/trace-context-2/#traceparent-header * https://www.w3.org/TR/trace-context-2/#trace-flags * https://www.w3.org/TR/trace-context-2/#random-trace-id-flag */ fn.call(ctx, "traceparent", `00-${span.traceId}-${span.spanId}-01`); } export function addXRayTraceContextHttpHeaders(fn, ctx, span) { /** * AWS X-Ray trace header. * General format is Root=${trace-id};Parent=${span-id};Sampled=${sampling-flag} * * Converts W3C trace ID format to X-Ray format: * W3C: 4efaaf4d1e8720b39541901950019ee5 (32 hex chars) * X-Ray: 1-4efaaf4d-1e8720b39541901950019ee5 (1-{8chars}-{24chars}) * * References: * https://docs.aws.amazon.com/xray/latest/devguide/xray-concepts.html#xray-concepts-tracingheader */ const xrayTraceId = convertW3CTraceIdToXRay(span.traceId); const xrayHeader = `Root=${xrayTraceId};Parent=${span.spanId};Sampled=1`; fn.call(ctx, "X-Amzn-Trace-Id", xrayHeader); } function convertW3CTraceIdToXRay(w3cTraceId) { // X-Ray trace ID format: 1-{timestamp}-{unique-id} // Split the 32-char W3C trace ID into 8-char timestamp and 24-char unique ID const timestamp = w3cTraceId.substring(0, 8); const uniqueId = w3cTraceId.substring(8, 32); return `1-${timestamp}-${uniqueId}`; }