Stack guides
The Lumin agent is stack-agnostic — it scrapes whatever Prometheus exposition you point it at and tails whatever stdout/stderr you label. But the Metrics page in the UI is built around three canonical metric names, and the per-stack guides below give you the exact snippet to emit them.
The canonical schema
Section titled “The canonical schema”If you want the canned KPIs, latency-distribution histogram, and top-routes table to light up, your service should emit:
| Metric | Type | Labels | What it counts |
|---|---|---|---|
http.requests |
counter | {method, route, status_class} |
Every HTTP request. status_class ∈ {2xx, 3xx, 4xx, 5xx}. |
http.latency_ms |
histogram | {method, route} |
Request latency in ms. Bucket bounds [5, 10, 25, 50, 100, 250, 500, 1000, 2500, 5000] work for typical Go/Python/Node services. |
http.errors |
counter | {method, route, status} |
Increment only when status >= 500. Raw 3-digit code is fine here — 5xx codes are low cardinality in practice. |
Use the templated route, not the expanded path. /api/projects/:projectId/logs is one route; /api/projects/1/logs and /api/projects/2/logs are two paths sharing a route. Templating keeps cardinality bounded as your project count grows.
How frameworks map onto this
Section titled “How frameworks map onto this”You will rarely emit these names by hand. Each supported framework has a library that already emits HTTP metrics under its own names (http_server_requests_seconds_count for Spring’s Micrometer, gin_http_requests_total for prometheus/client_golang, …) and the agent re-keys them to the canonical names when you tell it the framework via lumin.metrics.framework.
The framework value to pass in the Docker label:
| Framework | lumin.metrics.framework |
Underlying library |
|---|---|---|
| Browser SDK | n/a (event ingest, not metric scrape) | @lumin-monitor/browser |
| Gin (Go) | gin |
prometheus/client_golang |
| Spring Boot (JVM) | spring |
Micrometer + Spring Boot Actuator |
| Express (Node) | express |
prom-client |
| FastAPI (Python) | fastapi |
prometheus-fastapi-instrumentator |
| Axum (Rust) | axum |
axum-prometheus |
| React Native SDK | n/a (event ingest, not metric scrape) | @lumin-monitor/react-native |
What if my framework isn’t listed?
Section titled “What if my framework isn’t listed?”Two paths:
-
You only need logs. Label the container with
lumin.logs=trueand ignore metrics. The agent tails stdout/stderr regardless of framework; if your logger writes JSON with alevelfield, Lumin parses it as structured. -
You want metrics too. Expose Prometheus exposition on a known path and port, label with
lumin.metrics=trueandlumin.metrics.port=…, but omitlumin.metrics.framework. The agent ingests metric names verbatim. The canned UI panels won’t light up, but custom dashboards work and the metrics are queryable. -
You want the canned panels on an unlisted framework. Emit the three canonical names from the table above yourself, then omit
lumin.metrics.framework. The generic pass-through preserves names it does not recognise, sohttp.requests,http.latency_ms, andhttp.errorsreach the store intact and every panel lights up. This is more work than a framework label, and it is the only path that does not need a new adapter.
An unrecognised lumin.metrics.framework value is not an error. The agent falls back to the generic pass-through and keeps shipping metrics under their original names. Nothing warns you; the symptom is a Metrics page whose KPI cards stay on their empty state. Check the spelling against the table above if that happens.
Open an issue if your framework is common enough to warrant first-class support — adding a new value to lumin.metrics.framework is one mapping table.