opsdocsConsole

Packages / ops-sdk

Logs, traces and metrics

Structured logs, OTLP trace export and a Prometheus registry for an axum service.

Updated 13 Oct 2026View as Markdown

Feature: observability.

Logs and traces

rust
ops_sdk::observability::init_tracing("web");

Call it once, inside the Tokio runtime, right after env::load(). It installs the process wide tracing subscriber.

variableeffect
LOG_FORMAT=jsonone JSON object per line, which is what ops's log search reads best. Anything else prints a readable format for your terminal
RUST_LOGthe filter, for example info,sqlx=warn. The default is info
OTEL_EXPORTER_OTLP_ENDPOINTwhen set, spans are also exported over OTLP (HTTP, protobuf), batched
OTEL_SERVICE_NAMEthe service name on the spans. The default is the name you passed to init_tracing

If the trace exporter cannot be built, the service still starts and prints one line to stderr. Telemetry trouble never takes the service down.

Spans and log lines carry only what your code puts into them. Keep personal data such as emails and names out of fields; record ids instead.

Metrics

observability::metrics is a small in process Prometheus registry. It counts requests and times them by method, route template and status class (2xx, 4xx and so on).

rust
use axum::{Router, middleware, routing::get};
use ops_sdk::observability::metrics;

let app = Router::new()
    .route("/orders/{id}", get(order))
    .route("/metrics", get(metrics::serve))
    .layer(middleware::from_fn(metrics::track));
  • track is the middleware. It labels a request with the route template (/orders/{id}), never the concrete path, so the number of series stays small. A request no route matched is counted as (unmatched).
  • serve answers GET /metrics in the Prometheus text format. Keep it off your public domain: route only the paths your users need.
  • render() returns the same text as a String, for a test or a server that is not axum.

The output always holds process_uptime_seconds, http_requests_total and the http_request_duration_seconds histogram.

Gauges

Set a named level and it is rendered with the rest:

rust
metrics::set_gauge("queue_depth", "Jobs waiting in the queue", 42.0);
let now = metrics::gauge("queue_depth"); // Some(42.0)