feat(observability): direct-to-cloud OTLP with TLS + auth headers - #218
Conversation
|
Note Reviews pausedIt looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the Use the following commands to manage reviews:
Use the checkboxes below for quick actions:
📝 WalkthroughWalkthroughThis PR removes WaveHouse's bespoke OTLP endpoint and header configuration, delegating all endpoint/TLS/authentication setup to the OpenTelemetry SDK's standard environment variables. Exporters are initialized without explicit endpoints; tests, fixtures, and documentation are updated to use OTEL_EXPORTER_OTLP_* env vars, and test utilities gain TLS and gRPC metadata capture. ChangesSDK-Delegated OTLP Configuration
🎯 3 (Moderate) | ⏱️ ~25 minutes ✨ Finishing Touches🧪 Generate unit tests (beta)
✨ Simplify code
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
|
📚 Docs preview is live → https://cca44c30-wavehouse-docs.wave-rf.workers.dev |
|
Hey @taitelee — I went deeper on this one (plus some research into what the OTel Go SDK gives us out of the box) and want to capture it all in one place so we can steer toward as little custom code as possible. Your TL;DR: Almost all of the endpoint/TLS/header plumbing is something the SDK already does natively via the standard What the SDK already does for us
Refs: otlptracegrpc doc.go, OTLP exporter spec. ( Concrete items1. 2. 3. Self-signed / custom-CA gap. Prod TLS is now system-roots-only, and the trust-override hook is 4. PR description is stale. It still advertises per-signal DirectionLet's lean on the standard One trade-off to weigh: delegating means we inherit the SDK's fail-soft behavior — a malformed header gets logged via the OTel error handler and skipped, not fatal at boot. We'd lose the "refuse to start with bad auth config" property you built. If you feel strongly about keeping fail-fast, the move is a thin validated pass-through — validate the value at boot, then hand it straight to the SDK with matching (percent-decode) semantics — rather than a separate reimplementation. I lean toward minimal code + accepting fail-soft, but I'm open if you want to keep the boot check. Your call on that one. None of this touches the |
Resolved conflicts: - AGENTS.md: adopted main's slimmed invariant index; re-grafted the OTLP scheme-sniffing/headers/ParseOTelHeaders fact into item 15. - docs/.../deployment.md: kept the scheme-aware/headers paragraph, with main's Starlight link style (anchored to #otel). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
… vars, drop WH_OTEL_ADDR/HEADERS + custom validation
…xporter (otlploggrpc v0.19 drops them)
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Code Coverage OverviewLanguages: Go GoThe overall coverage in the Show a code coverage summary of the most impacted files.
Code Coverage is in Public Preview. Learn more and provide us with your feedback. |
Summary
Exports traces/metrics/logs straight to a cloud OTLP gateway (Honeycomb, Grafana Cloud) with no sidecar collector to terminate TLS or inject auth. Closes #97.
The endpoint, TLS, custom/private CA, mutual TLS, and per-RPC auth headers are all configured through the OpenTelemetry SDK's standard
OTEL_EXPORTER_OTLP_*environment variables — the same vars every Honeycomb / Grafana Cloud quickstart already documents.InitProviderpasses no endpoint/header options and lets the SDK read the env, so WaveHouse owns essentially no config-translation surface of its own.OTEL_EXPORTER_OTLP_ENDPOINT(and the per-signal_TRACES_/_METRICS_/_LOGS_ENDPOINToverrides). Anhttps://URL selects TLS with system root CAs;http://or a barehost:portstays plaintext. Defaultlocalhost:4317.OTEL_EXPORTER_OTLP_CERTIFICATEtrusts a private CA;OTEL_EXPORTER_OTLP_CLIENT_CERTIFICATE/_CLIENT_KEYenable mTLS.OTEL_EXPORTER_OTLP_HEADERS(SDK-parsed, percent-decoded per the OTLP spec) carries cloud auth as gRPC metadata on every signal.What this removed (vs. the earlier revisions of this PR)
The first cut shipped a WaveHouse-specific translation layer; review steered it toward delegating to the SDK instead. Gone now: the
otel.addr/WH_OTEL_ADDRandotel.headers/WH_OTEL_HEADERSkeys, the per-signalWH_OTEL_{TRACES,METRICS,LOGS}_ADDRoverrides, the custom header parser and its fail-loud boot validation, the TLS 1.3 floor, andendpoint.go(schemeURL/ParseEndpoint). SetOTEL_EXPORTER_OTLP_ENDPOINTin place ofWH_OTEL_ADDR. The per-signal enable gates and sample-rate knobs (otel.enabled,otel.traces.sample_rate, …) are unchanged.Trade-off — fail-soft, by design. Delegating means we inherit the SDK's behavior: a malformed
OTEL_EXPORTER_OTLP_HEADERSvalue is logged via the OTel error handler and skipped, not fatal at boot. We deliberately gave up the "refuse to start with bad auth config" property in exchange for zero parser-parity surface.The one piece of WaveHouse glue:
logExporterTLSOptionsThe pinned gRPC logs exporter (
otlploggrpcv0.19) readsOTEL_EXPORTER_OTLP_[LOGS_]CERTIFICATE/_CLIENT_CERTIFICATE/_CLIENT_KEYinto its config but never wires that*tls.Configinto the gRPC dial — itsnewGRPCDialOptionsonly honors the programmaticWithTLSCredentials, otherwise defaulting to system roots. So a custom CA or mTLS supplied via env would silently fall back to system roots for logs only, while traces/metrics(
otlptracegrpc/otlpmetricgrpcv1.43) apply the same env vars correctly.logExporterTLSOptionsrebuilds the credentials from those standard env vars and hands them to the log exporter viaWithTLSCredentials, so custom-CA + mTLS workuniformly across all three signals. It returns
nilwhen no custom trust material is set, leaving the public-CA path fully delegated to the SDK. (Confirmed still required as ofotlploggrpcv0.20 — a version bump alone doesn't fix it; track upstream before dropping the shim.)Datadog
Datadog has no public direct-to-cloud OTLP endpoint; its supported path remains the local DDOT Collector embedded in the Datadog Agent, reached as a plaintext receiver. See the deployment guide.
Test plan
Related Issues
Closes #97