Files
2020-04-08 10:39:44 -07:00

147 lines
5.1 KiB
Python

"""
Datadog trace code for flask_cache
"""
# stdlib
import logging
# project
from .utils import _extract_conn_tags, _resource_from_cache_prefix
from ...constants import ANALYTICS_SAMPLE_RATE_KEY
from ...ext import SpanTypes
from ...settings import config
# 3rd party
from flask.ext.cache import Cache
log = logging.Logger(__name__)
DEFAULT_SERVICE = 'flask-cache'
# standard tags
COMMAND_KEY = 'flask_cache.key'
CACHE_BACKEND = 'flask_cache.backend'
CONTACT_POINTS = 'flask_cache.contact_points'
def get_traced_cache(ddtracer, service=DEFAULT_SERVICE, meta=None):
"""
Return a traced Cache object that behaves exactly as the ``flask.ext.cache.Cache class``
"""
class TracedCache(Cache):
"""
Traced cache backend that monitors any operations done by flask_cache. Observed actions are:
* get, set, add, delete, clear
* all ``many_`` operations
"""
_datadog_tracer = ddtracer
_datadog_service = service
_datadog_meta = meta
def __trace(self, cmd):
"""
Start a tracing with default attributes and tags
"""
# create a new span
s = self._datadog_tracer.trace(
cmd,
span_type=SpanTypes.CACHE,
service=self._datadog_service
)
# set span tags
s.set_tag(CACHE_BACKEND, self.config.get('CACHE_TYPE'))
s.set_tags(self._datadog_meta)
# set analytics sample rate
s.set_tag(
ANALYTICS_SAMPLE_RATE_KEY,
config.flask_cache.get_analytics_sample_rate()
)
# add connection meta if there is one
if getattr(self.cache, '_client', None):
try:
s.set_tags(_extract_conn_tags(self.cache._client))
except Exception:
log.debug('error parsing connection tags', exc_info=True)
return s
def get(self, *args, **kwargs):
"""
Track ``get`` operation
"""
with self.__trace('flask_cache.cmd') as span:
span.resource = _resource_from_cache_prefix('GET', self.config)
if len(args) > 0:
span.set_tag(COMMAND_KEY, args[0])
return super(TracedCache, self).get(*args, **kwargs)
def set(self, *args, **kwargs):
"""
Track ``set`` operation
"""
with self.__trace('flask_cache.cmd') as span:
span.resource = _resource_from_cache_prefix('SET', self.config)
if len(args) > 0:
span.set_tag(COMMAND_KEY, args[0])
return super(TracedCache, self).set(*args, **kwargs)
def add(self, *args, **kwargs):
"""
Track ``add`` operation
"""
with self.__trace('flask_cache.cmd') as span:
span.resource = _resource_from_cache_prefix('ADD', self.config)
if len(args) > 0:
span.set_tag(COMMAND_KEY, args[0])
return super(TracedCache, self).add(*args, **kwargs)
def delete(self, *args, **kwargs):
"""
Track ``delete`` operation
"""
with self.__trace('flask_cache.cmd') as span:
span.resource = _resource_from_cache_prefix('DELETE', self.config)
if len(args) > 0:
span.set_tag(COMMAND_KEY, args[0])
return super(TracedCache, self).delete(*args, **kwargs)
def delete_many(self, *args, **kwargs):
"""
Track ``delete_many`` operation
"""
with self.__trace('flask_cache.cmd') as span:
span.resource = _resource_from_cache_prefix('DELETE_MANY', self.config)
span.set_tag(COMMAND_KEY, list(args))
return super(TracedCache, self).delete_many(*args, **kwargs)
def clear(self, *args, **kwargs):
"""
Track ``clear`` operation
"""
with self.__trace('flask_cache.cmd') as span:
span.resource = _resource_from_cache_prefix('CLEAR', self.config)
return super(TracedCache, self).clear(*args, **kwargs)
def get_many(self, *args, **kwargs):
"""
Track ``get_many`` operation
"""
with self.__trace('flask_cache.cmd') as span:
span.resource = _resource_from_cache_prefix('GET_MANY', self.config)
span.set_tag(COMMAND_KEY, list(args))
return super(TracedCache, self).get_many(*args, **kwargs)
def set_many(self, *args, **kwargs):
"""
Track ``set_many`` operation
"""
with self.__trace('flask_cache.cmd') as span:
span.resource = _resource_from_cache_prefix('SET_MANY', self.config)
if len(args) > 0:
span.set_tag(COMMAND_KEY, list(args[0].keys()))
return super(TracedCache, self).set_many(*args, **kwargs)
return TracedCache