Skip to content

OTLP browser telemetry export: follow-up improvements (KERNEL-1596)#317

Draft
archandatta wants to merge 9 commits into
mainfrom
archand/kernel-1596/otlp-export-followups
Draft

OTLP browser telemetry export: follow-up improvements (KERNEL-1596)#317
archandatta wants to merge 9 commits into
mainfrom
archand/kernel-1596/otlp-export-followups

Conversation

@archandatta

@archandatta archandatta commented Jul 16, 2026

Copy link
Copy Markdown
Contributor

tldr

Follow-up improvements to the in-VM OTLP browser-telemetry exporter (KERNEL-1596), post #308. Independent, reviewable commits. Off-by-default export is preserved; nothing changes for existing sessions unless the new toggle/knobs are set.

What changed

  1. Externalize batch knobsBTEL_OTLP_MAX_QUEUE_SIZE (2048), BTEL_OTLP_EXPORT_INTERVAL (1s), BTEL_OTLP_EXPORT_TIMEOUT (30s). Defaults match the OTel SDK's, so behavior is unchanged unless set; validated as > 0.
  2. Per-session export toggle — new export.otlp.enabled on the telemetry API. Export is off by default and gated on the toggle, independent of whether an export destination is configured, so an always-injected relay does not generate work that gets dropped. The writer moves under a runtime-toggleable controller; toggling is best-effort (never fails a telemetry apply).
  3. Drop / failure / exported metrics — queue-overflow drops (previously log-only) plus export failures and exported counts as Prometheus counters (kernel_otlp_records_dropped_total, _export_failures_total, _records_exported_total), owned above the writer so they stay monotonic across export toggles.
  4. Crash/OOM severityservice_crashed and system_oom_kill now map to ERROR in the OTLP converter (were INFO), so consumers can alert on them.
  5. Renderer-crash event — detect Inspector.targetCrashed (an "Aw, Snap!" renderer crash that leaves the browser process alive, so no service_crashed fires) and emit a page_crashed event, mapped to ERROR.

Scope notes

  • Two of the six ticket items are intentionally not code here: the concurrency-scaled resilience benchmark (measurement, depends on the knobs + drop metric landing first) and the event-reshape-for-relay-routing item (parked pending the durability decision).
  • Based on main (which already has Add in-VM OTLP telemetry export sink #308 + the metrics endpoint), keeping main's existing export auth wiring; the x-api-key swap remains Send instance name as x-api-key to the OTLP relay #316's concern.

Generated code (oapi.go)

The oapi.go diff looks large but decomposes as: ~727 lines are the embedded-spec gzip blob (the whole spec is embedded, so any spec change rewrites it — same as #308), ~105 lines are the genuinely new generated types (page_crashed + export config + union accessors), and 4 lines are an oapi-codegen naming side-effect: adding a second standalone page-category event renames the existing BrowserPageTabOpenedEventCategoryPage const to Page. That constant isn't referenced anywhere in-repo, and regenerating main's own spec with the pinned toolchain reproduces main's oapi.go exactly (0 diff), so this is faithful make oapi-generate output, not hand-editing or transitive drift.

Testing

  • go build ./..., go vet ./..., and the full unit suite (22 packages) pass.
  • Unit tests: export toggle (on/off, default-off, no-endpoint no-op, clear-stops-export), config defaults/validation, drop-counting handler, a real-SDK drop test that forces a batch-queue overflow against a local hung listener (so CI catches an SDK drop-message rename instead of silently zeroing the metric), metrics collector, converter severities, and the Inspector.targetCrashed handler.
  • Verified live during development against a real dockerized OpenTelemetry collector: crash/OOM land as ERROR, screenshots are excluded, promoted attributes appear, export counters advance, and a forced queue overflow reported dropped=1980.

Review fixes applied

  • Scrubbed internal deployment detail ("on the VM") from the public export spec descriptions.
  • Export reconcile now logs via the request context logger and drains with context.WithoutCancel so a toggle-off outlives the request.
  • page_crashed still emits (and warns) if a crash fires on an untracked session.
  • Promoted the drop-metric coverage to a real-SDK unit test that runs every CI build (removed the build-tagged docker live test; its coverage is now unit-side).

🤖 Generated with Claude Code

archandatta and others added 9 commits July 16, 2026 12:53
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Export is off by default and gated on the toggle, independent of whether
an endpoint is provisioned, so an always-injected relay does not export
by default. Writer lifecycle moves under a runtime-toggleable controller.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Surfaces queue-overflow drops (previously log-only) plus export failures and
exported counts as Prometheus counters, owned above the writer so they stay
monotonic across export toggles.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Detects Inspector.targetCrashed (an 'Aw, Snap!' renderer crash that leaves the
browser process alive, so no service_crashed fires) and emits a page_crashed
event, mapped to ERROR severity in the OTLP converter.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Exercises the export path end-to-end against a real dockerized collector:
severity mapping, category exclusion, promoted attributes, export counters,
and a forced queue overflow proving the drop metric. Run with -tags livetest.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…, crash guard

- Drop 'on the VM' from the public export spec descriptions.
- Thread request ctx into export reconcile; log via the context logger, and
  drain with context.WithoutCancel so a toggle-off outlives the request.
- Still emit page_crashed (and warn) if a crash fires on an untracked session.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
… test

Forces a real batch-queue overflow against a local hung listener so CI
exercises the SDK->global-logger->counter chain every run; an SDK message
rename now fails here instead of silently zeroing the metric. Removes the
build-tagged docker live test (its coverage is now unit-side).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant