prometheus / client_python

Prometheus instrumentation library for Python applications
Apache License 2.0
3.96k stars 798 forks source link

How to clear a particular metric's all labels and values #277

Closed nizamsp closed 6 years ago

nizamsp commented 6 years ago

According to the prometheus documentation in the below link, https://prometheus.io/docs/instrumenting/writing_clientlibs/#labels

Metrics with labels SHOULD support a remove() method with the same signature as labels() that will remove a Child from the metric no longer exporting it, and a clear() method that removes all Children from the metric. These invalidate caching of Children.

This seems to be missing in this python library.

my_gauge_metric = Gauge(..)

my_gauage_metric._metrics.clear() would do the job, but I felt little discomfort in using underscore variables outside. Also, its not thread safe since i should have used self._lock

Would be great if this is fixed in the new updates of this library.

Clearing of a particular metric is needed in Guage since the python layer will constatntly give the old Guage values even though its not generated in the latest time.

brian-brazil commented 6 years ago

When trying to write an exporter you should not be using direct instrumentation, see https://github.com/prometheus/client_python#custom-collectors for how to handle this.

sebastian-bello commented 3 years ago

Hi, from the custom collector's documentation I don't see how to clear labels and values, can anybody help me? Regards, Sebastian-

csmarchbanks commented 3 years ago

Right now you can use remove(labelvalues) on a metric to remove them. https://github.com/prometheus/client_python/pull/642, is looking to add the clear() method mentioned in this issue.

sebastian-bello commented 3 years ago

Hi Chris,

thanks for your swift response. My test example:

g2 = GaugeMetricFamily('g2', 'Help text', labels=['country', 'tablespace']) g2.add_metric(['SV', 'system'], 1.7) g2.remove(['SV', 'system']) yield g2

It throws the following error: g2.remove(['SV', 'system']) AttributeError: 'GaugeMetricFamily' object has no attribute 'remove'

Thanks, Sebastian-

csmarchbanks commented 3 years ago

Ahh, yes, I see what you mean now. *MetricFamily does not have the remove method as they are usually created as part of each collect, not kept around across multiple scrapes. For an individual scrape, is there a concrete use case where you would need to remove a child? Some preprocessing should give you every label value to be exposed rather than adding and removing as you go.

sebastian-bello commented 3 years ago

I'm writing an exporter to monitor a database. If a database is down, the metrics shouldn't be available. There's another scenario: you can have a metric related to an object which doesn't exist anymore (e.g. a tablespace gets dropped). What approach do you suggest?

sebastian-bello commented 3 years ago

Now I understand your comment, thanks!

TechDPi commented 2 years ago

Now I understand your comment, thanks!

How did you do it ? i have the same problem, when db is down i need to remove the gauge metric related to it. Any suggestion ?

sebastian-bello commented 2 years ago

Recreating it every time.

TechDPi commented 2 years ago

Recreating it every time.

in my use case i have some metrics that are exported and then over a period of time, need to be removed (ie the sql instance is stopped or deleted). Recreating every time i dont see it as a solution in my cause , cause the unwanted metric still there and i want to be able to remove it.

I see you tried that approch with the remove() and saw in the documentation that there is :

` def remove(self, *labelvalues: Any) -> None: if not self._labelnames: raise ValueError('No label names were set when constructing %s' % self)

    """Remove the given labelset from the metric."""
    if len(labelvalues) != len(self._labelnames):
        raise ValueError('Incorrect label count (expected %d, got %s)' % (len(self._labelnames), labelvalues))
    labelvalues = tuple(str(l) for l in labelvalues)
    with self._lock:
        del self._metrics[labelvalues]

def clear(self) -> None:
    """Remove all labelsets from the metric"""
    with self._lock:
        self._metrics = {}`

How can I use this ?

sebastian-bello commented 2 years ago

Hi,

At that time I tried with "remove" but it didn't work so I went for the other approach. Regards, Sebastian-

TechDPi commented 2 years ago

Hi,

At that time I tried with "remove" but it didn't work so I went for the other approach. Regards, Sebastian-

Ok no worries, thanks

thakurrishabh commented 1 year ago

You can remove a label simply by using the remove method as follows:

x=Gauge(metric_name, metric_description, label_names)

x.remove(label_values_list)

Note:- you must provide all values of the label instance you want to delete and the order must match the label_names that were declared when the gauge metric was created. otherwise, you'll get an exception

if you want to delete everything just use x.clear()

infa-aramesh commented 1 year ago

Follow up on this, can I clear other metric types such as Counters and Histograms. I am dealing with a use-case where the cardinality is around 10K (number of unique labels), I dont want to store all the children in memory of my service instance, but when I clear a counter the current value will ultimately go to 0 and I think this may cause issues when I use increase method to visualize this metric. Please advice.