-
Notifications
You must be signed in to change notification settings - Fork 0
Configuration
app := rex.New(metric.WithMetrics(metric.NewConfig(
metric.WithPath("/internal/metrics"),
metric.WithMetricsRouter(rx.RouterConfig{Addr: "127.0.0.1:9090"}),
metric.WithCollectionInterval(15*time.Second),
)))metric.WithMetrics(nil) takes the defaults.
There is no field-by-field merge. A partial struct literal leaves everything else at its zero value:
// Wrong: Router.Addr "", CollectionInterval 0 (collector off).
metric.WithMetrics(&metric.Config{Path: "/internal/metrics"})
// Right.
metric.WithMetrics(metric.NewConfig(metric.WithPath("/internal/metrics")))The merge used to exist and behaved as a trap: fields it forgot were silently ignored, fields it copied unconditionally were zeroed by a partial literal, and a deliberate zero could not be expressed at all.
This extension had no options at all until recently — its
Configwas struct-literal only. That was survivable while a partial literal was merged over the defaults, and is not now that it is used verbatim. The option set is the supported way to configure it.
| Field | Default | |
|---|---|---|
Path |
/metrics |
where the endpoint is served |
AtDefaultAddr |
false |
serve on the application router instead of a dedicated one |
Router |
:9090, base /, TLS off |
the dedicated metrics listener |
CollectionInterval |
5s |
process-metric sampling; 0 disables the collector |
WithPath(p) |
endpoint path |
WithAtDefaultAddr(bool) |
serve on the application router |
WithMetricsRouter(rx.RouterConfig) |
configure the dedicated listener |
WithCollectionInterval(d) |
process-metric sampling; 0 disables |
The default is a dedicated listener on :9090, and that is the right default:
/metrics exposes request rates, error counts, latency distributions and every
route pattern in the application. That is a map of your API and its weak points
to anyone who can reach it.
// Internal only.
metric.WithMetricsRouter(rx.RouterConfig{
Addr: "127.0.0.1:9090",
ReadTimeout: 5 * time.Second,
MaxBodyBytes: 4 << 10,
})WithAtDefaultAddr(true) puts it on the public listener. Worth a deliberate
choice — and if you do it, put authentication in front of the path.
TLS on the metrics router is opt-in and configured like any other
RouterConfig.
Both extensions default to their own router, on different ports (:9090
metrics, :9091 health). To put them together, give them the same router name
and config — whichever extension runs second reuses the existing router:
opsRouter := rx.RouterConfig{Addr: "127.0.0.1:9090"}
app := rex.New(
metric.WithMetrics(metric.NewConfig(metric.WithMetricsRouter(opsRouter))),
health.WithHealth(health.NewConfig(health.WithHealthRouter(opsRouter))),
)They create routers under different names by default, so this only merges them if both configs name the same address — in which case the second bind fails. Prefer keeping them on separate ports unless you have a reason not to.
metric.WithCollectionInterval(0) // disable the process collectorThe endpoint still serves whatever other instrumentation has recorded — HTTP metrics and your own are unaffected.
Keep the scrape interval at or above the collection interval; scraping more often than you sample produces stair-steps, not resolution.
rextension-metric — Prometheus / OpenMetrics instrumentation for Rex · MIT · © 2026 Kryovyx
Ecosystem