Monitoring¶
Metrics¶
Prometheus metrics are served on /metrics, labelled by route template so a
per-user path does not create a time series per user. Scrapers that send an
OpenMetrics Accept header (Prometheus does by default) get the OpenMetrics
format; other clients get the classic Prometheus text format.
Set METRICS_TOKEN to require a bearer token, for example one made with
openssl rand -hex 32. Requests without it get 401. Without the setting the
endpoint answers anyone who can reach it, and Keyosk warns about that at
startup. In Prometheus, put the token in a file and point the scrape job at it:
scrape_configs:
- job_name: keyosk
scheme: https
authorization:
type: Bearer
credentials_file: /etc/prometheus/keyosk-metrics-token
For a quick look, curl -H "Authorization: Bearer $METRICS_TOKEN" https://…/metrics.
| Metric | Meaning |
|---|---|
keyosk_http_requests_total |
requests by route, method, status |
keyosk_http_request_duration_seconds |
latency by route |
keyosk_key_operations_total |
key issue/extend/delete/revoke by outcome |
keyosk_keys_marked_missing_total |
keys marked as missing because the gateway no longer had them, by where Keyosk noticed (dashboard, extend, sync) |
keyosk_keys_missing |
keys marked as missing right now, waiting out the grace period; counted from the database on every scrape |
keyosk_keys_missing_removed_total |
marked keys removed after the grace period ran out |
keyosk_active_keys |
keys currently issued |
keyosk_keys_expiring_7d |
keys expiring within a week |
keyosk_job_last_success_timestamp_seconds |
when each background job last ran without error, by task; the job's start time until it first succeeds |
keyosk_job_interval_seconds |
how often each background job runs, by task |
keyosk_job_item_failures_total |
notices, reversions or limit pushes a background job could not get done and retries on its next run, by task |
The missing-key metrics are the alarm for a Keyosk instance pointed at the
wrong gateway, or at one restored from a backup. Suggested alerts: a warning
when keyosk_keys_missing stays above zero for an hour, or when
keyosk_keys_marked_missing_total rises; and a critical alert when
keyosk_keys_missing_removed_total rises, since a record was lost. The first
fires while the grace period (KEY_MISSING_GRACE_PERIOD) still lets you
correct the cause without losing anything.
The job metrics show whether the background jobs still run. The task label
names the job: expiry_reminder (expiry notices, every 6 hours), profile_expiry (reverting
temporary profile assignments, every 15 minutes), limit_sync (pushing
profile limits to the gateway, every LIMIT_SYNC_INTERVAL) and
session_cleanup (hourly). A run counts as a success when it gets through,
even if a single notice or key failed along the way; those failures are
logged and retried. One alert covers all of them, firing when a job has not
succeeded for two of its intervals, whether it stopped, keeps failing or is
still working on one run:
Before its first success, a job's timestamp is the time it started, so a job that fails from the start alerts as well, without firing on every restart.
A run that gets through with some of its items failing still counts as a
success, so a mail relay or gateway that keeps refusing does not show up
there. keyosk_job_item_failures_total counts those items. A single failure
is retried on the next run and needs no attention; suggested is a warning when
failures keep coming for a day, which clears by itself once the retries get
through:
The range covers two runs of the slowest job and for outlasts it, so one
failed item does not fire; a job that fails something in every half day for a
whole day does. Without the for, or with one shorter than the range, a single
failure would fire and stay up until it left the range.
Health checks¶
Two endpoints answer without a login, for load balancers and orchestrators:
GET /healthzanswers200 okwhile the server is running. Use it as the liveness probe.GET /readyzalso checks the database, and answers503when it cannot reach it. Use it as the readiness probe.
The container image needs no shell or curl for this: its HEALTHCHECK runs
keyosk -healthcheck, which probes /healthz on LISTEN_ADDR and exits
non-zero when that fails. Kubernetes ignores the image's health check and uses
its own probes on the two endpoints.