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

+31
View File
@@ -19,6 +19,28 @@ import (
"go.opentelemetry.io/collector/pdata/ptrace"
)
// checkIngest applies the shared ingest rate limit and, if configured, the
// ingest key check. It writes an error response and returns false when the
// request should be rejected.
func (c *Collector) checkIngest(w http.ResponseWriter, r *http.Request) bool {
if !c.ingestLimiter.Allow(clientIP(r)) {
http.Error(w, "too many requests, slow down", http.StatusTooManyRequests)
return false
}
if c.ingestKey == "" {
return true
}
key := r.Header.Get("X-Otel-Ingest-Key")
if key == "" {
key = r.URL.Query().Get("key")
}
if key != c.ingestKey {
http.Error(w, "invalid or missing ingest key", http.StatusUnauthorized)
return false
}
return true
}
// HandleTraces handles OTLP trace requests.
func (c *Collector) HandleTraces(w http.ResponseWriter, r *http.Request) {
log.Printf("Received traces request: method=%s, content-type=%s", r.Method, r.Header.Get("Content-Type"))
@@ -26,6 +48,9 @@ func (c *Collector) HandleTraces(w http.ResponseWriter, r *http.Request) {
http.Error(w, "method not allowed", http.StatusMethodNotAllowed)
return
}
if !c.checkIngest(w, r) {
return
}
body, err := io.ReadAll(r.Body)
if err != nil {
@@ -71,6 +96,9 @@ func (c *Collector) HandleMetrics(w http.ResponseWriter, r *http.Request) {
http.Error(w, "method not allowed", http.StatusMethodNotAllowed)
return
}
if !c.checkIngest(w, r) {
return
}
body, err := io.ReadAll(r.Body)
if err != nil {
@@ -112,6 +140,9 @@ func (c *Collector) HandleLogs(w http.ResponseWriter, r *http.Request) {
http.Error(w, "method not allowed", http.StatusMethodNotAllowed)
return
}
if !c.checkIngest(w, r) {
return
}
body, err := io.ReadAll(r.Body)
if err != nil {