diff --git a/cashews/contrib/prometheus.py b/cashews/contrib/prometheus.py index 4dc4313..cf285b0 100644 --- a/cashews/contrib/prometheus.py +++ b/cashews/contrib/prometheus.py @@ -1,29 +1,38 @@ -from typing import Optional - -from prometheus_client import Histogram +from prometheus_client import Counter, Histogram from cashews import cache from cashews._typing import Middleware from cashews.backends.interface import Backend from cashews.commands import Command +_DEFAULT_METRIC = Histogram( + "cashews_operations_latency_seconds", + "Latency of different operations with a cache", + labelnames=["operation", "backend_class", "tag"], +) +_HIT_MISS = Counter( + "cashews_get_operation", + "Count of hits or missed GET operations", + labelnames=["result", "backend_class", "tag"], +) -def create_metrics_middleware(latency_metric: Optional[Histogram] = None, with_tag: bool = False) -> Middleware: - _DEFAULT_METRIC = Histogram( - "cashews_operations_latency_seconds", - "Latency of different operations with a cache", - labelnames=["operation", "backend_class"] if not with_tag else ["operation", "backend_class", "tag"], - ) - _latency_metric = latency_metric or _DEFAULT_METRIC +def create_metrics_middleware(with_tag: bool = False) -> Middleware: async def metrics_middleware(call, cmd: Command, backend: Backend, *args, **kwargs): - with _latency_metric.time() as metric: - metric.labels(operation=cmd.value, backend_class=backend.__class__.__name__) + with _DEFAULT_METRIC.time() as metric: + tag = "" + if with_tag and "key" in kwargs: tags = cache.get_key_tags(kwargs["key"]) - tag = next((t for t in tags), None) - if tag: - metric.labels(tag=tag) - return await call(*args, **kwargs) + tag = next((t for t in tags), "") + metric.labels(operation=cmd.value, backend_class=backend.__class__.__name__, tag=tag) + result = await call(*args, **kwargs) + if cmd is Command.GET: + if result is not kwargs["default"]: + op_result = "hit" + else: + op_result = "miss" + _HIT_MISS.labels(result=op_result, backend_class=backend.__class__.__name__, tag=tag).inc() + return result return metrics_middleware diff --git a/cashews/wrapper/wrapper.py b/cashews/wrapper/wrapper.py index f05b19a..08e4a99 100644 --- a/cashews/wrapper/wrapper.py +++ b/cashews/wrapper/wrapper.py @@ -51,7 +51,13 @@ def _with_middlewares_for_backend(self, cmd: Command, backend, middlewares): call = partial(middleware, call, cmd, backend) return call - def setup(self, settings_url: str, middlewares: tuple = (), prefix: str = default_prefix, **kwargs) -> Backend: + def setup( + self, + settings_url: str, + middlewares: tuple = (), + prefix: str = default_prefix, + **kwargs, + ) -> Backend: backend_class, params = settings_url_parse(settings_url) params.update(kwargs) @@ -76,7 +82,7 @@ def _check_setup(self) -> None: def _add_backend(self, backend: Backend, middlewares=(), prefix: str = default_prefix) -> None: self._backends[prefix] = ( backend, - tuple(self._default_middlewares) + middlewares, + middlewares + tuple(self._default_middlewares), ) async def init(self, *args, **kwargs) -> None: diff --git a/tests/test_intergations/test_prom.py b/tests/test_intergations/test_prom.py index 5a8ee33..9fdd865 100644 --- a/tests/test_intergations/test_prom.py +++ b/tests/test_intergations/test_prom.py @@ -9,7 +9,7 @@ def _middleware(): from cashews.contrib.prometheus import create_metrics_middleware - return create_metrics_middleware() + return create_metrics_middleware(with_tag=True) async def test_smoke(middleware):