Observability & metrics
mq-bridge-app is production-ready with structured JSON logging and a Prometheus metrics
endpoint, plus per-route status you can query at runtime.
Metrics
Attach the metrics middleware to an endpoint to emit
throughput, latency, and error metrics. It requires the metrics feature and takes no options —
its presence enables collection. Input and output are labelled separately, so attaching it to
both sides is meaningful:
orders_bridge:
input:
middlewares: [ { metrics: {} } ]
kafka: { topic: "orders", url: "localhost:9092" }
output:
middlewares: [ { metrics: {} } ]
nats: { subject: "orders.processed", stream: "orders_stream", url: "nats://localhost:4222" }
Metrics are exposed for a Prometheus scrape. Point your Prometheus (or Grafana Agent) at the running server and build dashboards on the emitted throughput/latency/error series.
⚠️ Metrics are not free. The
metricsmiddleware records a measurement per message on whichever side it is attached, so it adds per-message overhead and can measurably reduce throughput — most noticeably on high-throughput endpoints where per-message cost dominates. Enable it where you need visibility, not blanket-on every side of every route: attach it to the one endpoint you actually want to watch, and leave it off the hot path when chasing peak throughput. Benchmark numbers should be taken without it attached (see Reading throughput honestly).
Logging
Logs are structured JSON, suited to shipping into a log aggregator. Two things to keep in mind:
- Message payloads are emitted only at
tracelevel. Run production abovetraceso no sensitive data (e.g. cardholder data) reaches logs or traces. See the TLS & security hardening notes. - The MCP server’s
stdiotransport owns stdout for the protocol, so its logs go to stderr. In HTTP transport this is not a concern.
Runtime route status
For a running bridge, query route health rather than reading logs:
- In the UI, the runtime status view shows live connection health and message counts per publisher/consumer/route.
- Through the MCP server,
list_routesandroute_statusreportmessages,messages_per_second(instantaneous),elapsed_s, andaverage_messages_per_second. For a running route read the instantaneous rate; for a finished job read the average. See MCP route status.
Reading throughput honestly
Whatever the source, a rate figure is only meaningful with its methodology:
- Measure on a release build — a debug build reports dramatically slower rates. Through MCP,
call
server_infofirst to confirm the buildprofile. - The instantaneous rate of a completed job decays to ~0 within a second — use the average for finished work.
- Record CPU/cores/RAM and the exact
batch_size/concurrencynext to every number.
See Performance tuning → Measuring and the like-for-like ETL/CDC
methodology in
benches/etl/README.md.