diff --git a/CHANGELOG.md b/CHANGELOG.md index 17c4c95..0998085 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,6 +9,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Added +- ipx-web sends a trace span for each request when `WEB_TRACING=on`, continuing the page's trace into ipx, so one trace runs from the browser through Caddy to ipx (#213). - The Grafana dashboard is laid out by container: an overview of all three, Tower's load, CPU, memory and disks, then ipx-web (from its new request log), ipx's API, worker and process, and the directory, each with its own warnings (#210). - `ipx-directory`, a directory of public podcasts that ipx servers share: each sends the public feeds its people subscribe to, and any server with a token browses them. Tokens are in its config file, each read-only, read-write or admin, and revoked one at a time (#204). diff --git a/CLAUDE.md b/CLAUDE.md index 22987ca..c286b30 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -273,6 +273,13 @@ set `version` to the next patch with `-dev` (after 0.9.0, `0.9.1-dev`), so a bui in the logo's tooltip instead of claiming to be the last release. The release that follows can still be a minor or major one; `-dev` only says the work comes after `X.Y.Z`. +**Traces first, logs second.** Anything that does work (a service, a handler, a job, a call to +another service) gets spans, and passes `traceparent` on to whatever it calls, so one trace in +Tempo follows a request or a job across ipx-web, ipx and the directory. A trace shows where the +time went and what called what; a log line only that something happened. Log what a trace cannot +carry: events worth counting on the dashboard, warnings and errors. A new service or route without +traces is not finished. + Deliberate simplifications get a `ponytail:` comment naming the ceiling and the upgrade path, e.g. `// ponytail: global connection mutex, move to a pool if feed count makes it contend`. diff --git a/docker-compose.yml b/docker-compose.yml index e126812..edf2647 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -38,6 +38,11 @@ services: # Behind Cloudflare Access only: where cloudflared's requests come from, the one address # whose Cf-Access-* headers are passed on. docs/sso.md says how to find it. # TUNNEL_PEER: "192.168.64.1" + # Traces to an OpenTelemetry collector, a span for each request, continued into ipx: + # WEB_TRACING: "on" + # OTEL_EXPORTER_OTLP_ENDPOINT: "http://collector:4318" + # OTEL_EXPORTER_OTLP_PROTOCOL: "http/protobuf" + # OTEL_SERVICE_NAME: "ipx-web" ports: - "8099:8080" # the web UI depends_on: diff --git a/web/Caddyfile b/web/Caddyfile index 72d7939..cef210e 100644 --- a/web/Caddyfile +++ b/web/Caddyfile @@ -2,6 +2,10 @@ # so the session cookie, live updates and Cloudflare Access work as they did when ipx served it. # IPX_UPSTREAM where ipx is, host:port (ipx:8099) # WEB_BIND where to listen (:8080) +# WEB_TRACING on: a span for each request to OpenTelemetry (OTEL_EXPORTER_OTLP_ENDPOINT, +# OTEL_EXPORTER_OTLP_PROTOCOL, OTEL_SERVICE_NAME), continuing the page's traceparent +# and passing it to ipx, so one trace runs browser, Caddy, ipx (#213). Off: none, +# and no export failing every few seconds where there is nothing to send to. # TUNNEL_PEER the one address whose Cf-Access-* headers are passed on: where cloudflared's # requests come from. Nobody else's are, so nobody else can claim to be signed in # by Cloudflare. Unset passes none. @@ -24,7 +28,17 @@ } } +(tracing-on) { + tracing { + span ipx-web + } +} +(tracing-off) { +} + http://{$WEB_BIND::8080} { + import tracing-{$WEB_TRACING:off} + root * {$WEB_ROOT:/srv} # One JSON line a request on stdout, for Loki and the dashboard's Page row (#210). Not the