navree

Health and metrics

Liveness and readiness endpoints, custom health checks, and Prometheus metrics with an optional bearer token.

On this page

Featureobserve Load balancers and orchestrators need to know whether your app is alive and ready for traffic, and you want numbers on how it behaves. navree-observe serves both: a liveness probe, a readiness probe that runs every registered health check, and a Prometheus endpoint with the request metrics Navree records for you.

Setup

Add ObserveModule to your app:

src/app.rs

It mounts three routes. Their paths are absolute (no API prefix, no version), they are public, and every response carries Cache-Control: no-store:

RouteWhat it answers
GET /health/live200 {"status":"up"} while the process serves HTTP.
GET /health/ready200 when every health check is up, 503 when one is down, with a report.
GET /metricsThe Prometheus text exposition (unless observe.metrics is off).

All three keep answering in maintenance mode: they are in the default http.maintenance_except list, so an orchestrator doesn't restart instances that are only down for maintenance.

The observe section is optional:

config/app.toml
KeyDefaultWhat it does
observe.metricstrueInstall the Prometheus recorder and serve GET /metrics.
observe.metrics_tokennoneWhen set, GET /metrics requires Authorization: Bearer <token>. An empty token fails the boot.

In code: ObserveModule::for_root(ObserveOptions { metrics: true, metrics_token: Some(Secret::new(token)) }), with Secret from navree::contracts.

Liveness

GET /health/live runs no checks: it only proves the process answers HTTP. Use it for restarts, so a slow database never gets a healthy process killed.

200 OK

Readiness

GET /health/ready runs every registered health check concurrently and reports each one. Use it to decide whether an instance gets traffic. This is the reference CRM's answer:

200 OK

When a check is down, the status is 503 and the check carries its reason:

503 Service Unavailable
  • Each check has 2 seconds (DEFAULT_CHECK_TIMEOUT). A check that takes longer, or panics, is down.
  • Down checks are logged as warnings under the navree::health target.
  • Two checks with the same name are reported as name, name#2, and so on.
  • With no checks registered, the app is ready.

Navree's modules register these checks when you add them:

CheckModuleWhat it does
databaseDatabaseModulePings the connection pool.
cacheCacheModuleWrites, reads back and forgets a key.
storageStorageModuleWrites, reads back and deletes a small file on every disk.

Writing a health check

A health check implements HealthCheck from navree::contracts: a name and an async check that returns HealthStatus::Up or HealthStatus::Down(reason). Register it as a multi-binding of dyn HealthCheck; readiness collects every one at boot:

src/modules/payments/health.rs

Keep checks fast and give outgoing calls a timeout below the 2-second budget, as above. A HttpClientError message never contains query strings or credentials, so it is safe to report.

To run the checks from your own code, inject Arc<Health> (from navree::observe): health.check().await returns a HealthReport with is_up() and the checks map.

Probes in Kubernetes

deployment.yaml

Metrics

GET /metrics serves every metric recorded in the process in the Prometheus text format. Navree's HTTP pipeline records two for every request:

MetricTypeLabels
http_requests_totalcountermethod, route, status
http_request_duration_secondshistogrammethod, route, status

route is the route's template (/api/v1/deals/{id}), not the request path, so the number of series stays small; requests that match no route are labelled unmatched. Histograms whose name ends in _seconds use the buckets 5 ms, 10 ms, 25 ms, 50 ms, 100 ms, 250 ms, 500 ms, 1 s, 2.5 s, 5 s and 10 s.

GET /metrics

These are the only metrics Navree records today: there are no built-in metrics for the queue, the cache or the database pool yet, and no OpenTelemetry or Sentry integration (see the roadmap).

Protecting the endpoint

Metrics reveal your routes and traffic. Set observe.metrics_token to require a bearer token:

Shell

A missing or wrong token gets 401 with WWW-Authenticate: Bearer, and the attempt is logged as a warning under navree::security. Tokens are compared in constant time. In Prometheus, pass the token in the scrape job:

prometheus.yml

Recording your own metrics

Navree uses the metrics facade, so anything your code records with its macros shows up on /metrics. Add the crate (the version Navree uses is 0.24) and record:

Cargo.toml
Rust

Keep label values bounded (ids and paths make the number of series explode), and end duration histograms in _seconds to get the buckets above.

Turning metrics off

With observe.metrics = false, no recorder is installed and /metrics isn't mounted. Do that when another library installs its own metrics recorder: there is one per process, and ObserveModule fails the boot if another one is already installed.

Testing

The Prometheus recorder is installed once per process, so every app booted by your tests shares it. Turn metrics off in tests (observe.metrics = false), or assert on counts with >= rather than exact values. Test health checks through the route:

tests/health.rs

Popular pages

  • Installation
  • Your first app
  • Routing and controllers
  • Validation
  • Authentication
  • Benchmarks