Okay thanks to the hint in this answer by @Xitrum "deregister method" I found a solution:

collectors = list(REGISTRY._collector_to_names.keys())
for collector in collectors:
    REGISTRY.unregister(collector)

Now all tests can start with their own registry:

def test_metrics_endpoint_availability():
    app = create_app()
    FlaskInstrumentator(app).instrument()
    client = app.test_client()

    response = client.get("/")
    response = client.get("/metrics")
    
    # Test stuff
    

def test_grouped_status_codes():
    app = create_app()
    FlaskInstrumentator(app).instrument()
    client = app.test_client()

    client.get("/does_not_exist")  # Should be ignored.
    client.get("/does_not_exist")  # Should be ignored.
    client.post("/")
    client.post("/")
    
    # Test stuff

Edit 2023

Here is a helper function I use for unit tests atm:

from prometheus_client import REGISTRY

def reset_prom_collectors() -> None:
    """Resets collectors in the default Prometheus registry.

    Modifies the `REGISTRY` registry. Supposed to be called at the beginning
    of individual test functions. Else registry is reused across test functions
    and so we can run into errors like duplicate metrics or unexpected values
    for metrics.
    """

    # Unregister all collectors.
    collectors = list(REGISTRY._collector_to_names.keys())
    print(f"before unregister collectors={collectors}")
    for collector in collectors:
        REGISTRY.unregister(collector)
    print(f"after unregister collectors={list(REGISTRY._collector_to_names.keys())}")

    # Import default collectors.
    from prometheus_client import gc_collector, platform_collector, process_collector

    # Re-register default collectors.
    process_collector.ProcessCollector()
    platform_collector.PlatformCollector()
    gc_collector.GCCollector()

    print(f"after re-register collectors={list(REGISTRY._collector_to_names.keys())}")
Answer from trallnag on Stack Overflow
🌐
GitHub
github.com › prometheus › client_python › blob › master › prometheus_client › registry.py
client_python/prometheus_client/registry.py at master · prometheus/client_python
Prometheus instrumentation library for Python applications - client_python/prometheus_client/registry.py at master · prometheus/client_python
Author: prometheus
Top answer
1 of 1
7

Okay thanks to the hint in this answer by @Xitrum "deregister method" I found a solution:

collectors = list(REGISTRY._collector_to_names.keys())
for collector in collectors:
    REGISTRY.unregister(collector)

Now all tests can start with their own registry:

def test_metrics_endpoint_availability():
    app = create_app()
    FlaskInstrumentator(app).instrument()
    client = app.test_client()

    response = client.get("/")
    response = client.get("/metrics")
    
    # Test stuff
    

def test_grouped_status_codes():
    app = create_app()
    FlaskInstrumentator(app).instrument()
    client = app.test_client()

    client.get("/does_not_exist")  # Should be ignored.
    client.get("/does_not_exist")  # Should be ignored.
    client.post("/")
    client.post("/")
    
    # Test stuff

Edit 2023

Here is a helper function I use for unit tests atm:

from prometheus_client import REGISTRY

def reset_prom_collectors() -> None:
    """Resets collectors in the default Prometheus registry.

    Modifies the `REGISTRY` registry. Supposed to be called at the beginning
    of individual test functions. Else registry is reused across test functions
    and so we can run into errors like duplicate metrics or unexpected values
    for metrics.
    """

    # Unregister all collectors.
    collectors = list(REGISTRY._collector_to_names.keys())
    print(f"before unregister collectors={collectors}")
    for collector in collectors:
        REGISTRY.unregister(collector)
    print(f"after unregister collectors={list(REGISTRY._collector_to_names.keys())}")

    # Import default collectors.
    from prometheus_client import gc_collector, platform_collector, process_collector

    # Re-register default collectors.
    process_collector.ProcessCollector()
    platform_collector.PlatformCollector()
    gc_collector.GCCollector()

    print(f"after re-register collectors={list(REGISTRY._collector_to_names.keys())}")
🌐
ProgramCreek
programcreek.com › python › example › 105488 › prometheus_client.CollectorRegistry
Python Examples of prometheus_client.CollectorRegistry
You may also want to check out all available functions/classes of the module prometheus_client , or try the search function . ... def setUp(self): self.registry = prometheus_client.CollectorRegistry() self.some_gauge = prometheus_client.Gauge( "some_gauge", "Some gauge.", registry=self.registry ) self.some_gauge.set(42) self.some_labelled_gauge = prometheus_client.Gauge( "some_labelled_gauge", "Some labelled gauge.", ["labelred", "labelblue"], registry=self.registry, ) self.some_labelled_gauge.labels("pink", "indigo").set(1) self.some_labelled_gauge.labels("pink", "royal").set(2) self.some_labelled_gauge.labels("carmin", "indigo").set(3) self.some_labelled_gauge.labels("carmin", "royal").set(4) self.test_case = SomeTestCase()
🌐
Uio
studmed.uio.no › elaring › voila › venv › lib › python3.9 › site-packages › prometheus_client-0.12.0.dist-info › METADATA
https://studmed.uio.no/elaring/voila/venv/lib/pyth...
```python from prometheus_client import CollectorRegistry, Gauge, push_to_gateway from prometheus_client.exposition import basic_auth_handler def my_auth_handler(url, method, timeout, headers, data): username = 'foobar' password = 'secret123' return basic_auth_handler(url, method, timeout, headers, data, username, password) registry = CollectorRegistry() g = Gauge('job_last_success_unixtime', 'Last time a batch job successfully finished', registry=registry) g.set_to_current_time() push_to_gateway('localhost:9091', job='batchA', registry=registry, handler=my_auth_handler) ``` ## Bridges It is also possible to expose metrics to systems other than Prometheus.
🌐
PyPI
pypi.org › project › prometheus-client › 0.14.0
Prometheus Python Client
A separate registry is used, as the default registry may contain other metrics such as those from the Process Collector. The Pushgateway allows ephemeral and batch jobs to expose their metrics to Prometheus. from prometheus_client import CollectorRegistry, Gauge, push_to_gateway registry = CollectorRegistry() g = Gauge('job_last_success_unixtime', 'Last time a batch job successfully finished', registry=registry) g.set_to_current_time() push_to_gateway('localhost:9091', job='batchA', registry=registry)
      » pip install prometheus-client
    
Published: Apr 05, 2022
Version: 0.14.0
🌐
PyPI
pypi.org › project › prometheus-client
prometheus-client · PyPI
Python client for the Prometheus monitoring system.
      » pip install prometheus-client
    
Published: Apr 09, 2026
Version: 0.25.0
Top answer
1 of 1
1

The same problem I had

In my personal project, I have the same problem and I adopted this solution.

In CollectorRegistry, the class where you store your metrics, there's no method to get Collector object (Collector is the parent class of any metric like Counter, Gauge, Histogram, etc.).

The restricted_registry method creates a subset (a restricted registry) where you have the Metrics that have that name and labels. But "it's experimental", so be careful. It doesn't solve my (our) problem. Because if a metric has a label, you also have to specify its value, and sometimes you can't know it (for example, if you're counting how many https requests you've made):

def restricted_registry(self, names: Iterable[str]) -> "RestrictedRegistry":
    """Returns object that only collects some metrics.

    Returns an object which upon collect() will return
    only samples with the given names.

    Intended usage is:
        generate_latest(REGISTRY.restricted_registry(['a_timeseries']))

    Experimental."""
    names = set(names)
    return RestrictedRegistry(names, self)

So if you're coding a project, and not its tests, don't use it.


My solutions adopted

First solution (fast implementation)

The first is to store all your metrics inside a custom class (eg PrometheusMetrics) where you have a dictionary with all Metrics object, for example (return objects are custom for my case, if you want to use a parent class, writes Collector):

def register_new_metrics(self, metrics: list[Counter | Gauge | Histogram | Summary | Enum]):
    for metric in metrics:
        for metric_obj in metric.describe():
            # Register the new metric inside the registry
            self.get_registry().register(metric)
            # Add it to the dict
            self._metric[metric_obj.name] = metric

And you can invoke it in this way:

self.register_new_metrics([
            Counter(f'name', "documentation", ['label1','label2']),
            Histogram(f'name2', "documentation", ['label1', 'label2', 'label3'])
])

This way you can have a simple get('metric_name') method that returns a requested metric object. This solution doesn't cause any problems if you only create metrics once at the same time as you create a CollectorRegistry (e.g.).

But if you want to create metrics at runtime, don't use this solution. Because Prometheus uses a threading.Lock (doc) inside the CollectorRegistry class and uses it for a lot of operations.

Second solution (more logical than the first)

The second, in my opinion, is another more logical solution. You can create a subclass of CollectorRegistry and create your own method where you get metrics using the protected field self._names_to_collectors and lock the thread with self._lock. After that you can register your own subclass using "Custom Collectors" way (doc):

from prometheus_client import REGISTRY

REGISTRY.register(CustomRegistry())

class CustomRegistry(CollectorRegistry):
    # ...
    def get_metric(metric: str) -> Collector:
        with self._lock:
            self._names_to_collectors.get(metric)
    # ...

If anyone has a better solution, please write! I am also interested in this topic.

🌐
GitHub
github.com › valohai › prometheus-client-python
GitHub - valohai/prometheus-client-python: Prometheus instrumentation library for Python applications · GitHub
A separate registry is used, as the default registry may contain other metrics such as those from the Process Collector. The Pushgateway allows ephemeral and batch jobs to expose their metrics to Prometheus. from prometheus_client import CollectorRegistry, Gauge, push_to_gateway registry = CollectorRegistry() g = Gauge('job_last_success_unixtime', 'Last time a batch job successfully finished', registry=registry) g.set_to_current_time() push_to_gateway('localhost:9091', job='batchA', registry=registry)
Author: valohai
Find elsewhere
🌐
Prometheus
prometheus.io › docs › instrumenting › writing_clientlibs
Writing client libraries | Prometheus
Client libraries are ENCOURAGED to offer ways that make it easy for users to unit-test their use of the instrumentation code. For example, the CollectorRegistry.get_sample_value in Python.
🌐
client_python
prometheus.github.io › client_python › collector
Collector | client_python
April 24, 2026 - Labels on python_info: version, implementation, major, minor, patchlevel. On Jython, additional labels are added: jvm_version, jvm_release, jvm_vendor, jvm_name. The module-level PLATFORM_COLLECTOR is the default instance registered with REGISTRY.
🌐
client_python
prometheus.github.io › client_python › restricted-registry
Restricted registry | client_python
November 14, 2023 - If you’re directly using generate_latest, you can use the function restricted_registry(). curl --get --data-urlencode "name[]=python_gc_objects_collected_total" --data-urlencode "name[]=python_info" http://127.0.0.1:9200/metrics · from prometheus_client import generate_latest generate_latest(REGISTRY.restricted_registry(['python_gc_objects_collected_total', 'python_info'])) # HELP python_info Python platform information # TYPE python_info gauge python_info{implementation="CPython",major="3",minor="9",patchlevel="3",version="3.9.3"} 1.0 # HELP python_gc_objects_collected_total Objects collected during gc # TYPE python_gc_objects_collected_total counter python_gc_objects_collected_total{generation="0"} 73129.0 python_gc_objects_collected_total{generation="1"} 8594.0 python_gc_objects_collected_total{generation="2"} 296.0 ·
🌐
client_python
prometheus.github.io › client_python › collector › custom
Custom Collectors | client_python
May 4, 2026 - Sometimes it is not possible to directly instrument code, as it is not in your control. This requires you to proxy metrics from other systems. To do so you need to create a custom collector, for example: from prometheus_client.core import GaugeMetricFamily, CounterMetricFamily, REGISTRY from prometheus_client.registry import Collector class CustomCollector(Collector): def collect(self): yield GaugeMetricFamily('my_gauge', 'Help text', value=7) c = CounterMetricFamily('my_counter_total', 'Help text', labels=['foo']) c.add_metric(['bar'], 1.7) c.add_metric(['baz'], 3.8) yield c REGISTRY.register(CustomCollector()) SummaryMetricFamily, HistogramMetricFamily and InfoMetricFamily work similarly.
🌐
Better Stack
betterstack.com › community › guides › monitoring › prometheus-python-metrics
Python Monitoring with Prometheus (Beginner's Guide) | Better Stack Community
February 17, 2025 - For each counter metric in your application, Prometheus Python client creates two metrics: ... from flask import Flask, request from prometheus_client import ( CollectorRegistry, generate_latest, CONTENT_TYPE_LATEST, Counter, disable_created_metrics, ) from dotenv import load_dotenv import os load_dotenv() disable_created_metrics() app = Flask(__name__) registry = CollectorRegistry()
🌐
DeepWiki
deepwiki.com › prometheus › client_python
prometheus/client_python | DeepWiki
April 24, 2025 - A registry system for collecting and organizing metrics · Multiple exposition methods to make metrics available to Prometheus servers · Built-in collectors for common metrics (process stats, garbage collection, platform information) ...
🌐
Google Groups
groups.google.com › g › prometheus-users › c › MJERB7uwB9k
How to add custom path to Python prometheus_client
from flask import Flask from werkzeug.middleware.dispatcher import DispatcherMiddleware from prometheus_client import make_wsgi_app from prometheus_client.core import REGISTRY app = Flask(__name__) def health(environ, start_response): headers = [("content-type", "application/json")] status = "200 OK" output = json.dumps({"data": {"status": "running"}) output_encoded = output.encode("utf-8") start_response(status, headers) return [output_encoded] app.wsgi_app = DispatcherMiddleware( app.wsgi_app, {"/metrics": make_wsgi_app(), "/health": util.health} ) ```
🌐
PyPI
pypi.org › project › pyprometheus
Client Challenge
JavaScript is disabled in your browser · Please enable JavaScript to proceed · A required part of this site couldn’t load. This may be due to a browser extension, network issues, or browser settings. Please check your connection, disable any ad blockers, or try using a different browser
🌐
Medium
ikod.medium.com › custom-exporter-with-prometheus-b1c23cb24e7a
Custom Exporter with Prometheus. Prometheus is an excellent tool for… | by Jakir Patel | Medium
June 8, 2023 - Writing the custom exporter in python for Prometheus. ... You can add your custom logic with the exporter. ... import time from prometheus_client.core import GaugeMetricFamily, REGISTRY, CounterMetricFamily from prometheus_client import start_http_server class CustomCollector(object): def __init__(self): pass def collect(self): g = GaugeMetricFamily("MemoryUsage", 'Help text', labels=['instance']) g.add_metric(["instance01.us.west.local"], 20) yield g c = CounterMetricFamily("HttpRequests", 'Help text', labels=['app']) c.add_metric(["example"], 2000) yield c if __name__ == '__main__': start_http_server(8000) REGISTRY.register(CustomCollector()) while True: time.sleep(1)
🌐
client_python
prometheus.github.io › client_python › multiprocess
Multiprocess Mode | client_python
June 23, 2026 - If a registry with metrics registered is used by a MultiProcessCollector duplicate metrics may be exported, one for multiprocess, and one for the process serving the request. from prometheus_client import multiprocess from prometheus_client import generate_latest, CollectorRegistry, CONTENT_TYPE_LATEST, Counter MY_COUNTER = Counter('my_counter', 'Description of my counter') # Expose metrics.
🌐
GitHub
github.com › faucetsdn › python3-prometheus-client › blob › master › prometheus_client › registry.py
python3-prometheus-client/prometheus_client/registry.py at master · faucetsdn/python3-prometheus-client
"""Metric collector registry. · Collectors must have a no-argument method 'collect' that returns a list of · Metric objects. The returned metrics should be consistent with the Prometheus · exposition formats.
Author: faucetsdn