Skip to content

OTLP HTTP Exporter sends to / instead of /v1/{signal} paths #15581

@tobilg

Description

@tobilg

What happened?

Description

When using the OTLP HTTP protocol with a custom endpoint, telemetry data is sent to the root path (/) instead of the standard OTLP paths (/v1/traces, /v1/metrics, /v1/logs).

Configuration

~/.gemini/settings.json:

{
  "telemetry": {
    "enabled": true,
    "target": "local",
    "useCollector": true,
    "otlpEndpoint": "http://localhost:4318",
    "otlpProtocol": "http",
    "logPrompts": true
  }
}

Environment variables (required to fix separate interval/timeout bug):

export OTEL_METRIC_EXPORT_TIMEOUT=10000
export OTEL_LOGS_EXPORT_TIMEOUT=5000

Expected Behavior

Per OTLP/HTTP specification, requests should be sent to:

  • POST http://localhost:4318/v1/traces
  • POST http://localhost:4318/v1/metrics
  • POST http://localhost:4318/v1/logs

Actual Behavior

All telemetry is sent to:

  • POST http://localhost:4318/

This results in 404 errors on standard OTLP collectors.

Example request captured:

POST / 404 [Content-Type: application/json, Proto: HTTP/1.1]
Body: {"resourceMetrics":[{"resource":{"attributes":[...]},...}]}

Root Cause

In packages/core/src/telemetry/sdk.ts, the HTTP exporters are configured with the url parameter:

spanExporter = new OTLPTraceExporterHttp({
  url: parsedEndpoint,
});

The parseOtlpEndpoint() function returns the full URL via url.href, which adds a trailing slash:

  • Input: http://localhost:4318
  • Output: http://localhost:4318/

When the url parameter is explicitly set, the OpenTelemetry SDK uses it verbatim and does not append the signal-specific paths. The SDK only appends /v1/traces, /v1/metrics, /v1/logs when no url is provided.

Suggested Fix

Append the signal-specific paths when constructing the exporters:

spanExporter = new OTLPTraceExporterHttp({
  url: `${parsedEndpoint}v1/traces`,
});
logExporter = new OTLPLogExporterHttp({
  url: `${parsedEndpoint}v1/logs`,
});
metricReader = new PeriodicExportingMetricReader({
  exporter: new OTLPMetricExporterHttp({
    url: `${parsedEndpoint}v1/metrics`,
  }),
  exportIntervalMillis: 10000,
});

Note: Since parseOtlpEndpoint() already returns a URL with trailing slash for HTTP, concatenation works directly.

Environment

  • Gemini CLI version: latest (installed via npm)
  • Node.js: v22.12.0
  • OS: macOS (arm64)

What did you expect to happen?

When specifying the http endpoint to http://localhost:4318, that the data is being sent to the appropriate OTLP-conform endpoints automatically.

Client information

Client Information

Run gemini to enter the interactive CLI, then run the /about command.

> /about
About Gemini CLI                                                                                                                                                                 │
│                                                                                                                                                                                  │
│ CLI Version                                                   0.22.2                                                                                                             │
│ Git Commit                                                    9bc9a3192                                                                                                          │
│ Model                                                         auto-gemini-2.5                                                                                                    │
│ Sandbox                                                       no sandbox                                                                                                         │
│ OS                                                            darwin                                                                                                             │
│ Auth Method                                                   OAuth

Login information

Personal OAuth

Anything else we need to know?

No response

Metadata

Metadata

Assignees

No one assigned

    Labels

    area/enterpriseIssues related to Telemetry, Policy, Quota / Licensingworkstream-rollupLabel used to tag epics and features that are associated with one of the three primary workstreams🔒 maintainer only⛔ Do not contribute. Internal roadmap item.

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions