Skip to content

Conversation

hazel-shen
Copy link

@hazel-shen hazel-shen commented Aug 13, 2025

Description
Fixes #1118
This PR introduces a new remove_by_labels() method to allow removing metric samples by matching a set of label values.

Changes

  • Added remove_by_labels() to MetricWrapperBase for selective deletion of metrics by label.
  • Included validation for label names and types.
  • Added safeguards for multi-process mode (warning issued if used).
  • Kept the return value consistent with remove(): returns None, and acts as a no-op if no series match.

Motivation
Currently, the Python client does not support removing metrics with specific label values without clearing the whole metric. This feature enables more granular control, which can be useful for scenarios such as:

  • Cleaning up metrics for tenants after deprovisioning
  • Removing outdated or irrelevant labeled data without impacting other metrics

Example Usage

from prometheus_client import Counter

c = Counter('my_counter', 'Example counter', ['tenant', 'status'])
c.labels(tenant='acme', status='ok').inc()
c.labels(tenant='acme', status='fail').inc()

# remove all series with tenant='acme', regardless of status
c.remove_by_labels({'tenant': 'acme'})

@csmarchbanks Would you take a look when you have a chance?

Signed-off-by: Hazel <hazel@hazel.localdomain>
Copy link
Member

@csmarchbanks csmarchbanks left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks! A couple comments/questions to start with

@@ -203,6 +203,41 @@ def remove(self, *labelvalues: Any) -> None:
if labelvalues in self._metrics:
del self._metrics[labelvalues]

def remove_matching(self, partial: dict[str, str]) -> int:
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What would you think of remove_partial_match for the name of this function? When I first see matching I think that all labelnames/values need to match to be removed not a partial. The name of the variable helps, but could also then be labels instead of partial which helps with confusion around thinking it could be a partial function.

Copy link
Author

@hazel-shen hazel-shen Aug 18, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the suggestion! I’ve renamed the method to remove_by_labels and the argument to labels.
I also added a short docstring to clarify that this removes series where the provided (key, value) pairs are a partial match of the labelset.
This should reduce confusion with full-match semantics.


pos_filter = {self._labelnames.index(k): str(v) for k, v in partial.items()}

deleted = 0
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What's the reasoning for returning the number of deleted items? We don't do that in remove today, but if there is a good use case I am not opposed.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good point on consistency. The initial version returned the number of deleted series, but I’ve updated it to return None, matching the behavior of remove(): idempotent and a no-op if nothing matches.
If there’s a strong use case for counts in the future, I’m happy to follow up with a separate helper that reports the number of removed series, without changing the main API.

Hazel added 2 commits August 18, 2025 17:03
Signed-off-by: Hazel <hazel@hazel.localdomain>
Signed-off-by: Hazel <hazel@hazel.localdomain>
@hazel-shen hazel-shen force-pushed the feature/remove-matching branch from 213940c to fc3fc1e Compare August 18, 2025 10:19
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Implement deletion of Gauge metrics based on partially specified labels
3 participants