Skip to main content

Observability config

The env vars and flags that turn on logs, metrics, and error tracking — and what each one routes where.

3 min read

Tale ships three observability seams: stdout logs from every container, Prometheus-format metrics behind a bearer token, and optional Sentry error reporting. The defaults are loud enough to spot a crash and quiet enough to fit in a single host's journald; the production knobs below add the structured paths your existing monitoring stack can scrape. None of the three send anything off-host unless you configure them to.

This page covers the server-side switches. The operator-facing alert playbook lives in Operations, and the symptom-first lookup in Troubleshooting.

Logs

Every container writes structured JSON or console logs to stdout, captured by Docker's default json-file driver with a 10 MB-per-file, 3-file rotation. The log destination is a function of how you deploy:

  • Single host with journald — journalctl -u docker carries the lot.
  • Single host without journald — docker compose logs -f <service> for live tailing.
  • Aggregator (Loki, Vector, Fluent Bit) — point the Docker logging driver at it via daemon.json.

Tale does not ship a log shipper. The driver swap is the supported integration point.

Metrics

The Caddy proxy exposes three metrics paths gated by a single bearer token:

PathSourceWhat's inside
/metrics/platformtale-platformHTTP latency, route counters, Node process metrics, response-time SLA target gauges
/metrics/convextale-convex261 built-in Convex metrics, plus the RAG and crawl timings
/metrics/sla-rulestale-platformGenerated Prometheus recording + alerting rules for the response-time SLAs

Knowledge work (RAG search, document ingestion, web crawling) runs inside the Convex backend now, so its timings ride the /metrics/convex series rather than a separate endpoint. Set METRICS_BEARER_TOKEN in .env to enable these endpoints; leave it unset to keep them returning 401 to every request. The /metrics/sla-rules path is a read-only YAML rules file you load into Prometheus, not a scrape target — the thresholds it carries are documented in Operations. Anything other than the listed paths returns 401 too, so a misrouted scraper does not accidentally see the platform's internal health endpoints.

A working Prometheus scrape stanza:

yaml
scrape_configs:
  - job_name: tale-platform
    scheme: https
    metrics_path: /metrics/platform
    authorization:
      credentials: <METRICS_BEARER_TOKEN>
    static_configs:
      - targets: ['tale.example.com']

Duplicate the stanza per path, or use a single job with relabel_configs if you prefer.

Error tracking with Sentry

Sentry is opt-in via SENTRY_DSN. Self-hosted GlitchTip and Bugsink work too, since they speak the same DSN format. The platform and the convex containers both read the DSN and tag events with the container name.

bash
# .env
SENTRY_DSN=https://your-key@your-sentry-host/project-id
SENTRY_TRACES_SAMPLE_RATE=0.1

The sample rate caps performance traces; leave it unset for the default 1.0 in development and tighten it (0.05–0.2) in production. Stack frames are sent unredacted, so point the DSN at infrastructure you control if your error payloads are sensitive.

What does not ship yet

OpenTelemetry traces are not built into the containers. The data is reachable indirectly — Convex action durations and HTTP route timings come through the Prometheus metrics — but there is no OTLP exporter on the box today. If you need full trace export, run an OpenTelemetry Collector alongside Tale and scrape the Prometheus endpoints from it.

Where this fits

The three seams above are the contact points with the rest of your monitoring stack; the alert thresholds and the oncall checklist live in Operations. If something is on fire right now and you need the symptom-first index, jump to Troubleshooting.

© 2026 Tale by Ruler GmbH — ISO 27001 & SOC 2 certified.

Tale is MIT licensed — free to use, modify, and distribute.