Add frontend error collector, CORS/ingest guards, and static doc routes (Phase 3)
Build and Publish / Metadata (push) Successful in 2s
Build and Publish / BuildAndDeployAmd64 (push) Failing after 5s

- 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>
This commit is contained in:
developerandClaude Sonnet 5 committed 2026-09-17 10:20:42 +00:00
1 parent 0d274ff89c
commit c20a0b77f3
10 files changed
+489 -17

No files matched your search

+48
View File
@@ -120,6 +120,14 @@ Errors seen in traces (spans with an error status) and logs (severity
- `GET /` - Serves the HTML visualization interface
### Static Routes
- `GET /static/otel-rum.js` - The frontend error collector script (see
below).
- `GET /agents_example.md` - Serves this repo's agent instructions doc
directly, so an AI agent can fetch it from the base URL before making any
API calls.
## Usage
### Sending Telemetry Data
@@ -156,8 +164,48 @@ curl http://localhost:8080/api/history/traces
This returns JSON arrays of historical entries with timestamps.
### Frontend Error Collector (`static/otel-rum.js`)
A framework-free browser script that captures uncaught errors, unhandled
promise rejections and failed resource loads (img/script/link), and ships
them as OTLP log records to the existing `/v1/logs` endpoint - so they flow
through the same history/search/issue pipeline as backend telemetry, tagged
`source: frontend`.
```html
<script src="https://otel.k6n.net/static/otel-rum.js"></script>
<script>
var rum = OtelRUM.init({ serviceName: "my-web-app" });
// Inject a W3C traceparent header into any HTTP client so a backend span
// (if the service is OTel-instrumented) shares this request's trace id -
// then GET /api/traces/{traceId} shows the frontend error and backend
// spans for the same request together.
fetch("/api/orders", { headers: rum.traceHeaders() });
// Manual error reporting.
try { risky(); } catch (err) { rum.captureException(err); }
</script>
```
`fetch` is auto-instrumented by default (same-origin requests only) to
inject `traceparent` and record request/response breadcrumbs; this can be
disabled via `injectTraceHeaders: false` / `autoInstrumentFetch: false`.
Out of scope for v1: source map resolution (stack traces stay minified),
session replay, PII scrubbing - don't route sensitive data through
breadcrumbs or attributes.
## Configuration
- `OTELLOG_PATH` - path to the persistent telemetry log file (default
`otel-agent.log`).
- `OTEL_INGEST_KEY` - optional shared key required (via `?key=` or the
`X-Otel-Ingest-Key` header) on `/v1/traces`, `/v1/metrics` and `/v1/logs`
over HTTP. Unset by default (no key required). This is meant to
scope/rate-limit a public ingest endpoint fed by a browser script, not to
provide real authentication - pair it with the built-in per-IP rate
limiting on those endpoints if the endpoint is public.
Currently, the history buffer size is hardcoded to 100 entries. This can be made configurable in future versions.
## Development