Metrics beyond bases
After you pick metrics.base (minimal or standard), you can trim which categories are active, separate collect from emit, shrink label sets with granularity, and apply those changes live (including a Prometheus listen rebind). Concept detail: Metrics configurability. For minimal vs standard side by side, see Operator metrics bases first.
Prerequisites: Conduit installed; an upstream on 127.0.0.1:5300; control: enabled if you practice overlay apply. Follow Metrics and tracing if you have not scraped Prometheus yet.
What you will practice
- Exclude a category from
standard(drop timing series from scrape) - Keep a category collected but
emit: false(series absent from scrape) - Override granularity so timing labels are pool-only
- Apply a metrics plan overlay without restart; optionally rebind the scrape port
Baseline config
Save as conduit-metrics-tune.yaml:
schema_version: 1
listeners:
listeners:
- address: "127.0.0.1:15353"
protocol: udp
pools:
- name: default
backends:
- address: "127.0.0.1:5300"
control:
listen_address: "127.0.0.1:5199"
metrics:
enabled: true
base: standard
prometheus:
listen_address: "127.0.0.1:9090"
path: /metrics
conduitctl validate --file conduit-metrics-tune.yaml
conduit conduit-metrics-tune.yaml
Send traffic, then confirm standard timing series appear:
dig @127.0.0.1 -p 15353 +time=2 example.com A
curl -sS "http://127.0.0.1:9090/metrics" | grep conduit_forward_duration
Expect: forward timing series present (exact names in Built-in metrics).
1. Exclude a category
Stop Conduit and add:
metrics:
enabled: true
base: standard
categories:
exclude: [timing]
prometheus:
listen_address: "127.0.0.1:9090"
Restart, send traffic, scrape again:
curl -sS "http://127.0.0.1:9090/metrics" | grep conduit_forward_duration || echo "timing omitted"
Expect: no forward timing series. Query volume counters from volume still increment. Use categories.include with base: none when you want an allow-list instead of carve-outs — Metrics configurability — Categories.
2. Collect vs emit
Restore base: standard without the exclude, then record timing in-process but omit it from scrape and OTLP:
metrics:
enabled: true
base: standard
collection:
timing:
collect: true
emit: false
prometheus:
listen_address: "127.0.0.1:9090"
After traffic:
curl -sS "http://127.0.0.1:9090/metrics" | grep conduit_forward_duration || echo "emit off — absent from scrape"
Expect: scrape omits timing series. Hot-path cost of collect remains — turn collect: false (or exclude the category) when you want to stop paying that cost. collect: false with emit: true fails validate.
flowchart LR
Hot[Hot path] -->|collect true| Store[In-process store]
Store -->|emit true| Prom[Prometheus / OTLP]
Store -->|emit false| Omit[Not exported]
Hot -->|collect false| Skip[No store / no export]
3. Granularity — fewer labels
Keep timing in the scrape, but drop the backend label on timing families:
metrics:
enabled: true
base: standard
granularity:
timing: [pool]
prometheus:
listen_address: "127.0.0.1:9090"
After traffic:
curl -sS "http://127.0.0.1:9090/metrics" | grep conduit_forward_duration
Expect: timing series labeled by pool (and other still-allowed dimensions), not per-backend. Changing a family's dimension list creates a new series identity — counters for that schema start over. Allowed keys: Built-in metric registry.
Coarse response codes (class buckets instead of every IANA name):
granularity:
default: fine
responses:
rcode: coarse
4. Live overlay — plan change and rebind
With the baseline config running (control: on 5199), apply a sparse overlay that only excludes timing:
Save as overlay-exclude-timing.yaml:
schema_version: 1
metrics:
categories:
exclude: [timing]
conduitctl --endpoint http://127.0.0.1:5199 apply --file overlay-exclude-timing.yaml
dig @127.0.0.1 -p 15353 +time=2 example.com A
curl -sS "http://127.0.0.1:9090/metrics" | grep conduit_forward_duration || echo "plan applied — timing gone"
Expect: timing disappears from scrape; the listen socket on 9090 stays up (plan-only change). Overlay merge for metrics is deep — Overlay merge strategy.
Rebind scrape to another port — save as overlay-rebind.yaml:
schema_version: 1
metrics:
prometheus:
listen_address: "127.0.0.1:9091"
conduitctl --endpoint http://127.0.0.1:5199 apply --file overlay-rebind.yaml
curl -sS "http://127.0.0.1:9091/metrics" | head
curl -sS "http://127.0.0.1:9090/metrics" && echo "old port still up?" || echo "old port closed"
Expect: new address serves metrics; old listener is closed after a successful bind. If the new bind fails, apply is rejected and the previous scrape address keeps working.
What to verify
| Check | Expected |
|---|---|
categories.exclude: [timing] |
No timing series; volume still present |
collection.timing.emit: false |
Timing absent from scrape; validate rejects emit without collect |
granularity.timing: [pool] |
Timing labels lack backend |
| Plan overlay | Timing toggles without restart; port unchanged |
| Rebind overlay | Scrape moves to the new listen address |
Related topics
- Metrics configurability — bases, collect/emit, granularity, overlay matrix
- Operator metrics bases —
minimalvsstandardlab - Metrics and tracing — first Prometheus scrape and
conduitctl trace - Control plane workflows — apply / export / reload
- Built-in metric registry — category membership and dimensions
- Config schema: metrics and tracing