|
2 | 2 |
|
3 | 3 | import fastapi |
4 | 4 | import litestar |
| 5 | +import pytest |
5 | 6 | from fastapi.testclient import TestClient as FastAPITestClient |
| 7 | +from faststream.redis import RedisBroker, TestRedisBroker |
| 8 | +from faststream.redis.prometheus import RedisPrometheusMiddleware |
6 | 9 | from litestar import status_codes |
7 | 10 | from litestar.middleware.base import DefineMiddleware |
8 | 11 | from litestar.testing import TestClient as LitestarTestClient |
| 12 | +from prometheus_client import REGISTRY |
9 | 13 |
|
10 | | -from microbootstrap import FastApiPrometheusConfig, LitestarPrometheusConfig |
| 14 | +from microbootstrap import FastApiPrometheusConfig, FastStreamSettings, LitestarPrometheusConfig |
11 | 15 | from microbootstrap.bootstrappers.fastapi import FastApiPrometheusInstrument |
| 16 | +from microbootstrap.bootstrappers.faststream import FastStreamBootstrapper |
12 | 17 | from microbootstrap.bootstrappers.litestar import LitestarPrometheusInstrument |
13 | | -from microbootstrap.instruments.prometheus_instrument import BasePrometheusConfig, PrometheusInstrument |
| 18 | +from microbootstrap.config.faststream import FastStreamConfig |
| 19 | +from microbootstrap.instruments.prometheus_instrument import ( |
| 20 | + BasePrometheusConfig, |
| 21 | + FastStreamPrometheusConfig, |
| 22 | + PrometheusInstrument, |
| 23 | +) |
| 24 | + |
| 25 | + |
| 26 | +def check_is_metrics_has_labels(custom_labels_keys: set[str]) -> bool: |
| 27 | + for metric in REGISTRY.collect(): |
| 28 | + for sample in metric.samples: |
| 29 | + label_keys = set(sample.labels.keys()) |
| 30 | + if custom_labels_keys & label_keys: |
| 31 | + return True |
| 32 | + return False |
14 | 33 |
|
15 | 34 |
|
16 | 35 | def test_prometheus_is_ready(minimal_base_prometheus_config: BasePrometheusConfig) -> None: |
@@ -85,3 +104,69 @@ def test_fastapi_prometheus_bootstrap_working(minimal_fastapi_prometheus_config: |
85 | 104 | ) |
86 | 105 | assert response.status_code == status_codes.HTTP_200_OK |
87 | 106 | assert response.text |
| 107 | + |
| 108 | + |
| 109 | +@pytest.mark.parametrize( |
| 110 | + ("custom_labels", "expected_label_keys"), |
| 111 | + [ |
| 112 | + ({"test_label": "test_value"}, {"test_label"}), |
| 113 | + ({}, {"method", "handler", "status"}), |
| 114 | + ], |
| 115 | +) |
| 116 | +def test_fastapi_prometheus_custom_labels( |
| 117 | + minimal_fastapi_prometheus_config: FastApiPrometheusConfig, |
| 118 | + custom_labels: dict[str, str], |
| 119 | + expected_label_keys: set[str], |
| 120 | +) -> None: |
| 121 | + minimal_fastapi_prometheus_config.prometheus_custom_labels = custom_labels |
| 122 | + prometheus_instrument: typing.Final = FastApiPrometheusInstrument(minimal_fastapi_prometheus_config) |
| 123 | + |
| 124 | + fastapi_application = fastapi.FastAPI() |
| 125 | + fastapi_application = prometheus_instrument.bootstrap_after(fastapi_application) |
| 126 | + |
| 127 | + response: typing.Final = FastAPITestClient(app=fastapi_application).get( |
| 128 | + minimal_fastapi_prometheus_config.prometheus_metrics_path |
| 129 | + ) |
| 130 | + |
| 131 | + assert response.status_code == status_codes.HTTP_200_OK |
| 132 | + assert check_is_metrics_has_labels(expected_label_keys) |
| 133 | + |
| 134 | + |
| 135 | +@pytest.mark.parametrize( |
| 136 | + ("custom_labels", "expected_label_keys"), |
| 137 | + [ |
| 138 | + ({"test_label": "test_value"}, {"test_label"}), |
| 139 | + ({}, {"app_name", "broker", "handler"}), |
| 140 | + ], |
| 141 | +) |
| 142 | +async def test_faststream_prometheus_custom_labels( |
| 143 | + minimal_faststream_prometheus_config: FastStreamPrometheusConfig, |
| 144 | + custom_labels: dict[str, str], |
| 145 | + expected_label_keys: set[str], |
| 146 | +) -> None: |
| 147 | + minimal_faststream_prometheus_config.prometheus_custom_labels = custom_labels |
| 148 | + minimal_faststream_prometheus_config.prometheus_middleware_cls = RedisPrometheusMiddleware # type: ignore[assignment] |
| 149 | + |
| 150 | + broker: typing.Final = RedisBroker() |
| 151 | + ( |
| 152 | + FastStreamBootstrapper(FastStreamSettings()) |
| 153 | + .configure_application(FastStreamConfig(broker=broker)) |
| 154 | + .configure_instrument(minimal_faststream_prometheus_config) |
| 155 | + .bootstrap() |
| 156 | + ) |
| 157 | + |
| 158 | + def create_test_redis_subscriber( |
| 159 | + broker: RedisBroker, |
| 160 | + topic: str, |
| 161 | + ) -> typing.Callable[[dict[str, str]], typing.Coroutine[typing.Any, typing.Any, None]]: |
| 162 | + @broker.subscriber(topic) |
| 163 | + async def test_subscriber(payload: dict[str, str]) -> None: |
| 164 | + pass |
| 165 | + |
| 166 | + return test_subscriber |
| 167 | + |
| 168 | + create_test_redis_subscriber(broker, topic="test-topic") |
| 169 | + |
| 170 | + async with TestRedisBroker(broker) as tb: |
| 171 | + await tb.publish({"foo": "bar"}, "test-topic") |
| 172 | + assert check_is_metrics_has_labels(expected_label_keys) |
0 commit comments