diff --git a/noxfile.py b/noxfile.py index e46ad6c..751fb42 100644 --- a/noxfile.py +++ b/noxfile.py @@ -18,7 +18,7 @@ def test_litestar_versions(session, litestar_version): @nox.session() -@nox.parametrize("aiohttp_version", ["3.9.1", "3.11.12"]) +@nox.parametrize("aiohttp_version", ["3.9.1", "3.11.13"]) def test_aiohttp_versions(session, aiohttp_version): session.install(*DEPENDENCIES, f"aiohttp=={aiohttp_version}") session.run("pytest", "tests", "--framework=aiohttp", "-k", "test_frameworks") diff --git a/pyproject.toml b/pyproject.toml index 5ac54d1..16edab0 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [project] name = "huntflow-base-metrics" -version = "0.2.0" +version = "0.2.1" description = "Prometheus metrics for Huntflow services" authors = [ {name = "Developers huntflow", email = "developer@huntflow.ru"}, diff --git a/src/huntflow_base_metrics/web_frameworks/aiohttp.py b/src/huntflow_base_metrics/web_frameworks/aiohttp.py index efbe58d..d8236db 100644 --- a/src/huntflow_base_metrics/web_frameworks/aiohttp.py +++ b/src/huntflow_base_metrics/web_frameworks/aiohttp.py @@ -7,7 +7,7 @@ from huntflow_base_metrics.export import export_to_http_response from huntflow_base_metrics.web_frameworks._middleware import PathTemplate, PrometheusMiddleware -__all__ = ["add_middleware", "get_http_response_metrics"] +__all__ = ["add_middleware", "get_http_response_metrics", "get_middleware"] class _PrometheusMiddleware(PrometheusMiddleware[Request]): @@ -42,9 +42,11 @@ def get_method(request: Request) -> str: def get_path_template(request: Request) -> PathTemplate: match_info = request.match_info value = request.rel_url.path - if match_info and match_info.route.resource: + is_handled = False + if match_info.route and match_info.route.resource: value = match_info.route.resource.canonical - return PathTemplate(value=value, is_handled=match_info is not None) + is_handled = True + return PathTemplate(value=value, is_handled=is_handled) def add_middleware( @@ -67,6 +69,25 @@ def add_middleware( app.middlewares.append(_PrometheusMiddleware.dispatch) +def get_middleware( + include_routes: Optional[Iterable[str]] = None, + exclude_routes: Optional[Iterable[str]] = None, +) -> Callable: + """ + Returns observing middleware for AioHTTP application. + Use if middleware order matters. + + :param include_routes: optional set of path templates to observe. + If it's not empty, then only the specified routes will be observed + (also exclude_routes will be ignored). + :param exclude_routes: optional set of path templates to not observe. + If it's not empty (and include_routes is not specified), then the + specified routes will not be observed. + """ + _PrometheusMiddleware.configure(include_routes, exclude_routes) + return _PrometheusMiddleware.dispatch + + def get_http_response_metrics() -> Response: """Method returns HTTP Response with current metrics in prometheus format.""" content, content_type = export_to_http_response() diff --git a/tests/test_web_frameworks/test_frameworks.py b/tests/test_web_frameworks/test_frameworks.py index c441c5e..cbd768d 100644 --- a/tests/test_web_frameworks/test_frameworks.py +++ b/tests/test_web_frameworks/test_frameworks.py @@ -145,6 +145,22 @@ async def test_exclude(create_app): assert REGISTRY.get_sample_value("requests_total", labels) == 1 +async def test_unknown_routes_are_skipped(create_app): + client = await create_app() + response = await client.get("/unknown") + await check_response(response, status=404) + + labels = COMMON_LABELS_VALUES.copy() + labels.update( + { + "method": "GET", + "path_template": "/unknown", + } + ) + + assert REGISTRY.get_sample_value("requests_total", labels) is None + + async def test_get_http_response_metrics(create_app): client = await create_app()