Skip to content
Merged
Show file tree
Hide file tree
Changes from 22 commits
Commits
Show all changes
39 commits
Select commit Hold shift + click to select a range
f1a33dd
Added intrastructure and integration point with OTel (#3864)
vladvildanov Dec 8, 2025
ab2af70
Added export of operation duration metric (#3881)
vladvildanov Dec 15, 2025
2e7b2db
Added export of resiliency metrics (#3888)
vladvildanov Dec 17, 2025
f46b1f5
Added export of connection basic metrics (#3891)
vladvildanov Jan 5, 2026
57cf6d7
Added pub/sub and stream lag metrics export (#3898)
vladvildanov Jan 5, 2026
26a11c2
Added OTel benchmark test (#3903)
vladvildanov Jan 5, 2026
9dc37a8
Added export of connection advanced metrics (#3910)
vladvildanov Jan 19, 2026
ce58929
Added CSC metrics export (#3911)
vladvildanov Jan 20, 2026
c4a4292
Added memory and CPU usage (#3933)
vladvildanov Feb 3, 2026
98c6030
Removed events dispatching overhead, refactored metrics attributes (#…
vladvildanov Feb 4, 2026
2f3fd25
Added async recorders and registry (#3950)
vladvildanov Feb 11, 2026
f48a4e0
Added bucket override configuration (#3952)
vladvildanov Feb 11, 2026
6c28630
Remove async instrumentations (#3953)
vladvildanov Feb 12, 2026
6bc1c74
Merge branch 'master' of github.com:redis/redis-py into feat/observab…
vladvildanov Feb 12, 2026
1f387e6
Fix tests and codestyle
vladvildanov Feb 12, 2026
810e97d
Fixed missing parameters
vladvildanov Feb 12, 2026
2f08920
Fixed tests
vladvildanov Feb 12, 2026
ce3ff2e
Fixed tests
vladvildanov Feb 12, 2026
12173fb
Fixed tests
vladvildanov Feb 12, 2026
b1023b4
Marked argument as unused
vladvildanov Feb 12, 2026
4de2db4
Fixed tests
vladvildanov Feb 12, 2026
4dc1802
Added missing metric export
vladvildanov Feb 12, 2026
453101d
Fixes units and pool name attribute
elena-kolevska Feb 12, 2026
42d7b6c
Updated test for pool name attribute
elena-kolevska Feb 13, 2026
15cd729
Updates more tests
elena-kolevska Feb 13, 2026
dc66503
Linter
elena-kolevska Feb 13, 2026
0989bfe
Added try...except blocks for recorder functions
vladvildanov Feb 13, 2026
304dd72
Added documentation
vladvildanov Feb 13, 2026
647567e
Updated wordlist
vladvildanov Feb 13, 2026
392ca36
Update redis/cluster.py
vladvildanov Feb 13, 2026
d8c68c1
Update redis/connection.py
vladvildanov Feb 13, 2026
8a93c8c
Update redis/connection.py
vladvildanov Feb 13, 2026
efc817a
Update pyproject.toml
vladvildanov Feb 16, 2026
ee7702a
Merge branch 'master' of github.com:redis/redis-py into feat/observab…
vladvildanov Feb 16, 2026
2cdc1b7
Codestyle fixes
vladvildanov Feb 16, 2026
734578d
Fixed metric export
vladvildanov Feb 16, 2026
88a9964
Fixed assertions
vladvildanov Feb 16, 2026
327bfbe
Added geo failover metric export
vladvildanov Feb 16, 2026
7a254ed
Codestyle fixes
vladvildanov Feb 16, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
843 changes: 843 additions & 0 deletions benchmarks/otel_benchmark.py

Large diffs are not rendered by default.

4 changes: 4 additions & 0 deletions dev_requirements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -30,3 +30,7 @@ redis-entraid==1.0.0
pybreaker>=1.4.0

xxhash==3.6.0

opentelemetry-api>=1.30.0
opentelemetry-sdk>=1.30.0
opentelemetry-exporter-otlp>=1.30.0
5 changes: 5 additions & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,11 @@ jwt = [
circuit_breaker = [
"pybreaker>=1.4.0"
]
otel = [
"opentelemetry-api>=1.30.0",
"opentelemetry-sdk>=1.30.0",
"opentelemetry-exporter-otlp-proto-http>=1.30.0",
]

[project.urls]
Changes = "https://github.com/redis/redis-py/releases"
Expand Down
2 changes: 1 addition & 1 deletion redis/_parsers/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -112,7 +112,7 @@ def parse_error(cls, response):
exception_class = cls.EXCEPTION_CLASSES[error_code]
if isinstance(exception_class, dict):
exception_class = exception_class.get(response, ResponseError)
return exception_class(response)
return exception_class(response, status_code=error_code)
return ResponseError(response)

def on_disconnect(self):
Expand Down
62 changes: 58 additions & 4 deletions redis/cache.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@
from enum import Enum
from typing import Any, List, Optional, Union

from redis.observability.attributes import CSCReason


class CacheEntryStatus(Enum):
VALID = "VALID"
Expand Down Expand Up @@ -186,9 +188,6 @@ def set(self, entry: CacheEntry) -> bool:
self._cache[entry.cache_key] = entry
self._eviction_policy.touch(entry.cache_key)

if self._cache_config.is_exceeds_max_size(len(self._cache)):
self._eviction_policy.evict_next()

return True

def get(self, key: CacheKey) -> Union[CacheEntry, None]:
Expand Down Expand Up @@ -248,6 +247,61 @@ def is_cachable(self, key: CacheKey) -> bool:
return self._cache_config.is_allowed_to_cache(key.command)


class CacheProxy(CacheInterface):
"""
Proxy object that wraps cache implementations to enable additional logic on top
"""

def __init__(self, cache: CacheInterface):
self._cache = cache

@property
def collection(self) -> OrderedDict:
return self._cache.collection

@property
def config(self) -> CacheConfigurationInterface:
return self._cache.config

@property
def eviction_policy(self) -> EvictionPolicyInterface:
return self._cache.eviction_policy

@property
def size(self) -> int:
return self._cache.size

def get(self, key: CacheKey) -> Union[CacheEntry, None]:
return self._cache.get(key)

def set(self, entry: CacheEntry) -> bool:
is_set = self._cache.set(entry)

if self.config.is_exceeds_max_size(self.size):
# Lazy import to avoid circular dependency
from redis.observability.recorder import record_csc_eviction

record_csc_eviction(
count=1,
reason=CSCReason.FULL,
)
self.eviction_policy.evict_next()

return is_set

def delete_by_cache_keys(self, cache_keys: List[CacheKey]) -> List[bool]:
return self._cache.delete_by_cache_keys(cache_keys)

def delete_by_redis_keys(self, redis_keys: List[bytes]) -> List[bool]:
return self._cache.delete_by_redis_keys(redis_keys)

def flush(self) -> int:
return self._cache.flush()

def is_cachable(self, key: CacheKey) -> bool:
return self._cache.is_cachable(key)


class LRUPolicy(EvictionPolicyInterface):
def __init__(self):
self.cache = None
Expand Down Expand Up @@ -422,4 +476,4 @@ def __init__(self, cache_config: Optional[CacheConfig] = None):

def get_cache(self) -> CacheInterface:
cache_class = self._config.get_cache_class()
return cache_class(cache_config=self._config)
return CacheProxy(cache_class(cache_config=self._config))
Loading
Loading