otlpTarget
Where OpenTelemetry's variables say to send traces: OTEL_EXPORTER_OTLP_TRACES_ENDPOINT as it is, or
OTEL_EXPORTER_OTLP_ENDPOINT with /v1/traces; headers (an API key) from OTEL_EXPORTER_OTLP_HEADERS
(key=value,…). tcm sends OTLP as JSON over HTTP, so gRPC is a problem to say; undefined when nothing's set.
export function otlpTarget( env: Record<string, string | undefined>, ): { url: string; headers: Record<string, string> } | { problem: string } | undefined { const traces = env.OTEL_EXPORTER_OTLP_TRACES_ENDPOINT?.trim(); const base = env.OTEL_EXPORTER_OTLP_ENDPOINT?.trim(); if (!traces && !base) return undefined; const protocol = env.OTEL_EXPORTER_OTLP_TRACES_PROTOCOL ?? env.OTEL_EXPORTER_OTLP_PROTOCOL; if (protocol === "grpc") return { problem: "traces aren't sent over gRPC: tcm sends OTLP as JSON over HTTP (an endpoint's /v1/traces)", }; const headers: Record<string, string> = {}; for (const part of ( env.OTEL_EXPORTER_OTLP_TRACES_HEADERS ?? env.OTEL_EXPORTER_OTLP_HEADERS ?? "" ).split(",")) { const i = part.indexOf("="); if (i <= 0) continue; const raw = [part.slice(0, i).trim(), part.slice(i + 1).trim()] as const; let key: string; let value: string; try { [key, value] = raw.map((s) => decodeURIComponent(s)) as [string, string]; } catch { [key, value] = raw; } headers[key] = value; } return { url: traces || `${base!.replace(/\/+$/, "")}/v1/traces`, headers }; }