-
Notifications
You must be signed in to change notification settings - Fork 652
/
rediscache.py
60 lines (48 loc) · 2.1 KB
/
rediscache.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
"""
This is an example of a library written to work with opentracing-python. It
provides a simple caching decorator backed by Redis, and uses the OpenTracing
Redis integration to automatically generate spans for each call to Redis.
"""
import pickle
from functools import wraps
# FIXME The pylint disablings are needed here because the code of this
# example is being executed against the tox.ini of the main
# opentelemetry-python project. Find a way to separate the two.
import redis # pylint: disable=import-error
import redis_opentracing # pylint: disable=import-error
class RedisCache:
"""Redis-backed caching decorator, using OpenTracing!
Args:
tracer: an opentracing.tracer.Tracer
"""
def __init__(self, tracer):
redis_opentracing.init_tracing(tracer)
self.tracer = tracer
self.client = redis.StrictRedis()
def __call__(self, func):
@wraps(func)
def inner(*args, **kwargs):
with self.tracer.start_active_span("Caching decorator") as scope1:
# Pickle the call args to get a canonical key. Don't do this in
# prod!
key = pickle.dumps((func.__qualname__, args, kwargs))
pval = self.client.get(key)
if pval is not None:
val = pickle.loads(pval)
scope1.span.log_kv(
{"msg": "Found cached value", "val": val}
)
return val
scope1.span.log_kv({"msg": "Cache miss, calling function"})
with self.tracer.start_active_span(
f'Call "{func.__name__}"'
) as scope2:
scope2.span.set_tag("func", func.__name__)
scope2.span.set_tag("args", str(args))
scope2.span.set_tag("kwargs", str(kwargs))
val = func(*args, **kwargs)
scope2.span.set_tag("val", str(val))
# Let keys expire after 10 seconds
self.client.setex(key, 10, pickle.dumps(val))
return val
return inner