The Forge Vault client counts its requests -- attempts, successes, failures, and per-request duration -- through a hand-rolled RED triad on an OpenTelemetry meter. Folding it into the instrumentation framework brings it inline with the rest of the fleet, with no change to any exposed metric.
What this involves
crates/api-core/src/secrets/forge_vault.rs (ForgeVaultMetrics, ~7 op methods): convert carbide_api_vault_requests_attempted_total, _succeeded_total, _failed_total, and the carbide_api_vault_request_duration_milliseconds histogram to #[derive(Event)] events. The request_type label (service_account_login / get / set / delete_credentials / get_certificate) becomes a bounded LabelValue enum matching the exact strings in use.
- Leave the
carbide-api.vault.token_time_until_refresh observable gauge untouched -- it's periodic state.
- Catalogue-pinned: these four metrics are rows in
docs/observability/core_metrics.md. Their descriptions must be copied byte-for-byte, INCLUDING the pre-existing wrong-sounding text (e.g. "The amount of tls connections that were attempted" on a Vault-requests counter, and the lowercase duration text) -- correcting those is a separate, deliberate change, not this reshape. Any drift regenerates a catalogue diff and defeats the gate-free purpose.
- The failed-counter's second label:
carbide_api_vault_requests_failed_total carries an http.response.status_code label whose value is the HTTP status code string, empty when there is none. Reproduce it exactly, including the empty-string case -- decide between a bounded newtype or an enum, and pin the exact rendered values (including empty) with a test.
- The failure sites sit beside
error! lines in callers: keep those byte-identical (metric-only log = off events; leave the logs alone).
- Prove zero delta: after regen,
git diff docs/observability/core_metrics.md must be EMPTY, and no golden /metrics fixture moves.
Part of #3169.
The Forge Vault client counts its requests -- attempts, successes, failures, and per-request duration -- through a hand-rolled RED triad on an OpenTelemetry meter. Folding it into the instrumentation framework brings it inline with the rest of the fleet, with no change to any exposed metric.
What this involves
crates/api-core/src/secrets/forge_vault.rs(ForgeVaultMetrics, ~7 op methods): convertcarbide_api_vault_requests_attempted_total,_succeeded_total,_failed_total, and thecarbide_api_vault_request_duration_millisecondshistogram to#[derive(Event)]events. Therequest_typelabel (service_account_login / get / set / delete_credentials / get_certificate) becomes a boundedLabelValueenum matching the exact strings in use.carbide-api.vault.token_time_until_refreshobservable gauge untouched -- it's periodic state.docs/observability/core_metrics.md. Their descriptions must be copied byte-for-byte, INCLUDING the pre-existing wrong-sounding text (e.g. "The amount of tls connections that were attempted" on a Vault-requests counter, and the lowercase duration text) -- correcting those is a separate, deliberate change, not this reshape. Any drift regenerates a catalogue diff and defeats the gate-free purpose.carbide_api_vault_requests_failed_totalcarries anhttp.response.status_codelabel whose value is the HTTP status code string, empty when there is none. Reproduce it exactly, including the empty-string case -- decide between a bounded newtype or an enum, and pin the exact rendered values (including empty) with a test.error!lines in callers: keep those byte-identical (metric-onlylog = offevents; leave the logs alone).git diff docs/observability/core_metrics.mdmust be EMPTY, and no golden/metricsfixture moves.Part of #3169.