ops: make OTLP telemetry export opt-in so a small-box deploy needs no collector #155

Closed
opened 2026-08-09 01:05:29 +00:00 by rosa · 1 comment
Owner

Found during a pre-production review.

Location: crates/server/src/main.rs:217 (init_telemetry), exporter built at main.rs:222
Severity: Operability friction — conflicts with "small box" goal

Problem

init_telemetry unconditionally builds an OTLP span exporter and installs a batch exporter (main.rs:222233). With no OTEL_EXPORTER_OTLP_ENDPOINT set, the OTLP HTTP exporter defaults to http://localhost:4318. A self-hoster who just wants a blog and runs no collector therefore gets a batch exporter that fails to export on every flush — recurring error/warN noise — and is effectively required to stand up a Jaeger/OTLP collector for a plain deployment.

This runs against ARCHITECTURE.md Goal #1 ("runs on a small box... little upkeep"): tracing export should be something you opt into, not mandatory boot wiring.

Suggested fix

Make OTLP export conditional on configuration:

  • Only build and install the OTLP exporter when an endpoint is configured (e.g. OTEL_EXPORTER_OTLP_ENDPOINT is present, or a VERNIER_-prefixed setting).
  • When it is not, initialize the fmt + EnvFilter layers alone so structured logging still works with zero external dependencies.

Keep the exporter path exactly as-is when an endpoint is configured — this is purely about not requiring a collector for the default single-box deployment.

Found during a pre-production review. **Location:** `crates/server/src/main.rs:217` (`init_telemetry`), exporter built at `main.rs:222` **Severity:** Operability friction — conflicts with "small box" goal ## Problem `init_telemetry` unconditionally builds an OTLP span exporter and installs a batch exporter (`main.rs:222`–`233`). With no `OTEL_EXPORTER_OTLP_ENDPOINT` set, the OTLP HTTP exporter defaults to `http://localhost:4318`. A self-hoster who just wants a blog and runs no collector therefore gets a batch exporter that fails to export on every flush — recurring error/warN noise — and is effectively required to stand up a Jaeger/OTLP collector for a plain deployment. This runs against ARCHITECTURE.md Goal #1 ("runs on a small box... little upkeep"): tracing export should be something you opt into, not mandatory boot wiring. ## Suggested fix Make OTLP export conditional on configuration: - Only build and install the OTLP exporter when an endpoint is configured (e.g. `OTEL_EXPORTER_OTLP_ENDPOINT` is present, or a `VERNIER_`-prefixed setting). - When it is not, initialize the `fmt` + `EnvFilter` layers alone so structured logging still works with zero external dependencies. Keep the exporter path exactly as-is when an endpoint *is* configured — this is purely about not requiring a collector for the default single-box deployment.
Author
Owner

This was generated by AI during triage.

Agent Brief

Category: bug
Summary: Only initialize the OTLP span exporter when an export endpoint is configured; otherwise run local logging alone, so a default single-box deploy needs no collector.

Current behavior:
Telemetry initialization at the composition root unconditionally builds an OTLP HTTP span exporter and installs it as a batch exporter alongside the fmt and EnvFilter logging layers. With no OTLP endpoint configured, the exporter defaults to http://localhost:4318; an operator who runs no collector gets a batch exporter that fails to export on every flush (recurring error/warn noise) and is effectively forced to stand up a collector for an ordinary deployment. This works against the "runs on a small box, little upkeep" goal.

Desired behavior:
OTLP export is opt-in. When an export endpoint is configured, behavior is exactly as today — the OTLP batch exporter is installed and spans are exported. When it is not configured, telemetry initializes with local logging only (fmt + EnvFilter), no OTLP exporter is built, and there is no export-failure noise. Detect the opt-in via the standard OTEL_EXPORTER_OTLP_ENDPOINT environment variable (present/non-empty = enabled); this keeps it consistent with the wider OpenTelemetry ecosystem and does not require adding a field to the typed Config. VERNIER_LOG continues to drive the filter in both modes.

Key interfaces:

  • The telemetry init routine at the composition root — currently returns the tracer provider so it can be flushed on shutdown. It must still return whatever the shutdown path needs, but with no provider/exporter constructed in the disabled case (e.g. an Option, or a no-op shutdown handle). Preserve clean shutdown: the enabled path must still flush buffered spans on exit; the disabled path has nothing to flush.
  • The subscriber registry composition — the OpenTelemetry layer is only added in the enabled case; the fmt and EnvFilter layers are always present.

Acceptance criteria:

  • With OTEL_EXPORTER_OTLP_ENDPOINT unset, the server starts, logs to stdout via fmt/EnvFilter, builds no OTLP exporter, and emits no export-failure errors.
  • With OTEL_EXPORTER_OTLP_ENDPOINT set, spans are exported over OTLP exactly as before.
  • Buffered spans are still flushed on shutdown in the enabled case; shutdown is clean (no panic, no error) in the disabled case.
  • VERNIER_LOG controls the filter in both modes.

Out of scope:

  • Adding OTLP/telemetry fields to the typed Config (env detection is sufficient).
  • Supporting non-OTLP exporters or new exporter protocols.
  • Changing the service name, resource attributes, or span content.
> *This was generated by AI during triage.* ## Agent Brief **Category:** bug **Summary:** Only initialize the OTLP span exporter when an export endpoint is configured; otherwise run local logging alone, so a default single-box deploy needs no collector. **Current behavior:** Telemetry initialization at the composition root unconditionally builds an OTLP HTTP span exporter and installs it as a batch exporter alongside the `fmt` and `EnvFilter` logging layers. With no OTLP endpoint configured, the exporter defaults to `http://localhost:4318`; an operator who runs no collector gets a batch exporter that fails to export on every flush (recurring error/warn noise) and is effectively forced to stand up a collector for an ordinary deployment. This works against the "runs on a small box, little upkeep" goal. **Desired behavior:** OTLP export is opt-in. When an export endpoint is configured, behavior is exactly as today — the OTLP batch exporter is installed and spans are exported. When it is not configured, telemetry initializes with local logging only (`fmt` + `EnvFilter`), no OTLP exporter is built, and there is no export-failure noise. Detect the opt-in via the standard `OTEL_EXPORTER_OTLP_ENDPOINT` environment variable (present/non-empty = enabled); this keeps it consistent with the wider OpenTelemetry ecosystem and does not require adding a field to the typed `Config`. `VERNIER_LOG` continues to drive the filter in both modes. **Key interfaces:** - The telemetry init routine at the composition root — currently returns the tracer provider so it can be flushed on shutdown. It must still return whatever the shutdown path needs, but with no provider/exporter constructed in the disabled case (e.g. an `Option`, or a no-op shutdown handle). Preserve clean shutdown: the enabled path must still flush buffered spans on exit; the disabled path has nothing to flush. - The subscriber registry composition — the OpenTelemetry layer is only added in the enabled case; the `fmt` and `EnvFilter` layers are always present. **Acceptance criteria:** - [ ] With `OTEL_EXPORTER_OTLP_ENDPOINT` unset, the server starts, logs to stdout via `fmt`/`EnvFilter`, builds no OTLP exporter, and emits no export-failure errors. - [ ] With `OTEL_EXPORTER_OTLP_ENDPOINT` set, spans are exported over OTLP exactly as before. - [ ] Buffered spans are still flushed on shutdown in the enabled case; shutdown is clean (no panic, no error) in the disabled case. - [ ] `VERNIER_LOG` controls the filter in both modes. **Out of scope:** - Adding OTLP/telemetry fields to the typed `Config` (env detection is sufficient). - Supporting non-OTLP exporters or new exporter protocols. - Changing the service name, resource attributes, or span content.
rosa closed this issue 2026-08-11 01:42:37 +00:00
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
rosa/vernier#155
No description provided.