Search code examples
python-3.xprometheusconnexion

Using Prometheus with Connexion - ValueError: Duplicated timeseries in CollectorRegistry


I get the following error message when using prometheus with connexion using python3.6/3.7:

ValueError: Duplicated timeseries in CollectorRegistry: {'app_request_processing_seconds_sum', 'app_request_processing_seconds_count', 'app_request_processing_seconds_created', 'app_request_processing_seconds'}

#!/usr/bin/env python3
from gevent import monkey  # noqa

# monkey.patch_all()  # noqa

import json
import os
import connexion
import datetime
import logging

from connexion import NoContent
from prometheus_client import Summary, Counter

logger = logging.getLogger(__name__)

REQUEST_TIME = Summary('app_request_processing_seconds', 'time spent processing')
REQUEST_COUNTER = Counter('app_request_count', 'number of requests')

@REQUEST_TIME.time()
def get_health():
    try:
        'Hello'
    except Exception:
        return connexion.problem(503, "Service Unavailable", "Unhealthy")
    else:
        return "Healthy"


logging.basicConfig(level=logging.INFO)
app = connexion.App(__name__)
app.add_api("swagger.yaml")

if __name__ == "__main__":
    # run our standalone gevent server
    app.run(port=8080, server="gevent")

There is a swagger.yaml that is identical to: https://github.com/hjacobs/connexion-example-redis-kubernetes/blob/master/swagger.yaml

Any help would be great


Solution

  • As a guess, you have named your file app.py. What happens it that when the swagger is loaded, the handling is specified as app.get_health:

    paths:
      /health:
        get:
          operationId: app.get_health
    

    And it loads (a second time) app.py to import the get_health() function.

    The reason it that the main file is loaded as __main__ module and thus get loaded a second time; see this other question for more information. Therefore, you end-up with defining your Prometheus metrics twice which doesn't sit well with the collector.

    The most simple solution is to rename your file and implement your application in another file named app.py.