otlpTarget

tcmts.cli.web.otlpTarget · #johhfh6s · term · runs anywhere

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 };
}

used by