38 lines
1.6 KiB
Python
38 lines
1.6 KiB
Python
import dogpile
|
|
|
|
from ...pin import Pin
|
|
from ...utils.formats import asbool
|
|
|
|
|
|
def _wrap_lock_ctor(func, instance, args, kwargs):
|
|
"""
|
|
This seems rather odd. But to track hits, we need to patch the wrapped function that
|
|
dogpile passes to the region and locks. Unfortunately it's a closure defined inside
|
|
the get_or_create* methods themselves, so we can't easily patch those.
|
|
"""
|
|
func(*args, **kwargs)
|
|
ori_backend_fetcher = instance.value_and_created_fn
|
|
|
|
def wrapped_backend_fetcher():
|
|
pin = Pin.get_from(dogpile.cache)
|
|
if not pin or not pin.enabled():
|
|
return ori_backend_fetcher()
|
|
|
|
hit = False
|
|
expired = True
|
|
try:
|
|
value, createdtime = ori_backend_fetcher()
|
|
hit = value is not dogpile.cache.api.NO_VALUE
|
|
# dogpile sometimes returns None, but only checks for truthiness. Coalesce
|
|
# to minimize APM users' confusion.
|
|
expired = instance._is_expired(createdtime) or False
|
|
return value, createdtime
|
|
finally:
|
|
# Keys are checked in random order so the 'final' answer for partial hits
|
|
# should really be false (ie. if any are 'negative', then the tag value
|
|
# should be). This means ANDing all hit values and ORing all expired values.
|
|
span = pin.tracer.current_span()
|
|
span.set_tag('hit', asbool(span.get_tag('hit') or 'True') and hit)
|
|
span.set_tag('expired', asbool(span.get_tag('expired') or 'False') or expired)
|
|
instance.value_and_created_fn = wrapped_backend_fetcher
|