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