fix(metrics): normalize persistence metric labels for Prometheus - #8064
Conversation
…l() by domain tag
The metered.tmpl wrapper never captured retryCount from context,
while metered_execution.tmpl did. Both templates emit on persistence_requests_per_domain, so
Prometheus saw two series with mismatched label keys
({operation,domain,is_retry} vs {operation,domain}) and silently
rejected whichever registered second.
Capture retryCount in the non-execution template and append
metrics.IsRetryTag(retryCount > 0) to every metered emission. This
also makes is_retry truthful for retried calls, which are exercised by common/backoff retry.
Naively adding the tag would have re-routed methods whose requests
have no MetricTags() impl (CreateShard, GetShard, UpdateShard,
FetchDynamicConfig, UpdateDynamicConfig, all QueueManager methods)
from persistence_requests to persistence_requests_per_domain, because
base.call() decides the metric by len(tags) > 0 rather than by the
presence of a domain tag — a silent rename and a new collision.
Switch base.call() to route by tag content (hasDomainTag) so the
choice between persistence_requests and persistence_requests_per_domain
is governed by whether a DomainTag is present, independent of how
many auxiliary tags (is_retry, task_category, ...) accompany it.
Signed-off-by: Stanislav Bychkov <stanislav.bychkov@netapp.com>
Persistence base metric names like persistence_requests are emitted directly by no-domain paths such as shard, queue, config, and history-task persistence calls. Using those same names as per-domain rollup targets makes two different emission paths share a metric family with different label sets. Keep the aggregate behavior, but give persistence rollups explicit _rollup names to avoid descriptor collisions while leaving generic rollup behavior unchanged. Signed-off-by: Stanislav Bychkov <stanislav.bychkov@netapp.com>
Some history-task requests add a task_category tag through MetricTags().
When those requests emit direct persistence metrics, they produce
persistence_requests / persistence_latency / persistence_latency_ns with
{operation, is_retry, task_category}. Other direct persistence emissions
use the same metric names with only {operation, is_retry}, creating
different label keys for the same Prometheus metric family.
Inject task_category="none" in callWithoutDomainTag and in call()'s
no-domain branch so direct persistence_* emissions carry a uniform label
set regardless of request type. Apply the same normalization to the
overall scope inside callWithDomainAndShardScope because it emits the
direct persistence_latency_ns metric.
Per-domain (*_per_domain) and per-shard (*_per_shard) emissions are left
unchanged. task_category does not appear on those metric paths today, and
adding it there would be unnecessary label noise.
Signed-off-by: Stanislav Bychkov <stanislav.bychkov@netapp.com>
8fcfc1b to
3317c28
Compare
|
Hey, the code changes look good to me, I am checking we will need to do with the metrics rename internally since we have bunch of alerts/dashboards based on it, and our deployment will take time to roll out to all production clusters |
|
@neil-xie Thanks for checking. I'll add this clearly to the release notes so the rollout impact is visible. |
neil-xie
left a comment
There was a problem hiding this comment.
LGTM, thanks for fixing it.
As discussed, I will merge when we make the changes internally since it will impact existing dashboards/alerts
Apply the is_retry metered template to historytaskdlq_generated.go so the generated persistence wrappers are in sync after merging master. Signed-off-by: Stanislav Bychkov <stanislav.bychkov@netapp.com>
6d60683 to
9f415a6
Compare
Code Review ✅ Approved 1 resolved / 1 findingsNormalizes persistence metric labels and renames rollup metrics to resolve Prometheus label-set conflicts. The previously missing task category tag in the call() path is also addressed, resulting in consistent metric reporting. ✅ 1 resolved✅ Bug: Per-domain path in call() still lacks ensureTaskCategoryTag
Rules ✅ All requirements metRepository Rules
2 rules not applicable. Show all rules by commenting OptionsAuto-apply is off → Gitar will not commit updates to this branch. Comment with these commands to change the behavior for this request:
Was this helpful? React with 👍 / 👎 | Gitar |
Shaddoll
left a comment
There was a problem hiding this comment.
metered_execution.tmpl is not updated
<!-- If you are new to contributing or want a refresher, please read ./pull_request_guidance.md --> **What changed?** Normalized persistence metric label sets emitted by the metered persistence wrappers so Prometheus does not reject metrics registered under the same name with different label keys. - Defaulting task_category="none" on `persistence_response_payload_size`, `persistence_response_row_size` and `persistence_empty_response` when no task category applies. related to #7844 **Why?** follow up of #8064 Prometheus requires every metric name to use a consistent label-name set. Cadence persistence metrics could emit the same metric name from different wrapper paths with different labels, causing Prometheus reporter warnings and dropped metrics. **How did you test it?** Added a Prometheus-backed regression test that exercises persistence metered wrapper paths with different label dimensions and verifies no Prometheus registration errors are emitted. go test ./common/persistence/wrappers/metered **Potential risks** No. **Release notes** This change removes domain label/tag from `persistence_response_payload_size`, `persistence_response_row_size` and `persistence_empty_response` metrics and add `task_category` label/tag to these metrics with default value "none". Selectors by metric name should still match, but dashboards/alerts that aggregate or group by labels may need to explicitly aggregate away those new dimensions. **Documentation Changes**
What changed?
Normalized persistence metric label sets emitted by the metered persistence wrappers so Prometheus does not reject metrics registered under the same name with different label keys.
is_retryon metered persistence wrapper paths.task_category="none"on direct persistence metrics when no task category applies.Why?
#7844
Prometheus requires every metric name to use a consistent label-name set. Cadence persistence metrics could emit the same metric name from different wrapper paths with different labels, causing Prometheus reporter warnings and dropped metrics.
How did you test it?
Added a Prometheus-backed regression test that exercises persistence metered wrapper paths with different label dimensions and verifies no Prometheus registration errors are emitted.
go test ./common/persistence/wrappers/meteredPotential risks
This changes some persistence rollup metric names, which may require dashboard or alert updates for users relying on the old aggregate persistence metric names.
Release notes
This PR changes the persistence metrics contract.
Persistence rollup metrics were renamed to avoid prometheus label-set conflicts with directly emitted persistence metrics:
persistence_requestsrollup is nowpersistence_requests_rolluppersistence_latencyrollup is nowpersistence_latency_rolluppersistence_latency_nsrollup is nowpersistence_latency_ns_rollupThe direct
persistence_requests/persistence_latency/persistence_latency_nsmetrics still exist, but they are no longer reused as rollup targets. During a mixed-version rollout, dashboards may need to account for both old and new rollup names until all clusters are upgraded. This PR also normalizes labels on direct persistence metrics, adding labels likeis_retryandtask_category="none"where they were previously missing. Selectors by metric name should still match, but dashboards/alerts that aggregate or group by labels may need to explicitly aggregate away those new dimensions.Documentation Changes