redis-client-kit 0.2.0__tar.gz → 0.3.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {redis_client_kit-0.2.0 → redis_client_kit-0.3.0}/CHANGELOG.md +7 -0
- {redis_client_kit-0.2.0 → redis_client_kit-0.3.0}/PKG-INFO +8 -3
- {redis_client_kit-0.2.0 → redis_client_kit-0.3.0}/README.md +7 -2
- {redis_client_kit-0.2.0 → redis_client_kit-0.3.0}/redis_client_kit/__init__.py +1 -1
- redis_client_kit-0.3.0/redis_client_kit/__version__.py +1 -0
- {redis_client_kit-0.2.0 → redis_client_kit-0.3.0}/redis_client_kit/config.py +1 -0
- {redis_client_kit-0.2.0 → redis_client_kit-0.3.0}/redis_client_kit/metrics/__init__.py +2 -2
- {redis_client_kit-0.2.0 → redis_client_kit-0.3.0}/redis_client_kit/metrics/redis.py +31 -1
- {redis_client_kit-0.2.0 → redis_client_kit-0.3.0}/redis_client_kit/providers/__init__.py +2 -1
- redis_client_kit-0.3.0/redis_client_kit/providers/metrics.py +44 -0
- redis_client_kit-0.2.0/redis_client_kit/__version__.py +0 -1
- {redis_client_kit-0.2.0 → redis_client_kit-0.3.0}/.gitignore +0 -0
- {redis_client_kit-0.2.0 → redis_client_kit-0.3.0}/LICENSE +0 -0
- {redis_client_kit-0.2.0 → redis_client_kit-0.3.0}/pyproject.toml +0 -0
- {redis_client_kit-0.2.0 → redis_client_kit-0.3.0}/redis_client_kit/aio/__init__.py +0 -0
- {redis_client_kit-0.2.0 → redis_client_kit-0.3.0}/redis_client_kit/aio/factory.py +0 -0
- {redis_client_kit-0.2.0 → redis_client_kit-0.3.0}/redis_client_kit/aio/instrumented.py +0 -0
- {redis_client_kit-0.2.0 → redis_client_kit-0.3.0}/redis_client_kit/aio/lifecycle.py +0 -0
- {redis_client_kit-0.2.0 → redis_client_kit-0.3.0}/redis_client_kit/aio/types.py +0 -0
- {redis_client_kit-0.2.0 → redis_client_kit-0.3.0}/redis_client_kit/metrics/_deps.py +0 -0
- {redis_client_kit-0.2.0 → redis_client_kit-0.3.0}/redis_client_kit/protocols.py +0 -0
- {redis_client_kit-0.2.0 → redis_client_kit-0.3.0}/redis_client_kit/providers/_deps.py +0 -0
- {redis_client_kit-0.2.0 → redis_client_kit-0.3.0}/redis_client_kit/providers/redis.py +0 -0
- {redis_client_kit-0.2.0 → redis_client_kit-0.3.0}/redis_client_kit/providers/utils.py +0 -0
- {redis_client_kit-0.2.0 → redis_client_kit-0.3.0}/redis_client_kit/py.typed +0 -0
- {redis_client_kit-0.2.0 → redis_client_kit-0.3.0}/redis_client_kit/settings/__init__.py +0 -0
- {redis_client_kit-0.2.0 → redis_client_kit-0.3.0}/redis_client_kit/settings/_deps.py +0 -0
- {redis_client_kit-0.2.0 → redis_client_kit-0.3.0}/redis_client_kit/settings/redis.py +0 -0
- {redis_client_kit-0.2.0 → redis_client_kit-0.3.0}/redis_client_kit/sync/__init__.py +0 -0
- {redis_client_kit-0.2.0 → redis_client_kit-0.3.0}/redis_client_kit/sync/factory.py +0 -0
- {redis_client_kit-0.2.0 → redis_client_kit-0.3.0}/redis_client_kit/sync/instrumented.py +0 -0
- {redis_client_kit-0.2.0 → redis_client_kit-0.3.0}/redis_client_kit/sync/lifecycle.py +0 -0
- {redis_client_kit-0.2.0 → redis_client_kit-0.3.0}/redis_client_kit/sync/types.py +0 -0
- {redis_client_kit-0.2.0 → redis_client_kit-0.3.0}/redis_client_kit/utils.py +0 -0
|
@@ -1,5 +1,12 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## [0.3.0](https://github.com/bedrock-python/redis-client-kit/compare/redis-client-kit-v0.2.0...redis-client-kit-v0.3.0) (2026-09-15)
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
### Features
|
|
7
|
+
|
|
8
|
+
* ship PrometheusRedisMetricsProvider and a cached get_redis_metrics ([fbe8feb](https://github.com/bedrock-python/redis-client-kit/commit/fbe8feba0b3041d6af4744482419156e7b1ca8e7))
|
|
9
|
+
|
|
3
10
|
## [0.2.0](https://github.com/bedrock-python/redis-client-kit/compare/redis-client-kit-v0.1.5...redis-client-kit-v0.2.0) (2026-09-07)
|
|
4
11
|
|
|
5
12
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.5
|
|
2
2
|
Name: redis-client-kit
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.3.0
|
|
4
4
|
Summary: Redis client with optional Pydantic, Prometheus, and Dishka support
|
|
5
5
|
Project-URL: Repository, https://github.com/bedrock-python/redis-client-kit
|
|
6
6
|
Project-URL: Documentation, https://bedrock-python.github.io/redis-client-kit/
|
|
@@ -425,14 +425,19 @@ client = create_async_redis_client(settings, metrics=metrics)
|
|
|
425
425
|
# - myapp_redis_connection_errors_total{error_type}
|
|
426
426
|
```
|
|
427
427
|
|
|
428
|
+
Prometheus registers a metric name once per process, so a second `RedisMetrics(prefix="myapp")`
|
|
429
|
+
raises `ValueError`. `get_redis_metrics(prefix="myapp")` returns the one instance per prefix
|
|
430
|
+
instead, which is what a test suite that rebuilds its container per test wants.
|
|
431
|
+
|
|
428
432
|
### With Dishka DI
|
|
429
433
|
|
|
430
434
|
```python
|
|
431
435
|
from dishka import make_async_container
|
|
432
|
-
from redis_client_kit.providers import AsyncRedisProvider
|
|
436
|
+
from redis_client_kit.providers import AsyncRedisProvider, PrometheusRedisMetricsProvider
|
|
433
437
|
|
|
434
438
|
container = make_async_container(
|
|
435
|
-
AsyncRedisProvider(),
|
|
439
|
+
AsyncRedisProvider(provide_default_metrics=False),
|
|
440
|
+
PrometheusRedisMetricsProvider(), # RedisMetrics when settings.metrics_enabled, else None
|
|
436
441
|
SettingsProvider(), # Your settings provider
|
|
437
442
|
)
|
|
438
443
|
|
|
@@ -185,14 +185,19 @@ client = create_async_redis_client(settings, metrics=metrics)
|
|
|
185
185
|
# - myapp_redis_connection_errors_total{error_type}
|
|
186
186
|
```
|
|
187
187
|
|
|
188
|
+
Prometheus registers a metric name once per process, so a second `RedisMetrics(prefix="myapp")`
|
|
189
|
+
raises `ValueError`. `get_redis_metrics(prefix="myapp")` returns the one instance per prefix
|
|
190
|
+
instead, which is what a test suite that rebuilds its container per test wants.
|
|
191
|
+
|
|
188
192
|
### With Dishka DI
|
|
189
193
|
|
|
190
194
|
```python
|
|
191
195
|
from dishka import make_async_container
|
|
192
|
-
from redis_client_kit.providers import AsyncRedisProvider
|
|
196
|
+
from redis_client_kit.providers import AsyncRedisProvider, PrometheusRedisMetricsProvider
|
|
193
197
|
|
|
194
198
|
container = make_async_container(
|
|
195
|
-
AsyncRedisProvider(),
|
|
199
|
+
AsyncRedisProvider(provide_default_metrics=False),
|
|
200
|
+
PrometheusRedisMetricsProvider(), # RedisMetrics when settings.metrics_enabled, else None
|
|
196
201
|
SettingsProvider(), # Your settings provider
|
|
197
202
|
)
|
|
198
203
|
|
|
@@ -24,7 +24,7 @@ from .utils import build_base_redis_kwargs, build_redis_retry, parse_redis_url_n
|
|
|
24
24
|
try:
|
|
25
25
|
__version__ = version("redis-client-kit")
|
|
26
26
|
except PackageNotFoundError: # pragma: no cover
|
|
27
|
-
__version__ = "0.
|
|
27
|
+
__version__ = "0.3.0"
|
|
28
28
|
|
|
29
29
|
# ruff: noqa: RUF022
|
|
30
30
|
__all__ = [
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
__version__ = "0.3.0"
|
|
@@ -5,6 +5,6 @@ from ._deps import HAS_PROMETHEUS
|
|
|
5
5
|
if not HAS_PROMETHEUS:
|
|
6
6
|
raise ImportError("prometheus-client not installed. Install redis-client-kit[metrics] to use metrics.")
|
|
7
7
|
|
|
8
|
-
from .redis import REDIS_COMMAND_DURATION_BUCKETS, RedisMetrics
|
|
8
|
+
from .redis import REDIS_COMMAND_DURATION_BUCKETS, RedisMetrics, get_redis_metrics
|
|
9
9
|
|
|
10
|
-
__all__ = ["REDIS_COMMAND_DURATION_BUCKETS", "RedisMetrics"]
|
|
10
|
+
__all__ = ["REDIS_COMMAND_DURATION_BUCKETS", "RedisMetrics", "get_redis_metrics"]
|
|
@@ -30,6 +30,9 @@ class RedisMetrics:
|
|
|
30
30
|
>>> metrics = RedisMetrics(prefix="myapp")
|
|
31
31
|
>>> metrics.record_command("GET", "success", 0.001)
|
|
32
32
|
>>> metrics.record_pool_stats(pool_size=10, pool_checked_out=3)
|
|
33
|
+
|
|
34
|
+
Prometheus registers a metric name once per registry, so a second instance with the
|
|
35
|
+
same prefix raises ``ValueError``; ``get_redis_metrics`` hands back the first one instead.
|
|
33
36
|
"""
|
|
34
37
|
|
|
35
38
|
def __init__(self, prefix: str | None = None) -> None:
|
|
@@ -37,6 +40,10 @@ class RedisMetrics:
|
|
|
37
40
|
|
|
38
41
|
Args:
|
|
39
42
|
prefix: Optional metric name prefix (e.g., "myapp" -> "myapp_redis_pool_size")
|
|
43
|
+
|
|
44
|
+
Raises:
|
|
45
|
+
ValueError: If a metric of the same name is already registered on the default
|
|
46
|
+
registry -- see ``get_redis_metrics`` for the second instance.
|
|
40
47
|
"""
|
|
41
48
|
metric_prefix = f"{prefix}_" if prefix else ""
|
|
42
49
|
|
|
@@ -95,4 +102,27 @@ class RedisMetrics:
|
|
|
95
102
|
self.pool_checked_out.set(float(pool_checked_out))
|
|
96
103
|
|
|
97
104
|
|
|
98
|
-
|
|
105
|
+
_REDIS_METRICS_CACHE: dict[str | None, RedisMetrics] = {}
|
|
106
|
+
|
|
107
|
+
|
|
108
|
+
def get_redis_metrics(prefix: str | None = None) -> RedisMetrics:
|
|
109
|
+
"""Get (or lazily create) the cached ``RedisMetrics`` for a prefix, on the default registry.
|
|
110
|
+
|
|
111
|
+
Caching by prefix is what lets a container be rebuilt -- a test suite does it per test --
|
|
112
|
+
without Prometheus refusing the second registration of the same series.
|
|
113
|
+
|
|
114
|
+
Args:
|
|
115
|
+
prefix: The metric name prefix the instance was, or is, created with; ``""`` and
|
|
116
|
+
``None`` are the same unprefixed instance.
|
|
117
|
+
|
|
118
|
+
Returns:
|
|
119
|
+
The one instance for that prefix.
|
|
120
|
+
"""
|
|
121
|
+
key = prefix or None
|
|
122
|
+
metrics = _REDIS_METRICS_CACHE.get(key)
|
|
123
|
+
if metrics is None:
|
|
124
|
+
metrics = _REDIS_METRICS_CACHE[key] = RedisMetrics(prefix=key)
|
|
125
|
+
return metrics
|
|
126
|
+
|
|
127
|
+
|
|
128
|
+
__all__ = ["REDIS_COMMAND_DURATION_BUCKETS", "RedisMetrics", "get_redis_metrics"]
|
|
@@ -5,6 +5,7 @@ from ._deps import HAS_DISHKA
|
|
|
5
5
|
if not HAS_DISHKA:
|
|
6
6
|
raise ImportError("dishka not installed. Install redis-client-kit[providers] to use AsyncRedisProvider.")
|
|
7
7
|
|
|
8
|
+
from .metrics import PrometheusRedisMetricsProvider
|
|
8
9
|
from .redis import AsyncRedisProvider
|
|
9
10
|
|
|
10
|
-
__all__ = ["AsyncRedisProvider"]
|
|
11
|
+
__all__ = ["AsyncRedisProvider", "PrometheusRedisMetricsProvider"]
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
"""Dishka provider for the Prometheus Redis metrics collector."""
|
|
2
|
+
|
|
3
|
+
from ..config import RedisSettingsProtocol
|
|
4
|
+
from ..protocols import RedisMetricsProtocol
|
|
5
|
+
from ._deps import Provider, Scope, provide
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
class PrometheusRedisMetricsProvider(Provider): # type: ignore[misc]
|
|
9
|
+
"""Dishka provider for the collector ``AsyncRedisProvider`` records into.
|
|
10
|
+
|
|
11
|
+
Provides ``RedisMetricsProtocol | None`` -- the key ``AsyncRedisProvider`` reads -- as
|
|
12
|
+
``get_redis_metrics(prefix)`` when ``settings.metrics_enabled`` and ``None`` otherwise,
|
|
13
|
+
so the client is instrumented exactly when the settings say so. Register it with
|
|
14
|
+
``AsyncRedisProvider(provide_default_metrics=False)``, or after ``AsyncRedisProvider()``,
|
|
15
|
+
since the last provider of a type wins.
|
|
16
|
+
|
|
17
|
+
The collector comes from ``get_redis_metrics``: one instance per prefix on the default
|
|
18
|
+
registry, so a container rebuilt per test never asks Prometheus to register the same
|
|
19
|
+
series twice. Resolving it with metrics on needs the ``metrics`` extra; without it the
|
|
20
|
+
import raises ``ImportError`` naming the extra.
|
|
21
|
+
"""
|
|
22
|
+
|
|
23
|
+
scope = Scope.APP # type: ignore[misc]
|
|
24
|
+
|
|
25
|
+
def __init__(self, *, prefix: str | None = None) -> None:
|
|
26
|
+
"""Remember the prefix the collector is created with.
|
|
27
|
+
|
|
28
|
+
Args:
|
|
29
|
+
prefix: Metric name prefix (``"myapp"`` gives ``myapp_redis_pool_size``)
|
|
30
|
+
"""
|
|
31
|
+
super().__init__()
|
|
32
|
+
self._prefix = prefix
|
|
33
|
+
|
|
34
|
+
@provide
|
|
35
|
+
def get_metrics(self, redis_settings: RedisSettingsProtocol) -> RedisMetricsProtocol | None:
|
|
36
|
+
"""Provide the collector when ``metrics_enabled`` is on, ``None`` otherwise."""
|
|
37
|
+
if not redis_settings.metrics_enabled:
|
|
38
|
+
return None
|
|
39
|
+
from ..metrics import get_redis_metrics # noqa: PLC0415 - lazy: needs the [metrics] extra
|
|
40
|
+
|
|
41
|
+
return get_redis_metrics(self._prefix)
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
__all__ = ["PrometheusRedisMetricsProvider"]
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
__version__ = "0.2.0"
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|