Skip to content

Commit

Permalink
DEV-19025: add aiohttp and litestar examples to README.md
Browse files Browse the repository at this point in the history
  • Loading branch information
alexreznikoff committed Feb 6, 2025
1 parent c0d0150 commit 07da4c8
Showing 1 changed file with 131 additions and 11 deletions.
142 changes: 131 additions & 11 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,13 +1,19 @@
# huntflow-base-metrics
Base definitions for metrics collection via prometheus client library.
Intended to be used in Huntflow fastapi-based services:
* ready-to use collectors to measure HTTP requests and responses.
* decorator to observe timings of custom methods/functions.
* builtin support for common lables across all collectors
* builtin support for common labels across all collectors

Intended to be used in Huntflow services based on:
* AioHTTP
* FastAPI
* Litestar

# Installation

TODO
```shell
pip install huntflow_base_metrics
```

# Usage

Expand All @@ -21,7 +27,7 @@ The package provides two labels which should be set for every metric:
You don't need to set those labels manually. The labels are handled implicitly by the package public
methods.

For FastAPI metrics you don't need to deal with labels at all.
For request metrics you don't need to deal with labels at all.

For another metrics use `register_metric` method. It will accept a custom list of labels and create
a collector with your labels + common labels. To get labelled metric instance (registered with `register_metric`) use
Expand All @@ -34,7 +40,8 @@ from contextlib import asynccontextmanager

from fastAPI import FastAPI

from huntflow_base_metrics import start_metrics, stop_metrics, add_middleware
from huntflow_base_metrics import start_metrics, stop_metrics
from huntflow_base_metrics.web_frameworks.fastapi import add_middleware


# Service name (in most cases should be provided in `FACILITY_NAME` environment variable)
Expand All @@ -59,7 +66,7 @@ async def onshutdown(app: FastAPI):
stop_metrics()


def create_app()
def create_app() -> FastAPI:
app = FastAPI(lifespan=lifespan)

start_metrics(
Expand All @@ -77,9 +84,122 @@ def create_app()
return app
```

### FastAPI metrics
## Collect Litestar requests metrics

```python
from uuid import uuid4

from litestar import Litestar, MediaType, Request, Response, get
from litestar.status_codes import HTTP_500_INTERNAL_SERVER_ERROR

from huntflow_base_metrics import start_metrics, stop_metrics
from huntflow_base_metrics.web_frameworks.litestar import (
exception_context,
get_http_response_metrics,
get_middleware,
)

FACILITY_NAME = "test_service"
FACILITY_ID = uuid4().hex

async def on_shutdown(app: Litestar):
stop_metrics()


def exception_handler(_: Request, exc: Exception):
"""
Important!
If you need to collect EXCEPTIONS metrics you should set it to exception_context here
"""
status_code = getattr(exc, "status_code", HTTP_500_INTERNAL_SERVER_ERROR)
exception_type = type(exc).__name__

exception_context.set(exception_type)

return Response(
media_type=MediaType.JSON,
content=exception_type,
status_code=status_code,
)


def create_app() -> Litestar:
@get("/ok")
async def ok() -> dict:
return {"status": "ok"}

@get("/metrics")
async def metrics() -> Response:
return get_http_response_metrics()

start_metrics(
FACILITY_NAME,
FACILITY_ID,
out_file_path=f"/app/metrics/{FACILITY_NAME}-{FACILITY_ID}.prom",
enabled=True,
write_to_file=True,
file_update_interval=15,
)
prometheus_middleware = get_middleware()
app = Litestar(
middleware=[prometheus_middleware],
route_handlers=[ok, metrics],
exception_handlers={Exception: exception_handler},
on_shutdown=[on_shutdown],
)

return app
```

## Collect AioHTTP requests metrics

```python
from aiohttp import web
from aiohttp.web_app import Application

from huntflow_base_metrics import start_metrics, stop_metrics
from huntflow_base_metrics.web_frameworks.aiohttp import add_middleware, get_http_response_metrics


# Service name (in most cases should be provided in `FACILITY_NAME` environment variable)
FACILITY_NAME = "my-service-name"
# Service instance name (should provided in `FACILITY_ID` environment variable)
FACILITY_ID = "qwerty"


async def on_cleanup(app):
stop_metrics()


def create_app() -> Application:
routes = web.RouteTableDef()

@routes.get("/ok")
async def ok(request):
return web.json_response(data={"status": "ok"})

@routes.get("/metrics")
async def ok(request):
return get_http_response_metrics()

start_metrics(
FACILITY_NAME,
FACILITY_ID,
out_file_path=f"/app/metrics/{FACILITY_NAME}-{FACILITY_ID}.prom",
enabled=True,
write_to_file=True,
file_update_interval=15,
)
app = Application()
app.add_routes(routes)
add_middleware(app)
app.on_cleanup.append(on_cleanup)
return app
```

## Request metrics

#### requests_total
### requests_total

Incremental counter for total number of requests

Expand All @@ -92,7 +212,7 @@ Incremental counter for total number of requests
* `method` - HTTP method like `GET`, `POST`
* `template_path` - path provided as a route

#### responses_total
### responses_total

Incremental counter for total number of responses

Expand All @@ -107,7 +227,7 @@ Incremental counter for total number of responses
* `status_code` - HTTP status code return by response (200, 404, 500, etc)


#### requests_processing_time_seconds
### requests_processing_time_seconds

Historgam collects latency (request processing time) for requests

Expand All @@ -122,7 +242,7 @@ Historgam collects latency (request processing time) for requests
* `le` - bucket in histogram (builtin label in Histogram collector)


#### requests_in_progress
### requests_in_progress

Current number of in-progress requests

Expand Down

0 comments on commit 07da4c8

Please sign in to comment.