Package: hr-prometheus
hr-prometheusPrometheus integration for aiohttp projects.hr-prometheus adds support for providingaiohttpapplications metrics toprometheus. It is implemented as a aiohttp middleware.Currently, it exports the following metrics via the /metrics endpoint by default:request_latency: Elapsed time per request in seconds.Labels exported: method (HTTP method), pathrequest_count: Number of requests received.Labels exported: method (HTTP method), path, status (HTTP status)requests_in_progress: In progress requests.Labels exported: method (HTTP method), pathDefault request behaviour can be modified by passing a customRequestMonitorto the middleware. You can find out how to do it inadvanced section.Installationpipinstallhr-prometheusUsageBriefly, the following is all you need to do to measure and export prometheus metrics from your aiohttp web application:fromaiohttpimportwebfromhr_prometheusimporthrprometheus_middleware,hrprometheus_viewapp=web.Application()app.router.add_get("/metrics",hrprometheus_view)app.middlewares.append(hrprometheus_middleware())Advanced usageCustom monitorsTo modify the default behavior you simply need to create a new monitor that inherits from theBaseRequestMonitorand pass the class to the middleware.This class provides two public methods.update_init_metricsandupdate_end_metrics.
These methods are executed at the beginning and end of a request respectively. Simply add the metrics you want at each point.Here's an example taken from the default monitor.fromaiohttpimportwebfromhr_prometheusimporthrprometheus_middleware,hrprometheus_viewfromhr_prometheus.monitorsimportBaseRequestMonitorclassRequestMonitor(BaseRequestMonitor):REQUEST_COUNT=Counter("request_count","Number of requests received",["method","path","status"])REQUEST_LATENCY=Histogram("request_latency","Elapsed time per request",["method","path"])REQUEST_IN_PROGRESS=Gauge("requests_in_progress","Requests in progress",["method","path"])defupdate_init_metrics(self):self.REQUEST_IN_PROGRESS.labels(*self.request_description).inc()defupdate_end_metrics(self):resp_time=time.time()-self.init_timeself.REQUEST_COUNT.labels(*self.request_description,self.response_status).inc()self.REQUEST_LATENCY.labels(*self.request_description).observe(resp_time)self.REQUEST_IN_PROGRESS.labels(*self.request_description).dec()app=web.Application()app.router.add_get("/metrics",hrprometheus_view)app.middlewares.append(hrprometheus_middleware(RequestMonitor))Grouping dynamic routesIn aiohttp you may define dynamic routes by parametrizing the route path (e.g./v1/resource/{resource_id}). If you are interested in grouping the different values for a given parameter under the same metrics you can do so by specifying the fixed parameters for a named route to the request monitor (you can do so trhough the middleware for convinience).Here is an example of an api returning neighbouring cells from a matrixfromaiohttpimportwebfromhr_prometheusimporthrprometheus_middlewarefrommy_project.viewsimportget_cell_neighbour_viewmiddleware=hrprometheus_middleware(fixed_routes_parameter={"get_cell_neighbour":["cell_id"]})app=web.Application(middlewares=[middleware])app.add_route("GET","/cell_neighbour/{cell_id}/direction/{direction}",get_cell_neighbour_view,name="get_cell_neighbour")This way requests with path/cell_neighbour/1948/direction/northand/cell_neighbour/874/direction/northare both collapsed into"/cell_neighbour/{cell_id}/direction/north"This is especially useful when you have a wide range of possible values for a path parameter and you are only interested in the overall monitoring, thus avoiding metrics namespace pollution.