Prometheus integration for Starlette.

Overview

Starlette Prometheus

Build Status codecov Package Version PyPI Version

Introduction

Prometheus integration for Starlette.

Requirements

  • Python 3.6+
  • Starlette 0.9+

Installation

$ pip install starlette-prometheus

Usage

A complete example that exposes prometheus metrics endpoint under /metrics/ path.

from starlette.applications import Starlette
from starlette_prometheus import metrics, PrometheusMiddleware

app = Starlette()

app.add_middleware(PrometheusMiddleware)
app.add_route("/metrics/", metrics)

Metrics for paths that do not match any Starlette route can be filtered by passing filter_unhandled_paths=True argument to add_middleware method.

Contributing

This project is absolutely open to contributions so if you have a nice idea, create an issue to let the community discuss it.

Comments
  • Releasing new version with updated prometheus-client dep?

    Releasing new version with updated prometheus-client dep?

    Hello! I have a deps conflict due to the fact that current version fron pypi 0.7.0 is still list prometheus-client dep as <8.0 in poetry, but another package needs prometheus-client >=8.0. I see that updated dependency is already merged since august, is it possible to release something like v0.7.1 with this dependency?

    opened by DMantis 4
  • Detail how to interact with visualizations of Prometheus

    Detail how to interact with visualizations of Prometheus

    I'm a new user to Starlette, and looking to monitor some Gunicorn processes for my Starlette server. This library looks promising, and I've successfully integrated and viewed the plain text stats at /metrics.

    However, I'd like a better visualization of these performance metrics. I've looked at integrating Grafana, but am having difficulty (https://prometheus.io/docs/visualization/grafana/ looks promising).

    I'm looking for the most basic level of monitoring; the console templates at https://prometheus.io/docs/visualization/consoles/ look promising.

    It'd be really nice to have the following:

    • A couple sentences describing the configuration that Grafana needs to use starlette-prometheus (which I suspect is just prometheus).
    • Basic integration with visualizations. I'd like to see some basics graphs of the stats at /metrics with a simple HTML page. I think I'd like to see an interface like this:
    from starlette.applications import Starlette
    from starlette_prometheus import metrics, metric_viz, PrometheusMiddleware
    
    app = Starlette()
    app.add_middleware(PrometheusMiddleware)
    app.add_route("/metrics/", metrics)
    app.add_route("/metric-viz/", metric_viz)
    
    opened by stsievert 4
  • [FEATURE] Path template instead of actual path in metrics

    [FEATURE] Path template instead of actual path in metrics

    Hi, there!

    Thanks for a great middleware! I've been using it a while and now I want to show response time by url in grafana. It works good with regular paths, like /users, but not with templated paths like /users/{id} because in /metrics they appear as actual paths (/users/1, /users/2, etc...)

    I've made a quick pull request https://github.com/perdy/starlette-prometheus/pull/6 for this. Let me know what you think of this idea and feel free to decline it if anything

    opened by unmade 4
  • [FEATURE] Group unhandled paths

    [FEATURE] Group unhandled paths

    In order to reduce cardinality of prometheus metrics and labels, this pull request adds an option to group all metrics that do not match any route.

    This solves the problem of random path requests generating unwanted metrics (each requested path generates around 23 lines of metrics), which could potentially be a big issue if exposed to the internet.

    opened by tsotnikov 3
  • Record exceptions as 500 responses

    Record exceptions as 500 responses

    This way it will be possible to count the number of 5xx responses with: sum(rate(starlette_responses_total{status_code=~"50."}[1m])) query.

    Fixes https://github.com/perdy/starlette-prometheus/issues/21

    released 
    opened by matino 2
  • Error when raising exception in FastAPI: UnboundLocalError: local variable 'status_code' referenced before assignment

    Error when raising exception in FastAPI: UnboundLocalError: local variable 'status_code' referenced before assignment

    Hi,

    I'm seeing an issue with FastAPI, where I am raising an exception in a route handler. I've created a small reproducer:

    from fastapi import FastAPI
    from starlette.middleware import Middleware
    from starlette_prometheus import PrometheusMiddleware
    
    
    middleware = [
        Middleware(PrometheusMiddleware)
    ]
    
    app = FastAPI(middleware=middleware)
    
    @app.get("/")
    def read_root():
        raise ValueError("Test error")
        # return {"Hello": "World"}
    

    Here's the output from running the reproducer and calling it with curl localhost:8000/:

    output
    $ uvicorn example:app                             
    INFO:     Started server process [5099]
    INFO:     Waiting for application startup.
    INFO:     Application startup complete.
    INFO:     Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit)
    ERROR:    Exception in ASGI application
    Traceback (most recent call last):
      File "/Users/krisb/Code/temp/starlette-prometheus-repro/.venv/lib/python3.8/site-packages/uvicorn/protocols/http/h11_impl.py", line 373, in run_asgi
        result = await app(self.scope, self.receive, self.send)
      File "/Users/krisb/Code/temp/starlette-prometheus-repro/.venv/lib/python3.8/site-packages/uvicorn/middleware/proxy_headers.py", line 75, in __call__
        return await self.app(scope, receive, send)
      File "/Users/krisb/Code/temp/starlette-prometheus-repro/.venv/lib/python3.8/site-packages/fastapi/applications.py", line 208, in __call__
        await super().__call__(scope, receive, send)
      File "/Users/krisb/Code/temp/starlette-prometheus-repro/.venv/lib/python3.8/site-packages/starlette/applications.py", line 112, in __call__
        await self.middleware_stack(scope, receive, send)
      File "/Users/krisb/Code/temp/starlette-prometheus-repro/.venv/lib/python3.8/site-packages/starlette/middleware/errors.py", line 159, in __call__
        await self.app(scope, receive, _send)
      File "/Users/krisb/Code/temp/starlette-prometheus-repro/.venv/lib/python3.8/site-packages/starlette/middleware/base.py", line 57, in __call__
        task_group.cancel_scope.cancel()
      File "/Users/krisb/Code/temp/starlette-prometheus-repro/.venv/lib/python3.8/site-packages/anyio/_backends/_asyncio.py", line 572, in __aexit__
        raise ExceptionGroup(exceptions)
    anyio._backends._asyncio.ExceptionGroup: 2 exceptions were raised in the task group:
    ----------------------------
    Traceback (most recent call last):
      File "/Users/krisb/Code/temp/starlette-prometheus-repro/.venv/lib/python3.8/site-packages/starlette/middleware/base.py", line 30, in coro
        await self.app(scope, request.receive, send_stream.send)
      File "/Users/krisb/Code/temp/starlette-prometheus-repro/.venv/lib/python3.8/site-packages/starlette/exceptions.py", line 82, in __call__
        raise exc
      File "/Users/krisb/Code/temp/starlette-prometheus-repro/.venv/lib/python3.8/site-packages/starlette/exceptions.py", line 71, in __call__
        await self.app(scope, receive, sender)
      File "/Users/krisb/Code/temp/starlette-prometheus-repro/.venv/lib/python3.8/site-packages/starlette/routing.py", line 656, in __call__
        await route.handle(scope, receive, send)
      File "/Users/krisb/Code/temp/starlette-prometheus-repro/.venv/lib/python3.8/site-packages/starlette/routing.py", line 259, in handle
        await self.app(scope, receive, send)
      File "/Users/krisb/Code/temp/starlette-prometheus-repro/.venv/lib/python3.8/site-packages/starlette/routing.py", line 61, in app
        response = await func(request)
      File "/Users/krisb/Code/temp/starlette-prometheus-repro/.venv/lib/python3.8/site-packages/fastapi/routing.py", line 226, in app
        raw_response = await run_endpoint_function(
      File "/Users/krisb/Code/temp/starlette-prometheus-repro/.venv/lib/python3.8/site-packages/fastapi/routing.py", line 161, in run_endpoint_function
        return await run_in_threadpool(dependant.call, **values)
      File "/Users/krisb/Code/temp/starlette-prometheus-repro/.venv/lib/python3.8/site-packages/starlette/concurrency.py", line 39, in run_in_threadpool
        return await anyio.to_thread.run_sync(func, *args)
      File "/Users/krisb/Code/temp/starlette-prometheus-repro/.venv/lib/python3.8/site-packages/anyio/to_thread.py", line 28, in run_sync
        return await get_asynclib().run_sync_in_worker_thread(func, *args, cancellable=cancellable,
      File "/Users/krisb/Code/temp/starlette-prometheus-repro/.venv/lib/python3.8/site-packages/anyio/_backends/_asyncio.py", line 818, in run_sync_in_worker_thread
        return await future
      File "/Users/krisb/Code/temp/starlette-prometheus-repro/.venv/lib/python3.8/site-packages/anyio/_backends/_asyncio.py", line 754, in run
        result = context.run(func, *args)
      File "./example.py", line 14, in read_root
        raise ValueError("Test error")
    ValueError: Test error
    ----------------------------
    Traceback (most recent call last):
      File "/Users/krisb/Code/temp/starlette-prometheus-repro/.venv/lib/python3.8/site-packages/starlette_prometheus/middleware.py", line 53, in dispatch
        response = await call_next(request)
      File "/Users/krisb/Code/temp/starlette-prometheus-repro/.venv/lib/python3.8/site-packages/starlette/middleware/base.py", line 35, in call_next
        message = await recv_stream.receive()
      File "/Users/krisb/Code/temp/starlette-prometheus-repro/.venv/lib/python3.8/site-packages/anyio/streams/memory.py", line 89, in receive
        await receive_event.wait()
      File "/Users/krisb/Code/temp/starlette-prometheus-repro/.venv/lib/python3.8/site-packages/anyio/_backends/_asyncio.py", line 1655, in wait
        await checkpoint()
      File "/Users/krisb/Code/temp/starlette-prometheus-repro/.venv/lib/python3.8/site-packages/anyio/_backends/_asyncio.py", line 440, in checkpoint
        await sleep(0)
      File "/Users/krisb/.pyenv/versions/3.8.9/lib/python3.8/asyncio/tasks.py", line 644, in sleep
        await __sleep0()
      File "/Users/krisb/.pyenv/versions/3.8.9/lib/python3.8/asyncio/tasks.py", line 638, in __sleep0
        yield
    asyncio.exceptions.CancelledError
    
    During handling of the above exception, another exception occurred:
    
    Traceback (most recent call last):
      File "/Users/krisb/Code/temp/starlette-prometheus-repro/.venv/lib/python3.8/site-packages/starlette/middleware/base.py", line 55, in __call__
        response = await self.dispatch_func(request, call_next)
      File "/Users/krisb/Code/temp/starlette-prometheus-repro/.venv/lib/python3.8/site-packages/starlette_prometheus/middleware.py", line 65, in dispatch
        RESPONSES.labels(method=method, path_template=path_template, status_code=status_code).inc()
    UnboundLocalError: local variable 'status_code' referenced before assignment
    
    `pip freeze` output
    anyio==3.4.0
    asgiref==3.4.1
    click==8.0.3
    fastapi==0.70.1
    h11==0.12.0
    idna==3.3
    prometheus-client==0.11.0
    pydantic==1.9.0
    sniffio==1.2.0
    starlette==0.16.0
    starlette-prometheus==0.8.0
    typing-extensions==4.0.1
    uvicorn==0.16.0
    

    It seems like starlette has started raising asyncio.exceptions.CancelledError, which is not based on Exception caught here

    https://github.com/perdy/starlette-prometheus/blob/672ffc363041924956e2cbc7c07bea6ec0dbd5a5/starlette_prometheus/middleware.py#L54

    but rather BaseException.

    I believe this was introduced in version 0.15.0 of Starlette, in PR https://github.com/encode/starlette/pull/1157.

    I've tried to change the exception catching to include both – i.e. except (Exception, asyncio.exceptions.CancelledError), this seems to revert the behavior to the expected.

    opened by kbakk 1
  • Fix:

    Fix: "UnboundLocalError: local variable 'status_code' referenced before assignment"

    Not all of the errors thrown by asyncio inherit from Exception. I was throwing an exception in a route to test my sentry intergration and it threw a asyncio.exceptions.CancelledError which inherits from BaseException (see https://github.com/python/cpython/blob/3.9/Lib/asyncio/exceptions.py#L9)

    opened by InsidersByte 1
  • How do i disable logging for specific path

    How do i disable logging for specific path

    I am using PrometheusMiddleware from starlette_prometheus ever second or the, it keeps generating log, this grows the log file.

    How do i disable this log, this specific?

    INFO:     127.0.0.1:57304 - "GET /metrics HTTP/1.1" 200 OK
    INFO:     127.0.0.1:57310 - "GET /metrics HTTP/1.1" 200 OK
    INFO:     127.0.0.1:57304 - "GET /metrics HTTP/1.1" 200 OK
    INFO:     127.0.0.1:57310 - "GET /metrics HTTP/1.1" 200 OK
    INFO:     127.0.0.1:57304 - "GET /metrics HTTP/1.1" 200 OK
    INFO:     127.0.0.1:57310 - "GET /metrics HTTP/1.1" 200 OK
    INFO:     127.0.0.1:57304 - "GET /metrics HTTP/1.1" 200 OK
    INFO:     127.0.0.1:57310 - "GET /metrics HTTP/1.1" 200 OK
    ............several  million times .............................
    INFO:     127.0.0.1:57310 - "GET /metrics HTTP/1.1" 200 OK
    
    opened by Delvify 1
  • WIP: Add test for prometheus_multiproc_dir

    WIP: Add test for prometheus_multiproc_dir

    I was wondering if we could add a test for the situation in which the environment variable prometheus_multiproc_dir is set, thus reaching 100% coverage. The problem is that we get a status code 200 OK, but the content of the response is empty. It would be nice if you have suggestions on how to correctly mock the processing using the prometheus_multiproc_dir. Many thanks and best regards.

    opened by vreyespue 1
  • Make module PEP 561 compatible.

    Make module PEP 561 compatible.

    Add py.typed to indicate that the project has inline type hints. This allows mypy to successfully import and use the type hints provided by the module.

    released 
    opened by trevora 1
  • Fix duplicated charset in the content-type header

    Fix duplicated charset in the content-type header

    The CONTENT_TYPE_LATEST constant from the prometheus_client already contains not only media type but also charset value. On the other hand, starlette adds charset value to a value passed as media_type (related place in code).

    This causes charset value duplication like: text/plain; version=0.0.4; charset=utf-8; charset=utf-8.

    released 
    opened by denysxftr 1
  • Bump certifi from 2021.10.8 to 2022.12.7

    Bump certifi from 2021.10.8 to 2022.12.7

    Bumps certifi from 2021.10.8 to 2022.12.7.

    Commits

    Dependabot compatibility score

    Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting @dependabot rebase.


    Dependabot commands and options

    You can trigger Dependabot actions by commenting on this PR:

    • @dependabot rebase will rebase this PR
    • @dependabot recreate will recreate this PR, overwriting any edits that have been made to it
    • @dependabot merge will merge this PR after your CI passes on it
    • @dependabot squash and merge will squash and merge this PR after your CI passes on it
    • @dependabot cancel merge will cancel a previously requested merge and block automerging
    • @dependabot reopen will reopen this PR if it is closed
    • @dependabot close will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually
    • @dependabot ignore this major version will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself)
    • @dependabot ignore this minor version will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself)
    • @dependabot ignore this dependency will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
    • @dependabot use these labels will set the current labels as the default for future PRs for this repo and language
    • @dependabot use these reviewers will set the current reviewers as the default for future PRs for this repo and language
    • @dependabot use these assignees will set the current assignees as the default for future PRs for this repo and language
    • @dependabot use this milestone will set the current milestone as the default for future PRs for this repo and language

    You can disable automated security fix PRs for this repo from the Security Alerts page.

    dependencies 
    opened by dependabot[bot] 0
  • Setting requests in progress multiprocess mode as livesum

    Setting requests in progress multiprocess mode as livesum

    By default it was by pid, this could generate a lot of metrics in case of many workers and multiprocess. This can overtime stack as worker processes can restart and leak metrics like this. With this change, this would remove the pid and the metric will be the same regardless of the multiprocess context

    opened by rbizos 0
  • Revamp implementation without BaseHTTPMiddleware

    Revamp implementation without BaseHTTPMiddleware

    Hello there 👋

    Because of the numerous limitations of the BaseHTTPMiddleware class provided by Starlette, the Starlette dev' team is about to deprecate it and encourage people to write "pure" ASGI middlewares. In particular, one of this limitation causes the issue #33 here.

    This PR is an attempt at converting the existing middleware without BaseHTTPMiddleware. The resulting code is quite similar, the only "tricky" thing is the part where we wrap the send function with our own; as it's the common way to do in ASGI.

    All existing tests are passing.

    I would be glad to discuss it and make all changes needed so we can integrate this new approach in the library.

    Cheers!

    opened by frankie567 2
  • Submounted routes use incorrect path in labels

    Submounted routes use incorrect path in labels

    When submounting routes, rather than the full path template being used, only the mount prefix is used.

    Running the following app:

    from starlette.applications import Starlette
    from starlette.middleware import Middleware
    from starlette.responses import Response
    from starlette.routing import Mount, Route
    from starlette_prometheus import PrometheusMiddleware, metrics
    
    
    async def foo(request):
        return Response()
    
    
    async def bar_baz(request):
        return Response()
    
    
    routes = [
        Route("/foo", foo),
        Mount("/bar", Route("/baz", bar_baz)),
        Route("/metrics", metrics),
    ]
    middleware = [Middleware(PrometheusMiddleware)]
    app = Starlette(routes=routes, middleware=middleware)
    

    Then making the following requests:

    $ curl localhost:8000/foo
    $ curl localhost:8000/bar/baz
    $ curl localhost:8000/metrics
    

    Gives the following output (I only included one metric as an example, but it's the same for all of them). Note the label for the request to localhost:8000/bar/baz has a path label of /bar.

    starlette_requests_total{method="GET",path_template="/foo"} 1.0
    starlette_requests_total{method="GET",path_template="/bar"} 1.0
    starlette_requests_total{method="GET",path_template="/metrics"} 1.0
    
    opened by ter0 2
  • respect PROMETHEUS_MULTIPROC_DIR in example metrics view

    respect PROMETHEUS_MULTIPROC_DIR in example metrics view

    Hey

    Since prometheus_client:0.10.x deprecated prometheus_multiproc_dir in favor of PROMETHEUS_MULTIPROC_DIR. So I updated the example metrics view to also respect PROMETHEUS_MULTIPROC_DIR - wdyt?

    opened by celloni 0
Releases(v0.9.0)
Owner
José Antonio Perdiguero
Artificial Intelligence Engineer & Software Architect
José Antonio Perdiguero
User authentication fastapi with python

user-authentication-fastapi Authentication API Development Setup environment You should create a virtual environment and activate it: virtualenv venv

Sabir Hussain 3 Mar 03, 2022
API written using Fast API to manage events and implement a leaderboard / badge system.

Open Food Facts Events API written using Fast API to manage events and implement a leaderboard / badge system. Installation To run the API locally, ru

Open Food Facts 5 Jan 07, 2023
Slack webhooks API served by FastAPI

Slackers Slack webhooks API served by FastAPI What is Slackers Slackers is a FastAPI implementation to handle Slack interactions and events. It serves

Niels van Huijstee 68 Jan 05, 2023
A FastAPI WebSocket application that makes use of ncellapp package by @hemantapkh

ncellFastAPI author: @awebisam Used FastAPI to create WS application. Ncellapp module by @hemantapkh NOTE: Not following best practices and, needs ref

Aashish Bhandari 7 Oct 01, 2021
fastapi-mqtt is extension for MQTT protocol

fastapi-mqtt MQTT is a lightweight publish/subscribe messaging protocol designed for M2M (machine to machine) telemetry in low bandwidth environments.

Sabuhi 144 Dec 28, 2022
Reusable utilities for FastAPI

Reusable utilities for FastAPI Documentation: https://fastapi-utils.davidmontague.xyz Source Code: https://github.com/dmontagu/fastapi-utils FastAPI i

David Montague 1.3k Jan 04, 2023
Ready-to-use and customizable users management for FastAPI

FastAPI Users Ready-to-use and customizable users management for FastAPI Documentation: https://fastapi-users.github.io/fastapi-users/ Source Code: ht

FastAPI Users 2.3k Dec 30, 2022
cookiecutter template for web API with python

Python project template for Web API with cookiecutter What's this This provides the project template including minimum test/lint/typechecking package

Hitoshi Manabe 4 Jan 28, 2021
API for Submarino store

submarino-api API for the submarino e-commerce documentation read the documentation in: https://submarino-api.herokuapp.com/docs or in https://submari

Miguel 1 Oct 14, 2021
MS Graph API authentication example with Fast API

MS Graph API authentication example with Fast API What it is & does This is a simple python service/webapp, using FastAPI with server side rendering,

Andrew Hart 4 Aug 11, 2022
Basic fastapi blockchain - An api based blockchain with full functionality

Basic fastapi blockchain - An api based blockchain with full functionality

1 Nov 27, 2021
Keycloack plugin for FastApi.

FastAPI Keycloack Keycloack plugin for FastApi. Your aplication receives the claims decoded from the access token. Usage Run keycloak on port 8080 and

Elber 4 Jun 24, 2022
Local Telegram Bot With FastAPI & Ngrok

An easy local telegram bot server with python, fastapi and ngrok.

Ömer Faruk Özdemir 7 Dec 25, 2022
Deploy/View images to database sqlite with fastapi

Deploy/View images to database sqlite with fastapi cd realistic Dependencies dat

Fredh Macau 1 Jan 04, 2022
Easily integrate socket.io with your FastAPI app 🚀

fastapi-socketio Easly integrate socket.io with your FastAPI app. Installation Install this plugin using pip: $ pip install fastapi-socketio Usage To

Srdjan Stankovic 210 Dec 23, 2022
FastAPI-Amis-Admin is a high-performance, efficient and easily extensible FastAPI admin framework. Inspired by django-admin, and has as many powerful functions as django-admin.

简体中文 | English 项目介绍 FastAPI-Amis-Admin fastapi-amis-admin是一个拥有高性能,高效率,易拓展的fastapi管理后台框架. 启发自Django-Admin,并且拥有不逊色于Django-Admin的强大功能. 源码 · 在线演示 · 文档 · 文

AmisAdmin 318 Dec 31, 2022
A Python framework to build Slack apps in a flash with the latest platform features.

Bolt for Python A Python framework to build Slack apps in a flash with the latest platform features. Read the getting started guide and look at our co

SlackAPI 684 Jan 09, 2023
Run your jupyter notebooks as a REST API endpoint. This isn't a jupyter server but rather just a way to run your notebooks as a REST API Endpoint.

Jupter Notebook REST API Run your jupyter notebooks as a REST API endpoint. This isn't a jupyter server but rather just a way to run your notebooks as

Invictify 54 Nov 04, 2022
Middleware for Starlette that allows you to store and access the context data of a request. Can be used with logging so logs automatically use request headers such as x-request-id or x-correlation-id.

starlette context Middleware for Starlette that allows you to store and access the context data of a request. Can be used with logging so logs automat

Tomasz Wójcik 300 Dec 26, 2022
Feature rich robust FastAPI template.

Flexible and Lightweight general-purpose template for FastAPI. Usage ⚠️ Git, Python and Poetry must be installed and accessible ⚠️ Poetry version must

Pavel Kirilin 588 Jan 04, 2023