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, kernel_otlp_export_failures_total, kernel_otlp_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. Categorized as page (produced by the CDP monitor, captured only while the page category is enabled).

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 is tracked in Send instance name as x-api-key to the OTLP relay #316.

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.

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), metrics collector, converter severities, and the Inspector.targetCrashed handler.

Live test results

Verified full-stack against the headless image + a real dockerized OpenTelemetry collector, driving the real telemetry API and a real Chromium over CDP:

  • Batch knobs: custom BTEL_OTLP_* values surfaced in the boot config (otlp_max_queue_size=512 otlp_export_interval=500ms otlp_export_timeout=30s); export shows available, not started, at boot.
  • Export toggle: GET /telemetry → 404 at boot; PUT with export.otlp.enabled:true → 201 echoing it. With export off but page/network capture on, exported_total froze (10 → 10) and the collector received nothing new; re-enabling resumed export (10 → 28), confirming the controller rebuilds the one-shot writer.
  • Renderer crash: a real chrome://crash produced a page_crashed record at the collector with category=page, url=chrome://crash/, and SeverityText: ERROR.
  • Converter fidelity: network_response carried promoted attributes (http.request.method, url.full, http.response.status_code=200); screenshot/monitor categories never reached the collector.
  • Metrics: /metrics served kernel_otlp_records_dropped_total 0, kernel_otlp_export_failures_total 0, kernel_otlp_records_exported_total 28.

🤖 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>
@archandatta
archandatta force-pushed the archand/kernel-1596/otlp-export-followups branch from 643f503 to 5e56d6a Compare July 17, 2026 13:11
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