Skip to content

Support protobuf OTLP export (OTEL_EXPORTER_OTLP_PROTOCOL=http/protobuf) #2934

@loganrosen

Description

@loganrosen

Describe the feature or problem you'd like to solve

Copilot CLI's OpenTelemetry support (shipped in copilot monitoring, closed via #2471 / #1911 / #1565) only exports OTLP over HTTP as application/json. The standard OTEL_EXPORTER_OTLP_PROTOCOL env var is silently ignored, and COPILOT_OTEL_EXPORTER_TYPE only accepts otlp-http or file. There's no way to switch to application/x-protobuf without forking the CLI.

Confirmed empirically with a local OTLP listener and Copilot CLI 1.0.34:

  • env -u OTEL_EXPORTER_OTLP_PROTOCOL …Content-Type: application/json
  • OTEL_EXPORTER_OTLP_PROTOCOL=http/protobuf OTEL_EXPORTER_OTLP_TRACES_PROTOCOL=http/protobuf OTEL_EXPORTER_OTLP_METRICS_PROTOCOL=http/protobuf …Content-Type: application/json (identical)

User-Agent OTel-OTLP-Exporter-JavaScript/0.213.0 on both runs pins the bundled package to @opentelemetry/exporter-trace-otlp-http@0.213.0 — the JSON-only HTTP exporter. Switching to @opentelemetry/exporter-trace-otlp-proto@0.213.0 (same version, sibling package) is a near-one-line change that would make any of the three protocol env vars above take effect.

Why it matters

OTLP backends vary in what they accept on HTTP:

  • Protobuf-only or protobuf-preferred: many OTel Collectors behind strict load balancers, some enterprise telemetry ingestion paths, and specific vendor endpoints. Without a protobuf option, clients can't send to these targets from Copilot CLI at all.
  • Both: Jaeger, Grafana OTLP, Datadog, New Relic, Azure Monitor accept both formats. No regression risk if protobuf is made opt-in.

Even for backends that nominally accept JSON, some JSON parsers are non-spec-compliant in ways that silently corrupt OTLP IDs (e.g. proto3-default base64 decoding applied to OTel's spec-required hex traceId/spanId, per OTLP 1.10.0 §JSON encoding). Protobuf sidesteps that class of bug entirely because the IDs are transported as raw bytes.

Today the only workaround is a local JSON→protobuf transcoding proxy per user — real operational overhead for what is fundamentally a one-line SDK package swap.

Proposed solution

Option A (minimal): accept a new value for COPILOT_OTEL_EXPORTER_TYPE, e.g. otlp-http-proto (or otlp-http-protobuf), that selects @opentelemetry/exporter-trace-otlp-proto and @opentelemetry/exporter-metrics-otlp-proto instead of the -http variants. Same endpoint/URL semantics, just different Content-Type: application/x-protobuf.

Option B (standards-aligned): honor the standard OTEL_EXPORTER_OTLP_PROTOCOL / OTEL_EXPORTER_OTLP_TRACES_PROTOCOL / OTEL_EXPORTER_OTLP_METRICS_PROTOCOL env vars with values http/json (current default) and http/protobuf. This matches the Python OTel SDK's behavior and what users coming from other ecosystems expect. The OTel spec documents this as the canonical protocol selector: https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/protocol/exporter.md#configuration-options

Both options are small code changes — the exporter packages are designed to be interchangeable drop-ins. Option B has more future-proofing value; Option A is faster to ship.

Example

OTEL_EXPORTER_OTLP_ENDPOINT=https://my-otel-collector.example.com \
OTEL_EXPORTER_OTLP_PROTOCOL=http/protobuf \
OTEL_EXPORTER_OTLP_HEADERS="authorization=Bearer $TOKEN" \
copilot -p "hello"

Expected: OTLP POSTs leave the CLI with Content-Type: application/x-protobuf and the serialized ExportTraceServiceRequest / ExportMetricsServiceRequest protobuf messages in the body.

Additional context

Affected version: 1.0.34 (verified) — bundled npm @opentelemetry/exporter-trace-otlp-http@0.213.0.

Metadata

Metadata

Assignees

No one assigned

    Labels

    area:configurationConfig files, instruction files, settings, and environment variables
    No fields configured for Feature.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions