%global _empty_manifest_terminate_build 0 Name: python-prometheusrock Version: 0.2.0 Release: 1 Summary: Prometheus middleware for Starlette and FastAPI License: MIT License URL: https://github.com/kozhushman/prometheusrock Source0: https://mirrors.nju.edu.cn/pypi/web/packages/c1/3e/ab798d882544f0c69990c56fe1f8dfed8d1f6fce1b34294207bf9f63cd18/prometheusrock-0.2.0.tar.gz BuildArch: noarch Requires: python3-starlette Requires: python3-prometheus-client %description # PrometheusRock ![Python package](https://github.com/kozhushman/prometheusrock/workflows/Python%20package/badge.svg?branch=main) ![CodeQL](https://github.com/kozhushman/prometheusrock/workflows/CodeQL/badge.svg?branch=main) Prometheus middleware for Starlette and FastAPI This middleware collects couple of basic metrics and allow you to add your own ones. **Basic metrics**: * Counter: requests_total * Histogram: request_processing_time Basic labels for them: * method * path * status_code * `User-Agent` and `Host` headers * application name Example: ```sh request_processing_time_sum{app_name="test_app",headers="{'host': '127.0.0.1:8020', 'user-agent': 'Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:81.0) Gecko/20100101 Firefox/81.0'}",path="/test",status_code="200"} 0.00036406517028808594 ``` Metrics include labels for the HTTP method, the path, and the response status code. Set for path `/metrics` handler `metrics_route` and your metrics will be exposed on that url for Prometheus further use. ## Usage ### 1. I don't want anything custom, just give me the basics! If you don't want nothing extra, this is for you. Grab the code and run to paste it! For **starlette** and **FastAPI** init part pretty similar. 1. First: ``` pip install prometheusrock ``` 2. Second: Choose your fighter! If you're using starlette: ```python from starlette.applications import Starlette ``` And if you're using FastAPI: ```python from fastapi import FastAPI ``` Moving further: ```python from prometheusrock import PrometheusMiddleware, metrics_route app = # Starlette() or FastAPI() app.add_middleware(PrometheusMiddleware) app.add_route("/metrics", metrics_route) ... ``` And that's it! Now go on `/metrics` and see your logs! ### 2. Custom you say? Let me see...but just a little! If you want to configure basic metrics let me show you how! When you declare middleware, you can pass following args: * `app_name` - the name you want to show in metrics as the name of your app. Default - "ASGIApp", * `additional_headers` - if you want to track additional headers (aside of default ones - `user-agent` and `host`) you can pass `list` (that's important!) with names of that headers. They all cast to lowercase, so casing doesn't matters. * `remove_labels` - by default basic metrics labels are following: `method`, `path`, `status_code`, `headers`, `app_name`. If you don't wanna some of them - pass `list` with their names here. And their gone! * `skip_paths` - sometimes you don't wanna log some of the endpoint. (Fore example you don't wanna log accesses to `/metrics` in your metrics). If you want to exclude this paths from metric - pass here `list` with their urls. By default this middleware ignores `/metrics` route, so if you initially moved your metric route to some other url - pass it here. If you want to log all routes (even the default `/metrics` - pass an empty list!) * `disable_default_counter` - if you want to disable default Counter metric - pass `True` value to this optional param. * `disable_default_histogram` - if you want to disable default Histogram metric - pass `True` value to this optional param. * `custom_base_labels` - if you want change default labels to yours - pass them here. **REWRITES DEFAULT LABLES**. Args `remove_labels` **WILL BE IGNORED**. example - `['path','method']` - and you have metric, that contains only `path` and `method` labels. * `custom_base_headers` - if you want change default headers to yours - pass them here. **REWRITES DEFAULT HEADERS**. Args `additional_headers` **WILL BE IGNORED**. If you use `custom_base_labels`, don't forget to pass `headers` in it, otherwise `custom_base_headers` will have no effect. example - `['content-type','x-api-client']` - and now you write only these two headers. * `aggregate_paths` - if you have endpoints like `/item/{id}`, then, by default, your logs will quickly overflow, showing you huge amount of numbers, when, in fact, endpoint is one. So pass here list of endpoints path to aggregate by. example - `['/item/']` But a picture is worth a thousand words, right? Let's see some code! For example, we want our middleware to have a following settings: we want a name `this_is_my_app`, we want to track header `accept-encoding`, we don't wanna label `path` (if you have one endpoint for example), and we don't want url `/_healthcheck` to be tracked. ```python app.add_middleware( PrometheusMiddleware, app_name='this_is_my_app', additional_headers=['accept-encoding'], remove_labels=['path'], skip_paths=['/_healthcheck'] ) ``` And after that, our metric will look something like that: ```sh requests_total{app_name="this_is_my_app",headers="{'host': '127.0.0.1:8000', 'user-agent': 'Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:81.0) Gecko/20100101 Firefox/81.0', 'accept-encoding': 'gzip, deflate'}",method="GET",status_code="200"} 1.0 ``` ## Let's go deeper! Add your own custom metric! And the star of the evening - custom metrics! So, lets suppose you want to check how many are rows in your Database after each request. Let's explore this: First, we do all the same things - we initiate the app, we add PrometheusMiddleware. And the next steps are: 1. We must decide what type of metric we want - [choose one from here](https://github.com/prometheus/client_python). Basically, you will need pass one of the types - `info, gauge, counter, histogram, summary, enum`. 2. We declare the function that will act like our metric logic: ```python # async here isn't necessary, you can use ordinary function async def query(middleware_proxy): res = await db.execute_query( "SELECT COUNT(*) as count from MyTable" ) middleware_proxy.metric.labels(**res) ``` Function **MUST** accept this argument. Obviously you can name it however you want, as long is it still there. If you want to know what's inside - `from prometheusrock import Metric`. I strongly recommend to pass it as typehinting: ```python from prometheusrock import Metric ... async def query(middleware_proxy: Metric): ``` Metric have 3 attributes: * metric - instance of `prometheus_client` metric object. * metric_type - string with type. * spent_time - time, that was spent on request. You may need it if you, for example, implementing Histogram metric. * request - request object from app. And now **IMPORTANT** remark - you *must* correctly invoke metric! So if you, for example, chose `Counter` metric, in your custom function you must do `middleware_proxy.metric.labels(**res).inc()`, or if you chose Histogram - `middleware_proxy.metric.labels(**res).observe(middleware_proxy.spent_time)` and so on, according to [this docs](https://github.com/prometheus/client_python). Value that you're passing there - `res` (or however you called it) must be a sequence of the parameters, that you set as lables for your metric. For example, if your metric have labels `count` and `id`, `res` must be a dictionary `{"count": count, "id": id}` or list with right positioning - `[count, id]`. 3. And finally we tell our middleware about our custom metric: ```python from prometheusrock import AddMetric, PrometheusMiddleware ... app.add_middleware(PrometheusMiddleware) ... # async here isn't necessary, you can use ordinary function async def query(middleware_proxy): res = await db.execute_query( "SELECT COUNT(*) as count from MyTable" ) middleware_proxy.metric.labels(**res) AddMetric( function=query, metric_name='my_precious', metric_type='info', labels=['row_count'] ) ``` AddMetric accept following params: * function - function that will work as your metric logic * metric_name - unique metric name, must be ONE-WORDED (e.g. unique_metric_name). Default - "user_metric". * metric_description- description of your metric. Default- "description of user metric". * labels - list of lables that you want your metric to contain. Default - ["info"]. * metric_type - one of `prometheus_client` metric types - described in paragraph 1. ## Links and dependencies Dependencies: [Starlette](https://github.com/encode/starlette), [client_python](https://github.com/prometheus/client_python) Additional links: [FastAPI](https://github.com/tiangolo/fastapi) %package -n python3-prometheusrock Summary: Prometheus middleware for Starlette and FastAPI Provides: python-prometheusrock BuildRequires: python3-devel BuildRequires: python3-setuptools BuildRequires: python3-pip %description -n python3-prometheusrock # PrometheusRock ![Python package](https://github.com/kozhushman/prometheusrock/workflows/Python%20package/badge.svg?branch=main) ![CodeQL](https://github.com/kozhushman/prometheusrock/workflows/CodeQL/badge.svg?branch=main) Prometheus middleware for Starlette and FastAPI This middleware collects couple of basic metrics and allow you to add your own ones. **Basic metrics**: * Counter: requests_total * Histogram: request_processing_time Basic labels for them: * method * path * status_code * `User-Agent` and `Host` headers * application name Example: ```sh request_processing_time_sum{app_name="test_app",headers="{'host': '127.0.0.1:8020', 'user-agent': 'Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:81.0) Gecko/20100101 Firefox/81.0'}",path="/test",status_code="200"} 0.00036406517028808594 ``` Metrics include labels for the HTTP method, the path, and the response status code. Set for path `/metrics` handler `metrics_route` and your metrics will be exposed on that url for Prometheus further use. ## Usage ### 1. I don't want anything custom, just give me the basics! If you don't want nothing extra, this is for you. Grab the code and run to paste it! For **starlette** and **FastAPI** init part pretty similar. 1. First: ``` pip install prometheusrock ``` 2. Second: Choose your fighter! If you're using starlette: ```python from starlette.applications import Starlette ``` And if you're using FastAPI: ```python from fastapi import FastAPI ``` Moving further: ```python from prometheusrock import PrometheusMiddleware, metrics_route app = # Starlette() or FastAPI() app.add_middleware(PrometheusMiddleware) app.add_route("/metrics", metrics_route) ... ``` And that's it! Now go on `/metrics` and see your logs! ### 2. Custom you say? Let me see...but just a little! If you want to configure basic metrics let me show you how! When you declare middleware, you can pass following args: * `app_name` - the name you want to show in metrics as the name of your app. Default - "ASGIApp", * `additional_headers` - if you want to track additional headers (aside of default ones - `user-agent` and `host`) you can pass `list` (that's important!) with names of that headers. They all cast to lowercase, so casing doesn't matters. * `remove_labels` - by default basic metrics labels are following: `method`, `path`, `status_code`, `headers`, `app_name`. If you don't wanna some of them - pass `list` with their names here. And their gone! * `skip_paths` - sometimes you don't wanna log some of the endpoint. (Fore example you don't wanna log accesses to `/metrics` in your metrics). If you want to exclude this paths from metric - pass here `list` with their urls. By default this middleware ignores `/metrics` route, so if you initially moved your metric route to some other url - pass it here. If you want to log all routes (even the default `/metrics` - pass an empty list!) * `disable_default_counter` - if you want to disable default Counter metric - pass `True` value to this optional param. * `disable_default_histogram` - if you want to disable default Histogram metric - pass `True` value to this optional param. * `custom_base_labels` - if you want change default labels to yours - pass them here. **REWRITES DEFAULT LABLES**. Args `remove_labels` **WILL BE IGNORED**. example - `['path','method']` - and you have metric, that contains only `path` and `method` labels. * `custom_base_headers` - if you want change default headers to yours - pass them here. **REWRITES DEFAULT HEADERS**. Args `additional_headers` **WILL BE IGNORED**. If you use `custom_base_labels`, don't forget to pass `headers` in it, otherwise `custom_base_headers` will have no effect. example - `['content-type','x-api-client']` - and now you write only these two headers. * `aggregate_paths` - if you have endpoints like `/item/{id}`, then, by default, your logs will quickly overflow, showing you huge amount of numbers, when, in fact, endpoint is one. So pass here list of endpoints path to aggregate by. example - `['/item/']` But a picture is worth a thousand words, right? Let's see some code! For example, we want our middleware to have a following settings: we want a name `this_is_my_app`, we want to track header `accept-encoding`, we don't wanna label `path` (if you have one endpoint for example), and we don't want url `/_healthcheck` to be tracked. ```python app.add_middleware( PrometheusMiddleware, app_name='this_is_my_app', additional_headers=['accept-encoding'], remove_labels=['path'], skip_paths=['/_healthcheck'] ) ``` And after that, our metric will look something like that: ```sh requests_total{app_name="this_is_my_app",headers="{'host': '127.0.0.1:8000', 'user-agent': 'Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:81.0) Gecko/20100101 Firefox/81.0', 'accept-encoding': 'gzip, deflate'}",method="GET",status_code="200"} 1.0 ``` ## Let's go deeper! Add your own custom metric! And the star of the evening - custom metrics! So, lets suppose you want to check how many are rows in your Database after each request. Let's explore this: First, we do all the same things - we initiate the app, we add PrometheusMiddleware. And the next steps are: 1. We must decide what type of metric we want - [choose one from here](https://github.com/prometheus/client_python). Basically, you will need pass one of the types - `info, gauge, counter, histogram, summary, enum`. 2. We declare the function that will act like our metric logic: ```python # async here isn't necessary, you can use ordinary function async def query(middleware_proxy): res = await db.execute_query( "SELECT COUNT(*) as count from MyTable" ) middleware_proxy.metric.labels(**res) ``` Function **MUST** accept this argument. Obviously you can name it however you want, as long is it still there. If you want to know what's inside - `from prometheusrock import Metric`. I strongly recommend to pass it as typehinting: ```python from prometheusrock import Metric ... async def query(middleware_proxy: Metric): ``` Metric have 3 attributes: * metric - instance of `prometheus_client` metric object. * metric_type - string with type. * spent_time - time, that was spent on request. You may need it if you, for example, implementing Histogram metric. * request - request object from app. And now **IMPORTANT** remark - you *must* correctly invoke metric! So if you, for example, chose `Counter` metric, in your custom function you must do `middleware_proxy.metric.labels(**res).inc()`, or if you chose Histogram - `middleware_proxy.metric.labels(**res).observe(middleware_proxy.spent_time)` and so on, according to [this docs](https://github.com/prometheus/client_python). Value that you're passing there - `res` (or however you called it) must be a sequence of the parameters, that you set as lables for your metric. For example, if your metric have labels `count` and `id`, `res` must be a dictionary `{"count": count, "id": id}` or list with right positioning - `[count, id]`. 3. And finally we tell our middleware about our custom metric: ```python from prometheusrock import AddMetric, PrometheusMiddleware ... app.add_middleware(PrometheusMiddleware) ... # async here isn't necessary, you can use ordinary function async def query(middleware_proxy): res = await db.execute_query( "SELECT COUNT(*) as count from MyTable" ) middleware_proxy.metric.labels(**res) AddMetric( function=query, metric_name='my_precious', metric_type='info', labels=['row_count'] ) ``` AddMetric accept following params: * function - function that will work as your metric logic * metric_name - unique metric name, must be ONE-WORDED (e.g. unique_metric_name). Default - "user_metric". * metric_description- description of your metric. Default- "description of user metric". * labels - list of lables that you want your metric to contain. Default - ["info"]. * metric_type - one of `prometheus_client` metric types - described in paragraph 1. ## Links and dependencies Dependencies: [Starlette](https://github.com/encode/starlette), [client_python](https://github.com/prometheus/client_python) Additional links: [FastAPI](https://github.com/tiangolo/fastapi) %package help Summary: Development documents and examples for prometheusrock Provides: python3-prometheusrock-doc %description help # PrometheusRock ![Python package](https://github.com/kozhushman/prometheusrock/workflows/Python%20package/badge.svg?branch=main) ![CodeQL](https://github.com/kozhushman/prometheusrock/workflows/CodeQL/badge.svg?branch=main) Prometheus middleware for Starlette and FastAPI This middleware collects couple of basic metrics and allow you to add your own ones. **Basic metrics**: * Counter: requests_total * Histogram: request_processing_time Basic labels for them: * method * path * status_code * `User-Agent` and `Host` headers * application name Example: ```sh request_processing_time_sum{app_name="test_app",headers="{'host': '127.0.0.1:8020', 'user-agent': 'Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:81.0) Gecko/20100101 Firefox/81.0'}",path="/test",status_code="200"} 0.00036406517028808594 ``` Metrics include labels for the HTTP method, the path, and the response status code. Set for path `/metrics` handler `metrics_route` and your metrics will be exposed on that url for Prometheus further use. ## Usage ### 1. I don't want anything custom, just give me the basics! If you don't want nothing extra, this is for you. Grab the code and run to paste it! For **starlette** and **FastAPI** init part pretty similar. 1. First: ``` pip install prometheusrock ``` 2. Second: Choose your fighter! If you're using starlette: ```python from starlette.applications import Starlette ``` And if you're using FastAPI: ```python from fastapi import FastAPI ``` Moving further: ```python from prometheusrock import PrometheusMiddleware, metrics_route app = # Starlette() or FastAPI() app.add_middleware(PrometheusMiddleware) app.add_route("/metrics", metrics_route) ... ``` And that's it! Now go on `/metrics` and see your logs! ### 2. Custom you say? Let me see...but just a little! If you want to configure basic metrics let me show you how! When you declare middleware, you can pass following args: * `app_name` - the name you want to show in metrics as the name of your app. Default - "ASGIApp", * `additional_headers` - if you want to track additional headers (aside of default ones - `user-agent` and `host`) you can pass `list` (that's important!) with names of that headers. They all cast to lowercase, so casing doesn't matters. * `remove_labels` - by default basic metrics labels are following: `method`, `path`, `status_code`, `headers`, `app_name`. If you don't wanna some of them - pass `list` with their names here. And their gone! * `skip_paths` - sometimes you don't wanna log some of the endpoint. (Fore example you don't wanna log accesses to `/metrics` in your metrics). If you want to exclude this paths from metric - pass here `list` with their urls. By default this middleware ignores `/metrics` route, so if you initially moved your metric route to some other url - pass it here. If you want to log all routes (even the default `/metrics` - pass an empty list!) * `disable_default_counter` - if you want to disable default Counter metric - pass `True` value to this optional param. * `disable_default_histogram` - if you want to disable default Histogram metric - pass `True` value to this optional param. * `custom_base_labels` - if you want change default labels to yours - pass them here. **REWRITES DEFAULT LABLES**. Args `remove_labels` **WILL BE IGNORED**. example - `['path','method']` - and you have metric, that contains only `path` and `method` labels. * `custom_base_headers` - if you want change default headers to yours - pass them here. **REWRITES DEFAULT HEADERS**. Args `additional_headers` **WILL BE IGNORED**. If you use `custom_base_labels`, don't forget to pass `headers` in it, otherwise `custom_base_headers` will have no effect. example - `['content-type','x-api-client']` - and now you write only these two headers. * `aggregate_paths` - if you have endpoints like `/item/{id}`, then, by default, your logs will quickly overflow, showing you huge amount of numbers, when, in fact, endpoint is one. So pass here list of endpoints path to aggregate by. example - `['/item/']` But a picture is worth a thousand words, right? Let's see some code! For example, we want our middleware to have a following settings: we want a name `this_is_my_app`, we want to track header `accept-encoding`, we don't wanna label `path` (if you have one endpoint for example), and we don't want url `/_healthcheck` to be tracked. ```python app.add_middleware( PrometheusMiddleware, app_name='this_is_my_app', additional_headers=['accept-encoding'], remove_labels=['path'], skip_paths=['/_healthcheck'] ) ``` And after that, our metric will look something like that: ```sh requests_total{app_name="this_is_my_app",headers="{'host': '127.0.0.1:8000', 'user-agent': 'Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:81.0) Gecko/20100101 Firefox/81.0', 'accept-encoding': 'gzip, deflate'}",method="GET",status_code="200"} 1.0 ``` ## Let's go deeper! Add your own custom metric! And the star of the evening - custom metrics! So, lets suppose you want to check how many are rows in your Database after each request. Let's explore this: First, we do all the same things - we initiate the app, we add PrometheusMiddleware. And the next steps are: 1. We must decide what type of metric we want - [choose one from here](https://github.com/prometheus/client_python). Basically, you will need pass one of the types - `info, gauge, counter, histogram, summary, enum`. 2. We declare the function that will act like our metric logic: ```python # async here isn't necessary, you can use ordinary function async def query(middleware_proxy): res = await db.execute_query( "SELECT COUNT(*) as count from MyTable" ) middleware_proxy.metric.labels(**res) ``` Function **MUST** accept this argument. Obviously you can name it however you want, as long is it still there. If you want to know what's inside - `from prometheusrock import Metric`. I strongly recommend to pass it as typehinting: ```python from prometheusrock import Metric ... async def query(middleware_proxy: Metric): ``` Metric have 3 attributes: * metric - instance of `prometheus_client` metric object. * metric_type - string with type. * spent_time - time, that was spent on request. You may need it if you, for example, implementing Histogram metric. * request - request object from app. And now **IMPORTANT** remark - you *must* correctly invoke metric! So if you, for example, chose `Counter` metric, in your custom function you must do `middleware_proxy.metric.labels(**res).inc()`, or if you chose Histogram - `middleware_proxy.metric.labels(**res).observe(middleware_proxy.spent_time)` and so on, according to [this docs](https://github.com/prometheus/client_python). Value that you're passing there - `res` (or however you called it) must be a sequence of the parameters, that you set as lables for your metric. For example, if your metric have labels `count` and `id`, `res` must be a dictionary `{"count": count, "id": id}` or list with right positioning - `[count, id]`. 3. And finally we tell our middleware about our custom metric: ```python from prometheusrock import AddMetric, PrometheusMiddleware ... app.add_middleware(PrometheusMiddleware) ... # async here isn't necessary, you can use ordinary function async def query(middleware_proxy): res = await db.execute_query( "SELECT COUNT(*) as count from MyTable" ) middleware_proxy.metric.labels(**res) AddMetric( function=query, metric_name='my_precious', metric_type='info', labels=['row_count'] ) ``` AddMetric accept following params: * function - function that will work as your metric logic * metric_name - unique metric name, must be ONE-WORDED (e.g. unique_metric_name). Default - "user_metric". * metric_description- description of your metric. Default- "description of user metric". * labels - list of lables that you want your metric to contain. Default - ["info"]. * metric_type - one of `prometheus_client` metric types - described in paragraph 1. ## Links and dependencies Dependencies: [Starlette](https://github.com/encode/starlette), [client_python](https://github.com/prometheus/client_python) Additional links: [FastAPI](https://github.com/tiangolo/fastapi) %prep %autosetup -n prometheusrock-0.2.0 %build %py3_build %install %py3_install install -d -m755 %{buildroot}/%{_pkgdocdir} if [ -d doc ]; then cp -arf doc %{buildroot}/%{_pkgdocdir}; fi if [ -d docs ]; then cp -arf docs %{buildroot}/%{_pkgdocdir}; fi if [ -d example ]; then cp -arf example %{buildroot}/%{_pkgdocdir}; fi if [ -d examples ]; then cp -arf examples %{buildroot}/%{_pkgdocdir}; fi pushd %{buildroot} if [ -d usr/lib ]; then find usr/lib -type f -printf "/%h/%f\n" >> filelist.lst fi if [ -d usr/lib64 ]; then find usr/lib64 -type f -printf "/%h/%f\n" >> filelist.lst fi if [ -d usr/bin ]; then find usr/bin -type f -printf "/%h/%f\n" >> filelist.lst fi if [ -d usr/sbin ]; then find usr/sbin -type f -printf "/%h/%f\n" >> filelist.lst fi touch doclist.lst if [ -d usr/share/man ]; then find usr/share/man -type f -printf "/%h/%f.gz\n" >> doclist.lst fi popd mv %{buildroot}/filelist.lst . mv %{buildroot}/doclist.lst . %files -n python3-prometheusrock -f filelist.lst %dir %{python3_sitelib}/* %files help -f doclist.lst %{_docdir}/* %changelog * Mon May 29 2023 Python_Bot - 0.2.0-1 - Package Spec generated