- Add static/otel-rum.js: a framework-free browser script that captures
uncaught errors, unhandled promise rejections and failed resource loads,
translating them into OTLP log records POSTed to the existing /v1/logs
endpoint (source: frontend attribute) so they flow through the same
history/search/issue pipeline as backend telemetry.
- Add correlation-id support: traceHeaders() (manual) and same-origin
fetch auto-instrumentation inject a W3C traceparent header, so a
frontend error and the backend spans it triggered share a trace id and
can be found together via GET /api/traces/{traceId}.
- Add CORS handling (withCORS in cmd/server/main.go) on the OTLP HTTP
endpoints, required for any browser-origin POST.
- Add an optional shared ingest key (OTEL_INGEST_KEY, via '?key=' or
X-Otel-Ingest-Key) and a per-IP rate limit (20 rps/burst 50) on OTLP
HTTP ingestion, to scope/protect a public endpoint fed by a browser
script. Verified end-to-end (CORS preflight, cross-origin POST, ingest
key enforcement, rate limiting) against a running server.
- Serve static/otel-rum.js and agents_example.md as static HTTP routes so
both the script and the agent instructions doc are fetchable directly
from the base URL.
- Ignore the separately-cloned otel-ui/ frontend repo (has its own .git;
not meant to be nested into this repo's history).
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
3.0 KiB
3.0 KiB
Improvement plan
Priority order: (1) agent endpoints, (2) recent issues for the web UI, (3) a Sentry-like frontend error collector.
Phase 1 — Agent endpoints (highest priority)
- Fix
HandleHistoryByType: it only filtered the in-memory ring buffer (capped athistorySize, default 100) instead of the persistent store, so/api/history/traces|metrics|logssilently returned far less than/api/history/searchcould see. Now routed throughSearchHistory. - Structured filters on
/api/history/searchand/api/history/wait:type=,since=,until=(unix nanoseconds), combinable with the existing free-textq=. GET /api/traces/{traceId}— assemble all entries referencing one trace id in a single call, instead of relying on substring search matching the id inside raw JSON.- Basic per-IP rate limiting on
/api/history/wait(a blocking long-poll, cheap to abuse). - Cursor-based pagination for
/api/history/search(deferred). - Machine-readable tool manifest (
/.well-known/agent-tools.jsonor an MCP server) replacingagents_example.md(deferred).
Phase 2 — Recent issues for the web UI
- Fingerprint spans with
status=ERROR/exception events and logs withseverity >= ERRORinto deduped Issues (count, firstSeen, lastSeen, sample entries, affected services), updated incrementally on ingest.internal/issues(fingerprinting/dedup) +internal/collector/issue_extract.go(OTLP field extraction). GET /api/issues,GET /api/issues/{id}.- UI "Issues" tab (lives in the separate frontend/
distproject — this repo's API is ready for it).
Phase 3 — Frontend error collector (Sentry-style)
static/otel-rum.js: captures uncaught errors,unhandledrejection, resource load failures; translates them to OTLP log records client-side and POSTs to the existing/v1/logsendpoint (so Phase 2's issue derivation picks them up for free via asource: frontendattribute). Verified end-to-end against a running server: an ingested frontend error shows up inGET /api/issuesandGET /api/traces/{traceId}.- Correlation-id injection:
traceHeaders()(manual) and auto-injection into same-originfetchcalls, using a W3Ctraceparentheader so a backend span sharing that trace id and the frontend error that triggered it show up together via/api/traces/{traceId}. - CORS support on the OTLP HTTP endpoints (
withCORSincmd/server/main.go), verified with a live cross-origin POST. - Lightweight ingest key (
OTEL_INGEST_KEY, checked viaCollector.checkIngest) for scoping noisy pages, plus a per-IP rate limit (20 rps/burst 50) on the OTLP HTTP ingestion endpoints so a runaway error loop can't hammer the collector. Not real auth. - Explicitly out of scope for v1: source map resolution, session replay, PII scrubbing (documented in README.md and the script's header comment).