What you can export
Manage destinations from Settings, Data export in the dashboard or with
levelrail-cli export destinations.
Prometheus scrape
GET /metrics returns the Prometheus text format. It is gated like every read route: give Prometheus a token with the read ability as a bearer credential.
app, database and node (one per series, from the resource the sample belongs to) and destination on the exporter’s own series, so the series count tracks what you have deployed and what you configured, not request traffic.
The prefix is the lowercase brand short name followed by an underscore,
levelrail_ on a stock install. A token limited to some apps only sees those apps and databases, and no node or platform series.
Loki and Grafana quick start
-
Run Loki and Grafana wherever you like. For a trial on one host:
-
Loki on the same host or a private network is an internal address, which export refuses by default. On the control plane set
APP_EXPORT_ALLOW_PRIVATE_NETWORKS=trueand restart (see Environment variables). A public HTTPS Loki needs nothing. -
Add the destination:
For Grafana Cloud or a multi-tenant Loki add
--header X-Scope-OrgID=tenantor--header "Authorization=Basic <base64>". Header values are stored encrypted and are never returned by the API. -
In Grafana add a Loki data source pointing at
http://loki:3100, then query{job="levelrail", app="web"}.
job, app, kind (app or database), stream (stdout or stderr) and level, plus any --label you set. level is the structured level or severity field when the line is JSON, otherwise error for stderr and info for stdout.
Log destinations
Filters apply per destination:--app (repeatable, empty means every app) and --min-level (debug, info, warn, error). Database containers are exported only by destinations with no --app filter.
- HTTP JSON lines: one JSON object per line:
time,kind,app,stream,level,messageandfieldsfor structured lines.Content-Type: application/x-ndjson. - Loki: an endpoint with no path gets
/loki/api/v1/pushappended. - Syslog:
tcp://host:portortls://host:port, RFC 5424 with octet counting framing, facilitylocal0. TLS verifies the server certificate against the system roots.
Audit log export
Streaming sends each new audit row at least once. Each batch is NDJSON, and webhook batches carry these headers (the prefix follows the brand name):
The signature is HMAC-SHA256 over
<unix>.<raw body> with your key. Verify it and reject timestamps outside a few minutes:
audit_s3 writes each batch to <prefix>/<yyyy>/<mm>/<dd>/<first-created-at>-<first-id>.ndjson in a storage destination. The key is derived from the batch’s first row, so a retried batch overwrites itself.
Tokens, bearer values, URL credentials and token-shaped strings are masked in every exported field. By default streaming starts at the moment the destination is created. --backfill starts at the oldest audit row instead.
Delivery semantics
- A cursor (timestamp and row id) is saved after every successful batch, so a restart resumes where it stopped.
- Delivery is at least once. A crash between a receiver accepting a batch and the cursor being saved sends that batch again, with the same id range.
- A failing destination holds the cursor and retries. Rows are never skipped, and the audit log itself is the buffer.
On demand download
from is inclusive and to exclusive. The API route is GET /api/v1/audit-log/export?from=&to=&format=ndjson|csv and needs the root ability. A single download is capped at APP_EXPORT_AUDIT_MAX_ROWS.
OTLP metrics
Ametrics_otlp destination pushes the same series as the scrape endpoint as OTLP/HTTP JSON (/v1/metrics is appended when the endpoint has no path). Counters are cumulative monotonic sums, everything else gauges. The interval defaults to APP_EXPORT_METRICS_INTERVAL and can be set per destination with --interval (10 to 3600 seconds).
Reliability and safety
- Every destination has an in-memory queue of
APP_EXPORT_QUEUE_LINESentries. When it fills, the oldest entries are dropped and counted. There is no disk buffer, so a control plane restart loses queued log lines but not audit rows. - Container log lines are handed to exporters through a non-blocking subscription. A slow destination cannot slow a container, the log store, a deploy or the API.
- A batch is retried with exponential backoff and jitter up to
APP_EXPORT_MAX_ATTEMPTStimes. Responses in the 4xx range other than 408 and 429 are not retried, because retrying cannot fix them. - After
APP_EXPORT_BREAKER_FAILURESconsecutive failed batches a destination backs off forAPP_EXPORT_BREAKER_COOLDOWN, then tries one batch. - Endpoints are validated when saved and again at every connection, including redirects: private, loopback and link-local addresses are refused unless
APP_EXPORT_ALLOW_PRIVATE_NETWORKS=true. Endpoints cannot embed credentials. - Headers and signing keys are stored with envelope encryption and are never returned. The API shows header names and whether a key is set.
- Each destination shows its last success, last error, queue depth, dropped and failed counts, and breaker state, in the dashboard, with
levelrail-cli export destinations status <id>, and asexport_*metrics.
CLI
--header and --hmac-key values end up in your shell history. Prefer a script that reads them from a secret store.
Next steps
Observability
Node-local metrics and the remote read endpoint.
Log archive
Scheduled, compressed log archives in a bucket.