Multi-Target Python Exporter

95 views
Skip to first unread message

Sebastian Halter

unread,
Sep 22, 2020, 5:03:23 AM9/22/20
to Prometheus Users
Hello everyone,

i am trying to collect some data via TL1 (basically telnet) because the manufacturer doesn't provide the temperature of the installed cards via SNMP.

I would like to recreate something like the SNMP-Exporter where i can specify my target in the URL it scrapes. Currently i am facing the issue, that my exporter runs once and then it runs into an error on every other request ("ValueError: Duplicated timeseriers in CollectorRegistry").

Does anyone have a basic example of a multi-target python exporter? 
I found in the documentation that python, go und java are the only client libraries that supports this approch but couldn't find any example of this on the python-client github site.

Ben Kochie

unread,
Sep 22, 2020, 5:31:43 AM9/22/20
to Sebastian Halter, Prometheus Users
You probably need to use the Custom Collector. This is similar to the "Const" metrics in the Go code.


--
You received this message because you are subscribed to the Google Groups "Prometheus Users" group.
To unsubscribe from this group and stop receiving emails from it, send an email to prometheus-use...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/prometheus-users/2f7dd7e7-ac2e-4cee-8f55-68390051efd9n%40googlegroups.com.

Sebastian Halter

unread,
Sep 22, 2020, 6:06:42 AM9/22/20
to Prometheus Users
Thats what i tried:

g = GaugeMetricFamily("cardTemperature", "Temperature of the installed card", labels=["card"])
class TL1Collector(object):
    def __init__(self, endpoint):
        self._endpoint = endpoint
   
    def collect(self):
        g.add_metric(self._endpoint, 2)
        yield g

@app.route("/temperature")
def handle_get():
    if "target" in request.args:
        target = request.args.get('target')
        REGISTRY.register(TL1Collector(target))
        return generate_latest(REGISTRY)
    else:
        return "Error: No target field provided. Please specify target."

I'm probably wrong the line "REGISTRY.register(TL1Collector(target))"  because i register the collector every time i call the endpoint and it is already registered from the http call before that one.
But i don't know where to register the custom collector to prevent that, because i need the target variable to be passed through.
If i only trigger it once at the start with a boolean it works serveral times and i dont get that error anymore but in only adds another metric to the output an keeps the old data from a different target parameter aswell.

Brian Brazil

unread,
Sep 22, 2020, 7:19:32 AM9/22/20
to Sebastian Halter, Prometheus Users
On Tue, 22 Sep 2020 at 11:06, Sebastian Halter <halter.se...@gmail.com> wrote:
Thats what i tried:

g = GaugeMetricFamily("cardTemperature", "Temperature of the installed card", labels=["card"])

This should be inside the collector.
 

class TL1Collector(object):
    def __init__(self, endpoint):
        self._endpoint = endpoint
   
    def collect(self):
        g.add_metric(self._endpoint, 2)
        yield g

@app.route("/temperature")
def handle_get():
    if "target" in request.args:
        target = request.args.get('target')
        REGISTRY.register(TL1Collector(target))

Create a registry per request, and register with that.

Brian
 
        return generate_latest(REGISTRY)
    else:
        return "Error: No target field provided. Please specify target."

I'm probably wrong the line "REGISTRY.register(TL1Collector(target))"  because i register the collector every time i call the endpoint and it is already registered from the http call before that one.
But i don't know where to register the custom collector to prevent that, because i need the target variable to be passed through.
If i only trigger it once at the start with a boolean it works serveral times and i dont get that error anymore but in only adds another metric to the output an keeps the old data from a different target parameter aswell.
sup...@gmail.com schrieb am Dienstag, 22. September 2020 um 11:31:43 UTC+2:
You probably need to use the Custom Collector. This is similar to the "Const" metrics in the Go code.


On Tue, Sep 22, 2020 at 11:03 AM Sebastian Halter <halter.se...@gmail.com> wrote:
Hello everyone,

i am trying to collect some data via TL1 (basically telnet) because the manufacturer doesn't provide the temperature of the installed cards via SNMP.

I would like to recreate something like the SNMP-Exporter where i can specify my target in the URL it scrapes. Currently i am facing the issue, that my exporter runs once and then it runs into an error on every other request ("ValueError: Duplicated timeseriers in CollectorRegistry").

Does anyone have a basic example of a multi-target python exporter? 
I found in the documentation that python, go und java are the only client libraries that supports this approch but couldn't find any example of this on the python-client github site.

--
You received this message because you are subscribed to the Google Groups "Prometheus Users" group.
To unsubscribe from this group and stop receiving emails from it, send an email to prometheus-use...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/prometheus-users/2f7dd7e7-ac2e-4cee-8f55-68390051efd9n%40googlegroups.com.

--
You received this message because you are subscribed to the Google Groups "Prometheus Users" group.
To unsubscribe from this group and stop receiving emails from it, send an email to prometheus-use...@googlegroups.com.

Sebastian Halter

unread,
Sep 22, 2020, 9:09:13 AM9/22/20
to Prometheus Users
Hi Brian,

thank you for you replay.
The first thing with "GaugeMetricFamily"  I figured out just a few minutes after my first reply.

To the second thing you pointed out:
Can you give me an example for how to create a registry per request?
If i try to use "req = REGISTRY()"  i get the error "'CollectorRegistry' object is not callable".

Sebastian Halter

unread,
Sep 22, 2020, 9:49:32 AM9/22/20
to Prometheus Users
It's working now:
registry = CollectorRegistry()
registry.register(CustomCollector(target))

Thank you for your help!

Reply all
Reply to author
Forward
0 new messages