Monitoring & Observability Guide
HyperInfer is designed to be observable by default. Every LLM call is traced, every token is counted, and every error is recorded. This guide covers the telemetry stack, metrics, logging, and how to integrate with your existing observability infrastructure.
1. The Two Pillars of Observability
HyperInfer currently emits data via two mechanisms:
| Pillar | What You Get | Where It Goes |
|---|---|---|
| Distributed Traces | Per-request spans with model, tokens, and latency | OpenTelemetry collector (OTLP) |
| Structured Logs | JSON logs via the tracing crate |
stdout / log aggregators |
Metrics Endpoint
A Prometheus /metrics endpoint is a planned follow-up. Currently, metrics are derived from logs and traces rather than scraped directly.
2. OpenTelemetry Integration
HyperInfer uses OpenTelemetry with OTLP export. The GenAI semantic conventions are followed for span attributes.
2.1. Enabling Telemetry (Rust)
The actual signature is:
use hyperinfer_client::init_telemetry;
// Takes a single endpoint URL
init_telemetry("http://localhost:4318").expect("Failed to init telemetry");
For custom headers (e.g., authentication):
use hyperinfer_client::init_telemetry_with_headers;
init_telemetry_with_headers(
"https://otel-collector.example.com/v1/traces",
vec![("Authorization".to_string(), "Bearer my-token".to_string())]
).expect("Failed to init telemetry");
2.2. Langfuse Integration
use hyperinfer_client::init_langfuse_telemetry;
init_langfuse_telemetry(
"lf-public-key",
"lf-secret-key",
"https://cloud.langfuse.com",
).expect("Failed to init Langfuse");
2.3. GenAI Span Attributes
The client library automatically attaches GenAI-convention attributes to every LLM call span:
| Attribute | Description |
|---|---|
gen_ai.system |
Provider name (e.g., openai, anthropic) |
gen_ai.request.model |
The requested model |
gen_ai.response.model |
The actual model that responded |
gen_ai.usage.input_tokens |
Prompt tokens |
gen_ai.usage.output_tokens |
Completion tokens |
gen_ai.response.finish_reason |
stop, length, etc. |
These are set via helper functions:
use hyperinfer_client::{set_gen_ai_attributes, set_gen_ai_usage, set_gen_ai_response};
let span = tracing::info_span!("chat");
set_gen_ai_attributes(&span, "openai", "gpt-4o", "chat");
set_gen_ai_usage(&span, 100, 50);
set_gen_ai_response(&span, "resp-abc123", "stop");
3. Usage Tracking via Redis Streams
Usage data is pushed to Redis Streams via XADD for durability and ordered delivery. This allows multiple consumers to process the data independently.
3.1. The TelemetryConsumer
The control plane includes a TelemetryConsumer (in hyperinfer_core) that reads usage records from Redis Streams consumer groups. It provides:
- Consumer groups for horizontal scaling.
- Automatic acknowledgment of successfully processed records.
- Retry logic for failed processing.
use hyperinfer_core::TelemetryConsumer;
let consumer = TelemetryConsumer::new(redis_url, "billing-pipeline").await?;
consumer.run().await?;
4. Structured Logging
HyperInfer emits structured logs via the tracing crate.
4.1. Log Levels
| Level | When to Use |
|---|---|
ERROR |
Something failed and the request could not complete. |
WARN |
Something unexpected happened, but the request succeeded (e.g., a fallback was triggered). |
INFO |
Normal operational events (server started, deployment created). |
DEBUG |
Detailed diagnostic info (every LLM call, every routing decision). |
TRACE |
Extremely verbose (full request/response bodies). |
4.2. Enabling Logs
Set the RUST_LOG environment variable to control verbosity:
# Show all info-level logs from hyperinfer crates
export RUST_LOG=hyperinfer=info
cargo run --bin hyperinfer-server
# Debug-level for the router only
export RUST_LOG=hyperinfer_router=debug
cargo run --bin hyperinfer-server
4.3. Example Log Line
Logs are emitted in a structured format via tracing_subscriber:
2026-06-06T12:34:56.789Z INFO hyperinfer::router: Request routed successfully
request_id=req_abc123 model=gpt-4o deployment=gpt-4o-prod provider=openai
latency_ms=342 tokens=150
5. The Client Telemetry Lifecycle
The hyperinfer-client library starts its own background task on init() that:
- Connects to Redis.
- Subscribes to configuration changes via Redis Pub/Sub.
- Pushes usage records to a Redis Stream.
- Rebuilds the deployment pool when config changes.
[INFO hyperinfer_client] Telemetry stream started
[INFO hyperinfer_client] Connected to Redis at redis://localhost:6379
[INFO hyperinfer_client] Subscribed to config changes
[INFO hyperinfer_client] Rebuilt deployment pool after config update
This task runs until close() is called.
6. Comparison Table: Observability Features
| Feature | Data Plane (Client) | Control Plane (Server) |
|---|---|---|
| OpenTelemetry Traces | Emits per-request spans | N/A (no traces on server) |
| Structured Logs | Yes (via tracing) |
Yes (via tracing) |
| Usage Tracking | Pushes to Redis Streams | Consumes via TelemetryConsumer |
| Health Endpoints | N/A (client-side) | /healthz (liveness only) |
| Prometheus Metrics | Not yet | Not yet (planned) |