diff --git a/api/datalake_api/sentry.py b/api/datalake_api/sentry.py new file mode 100644 index 0000000..1273343 --- /dev/null +++ b/api/datalake_api/sentry.py @@ -0,0 +1,54 @@ +from sentry_sdk import Hub, start_transaction +import functools + + +class SentryTransaction: + ''' + Context manager for performance monitoring in sentry. Used by the + monitor_performance decorator. You can also use this to track any + block of code. Example: + + with sentry.SentryTransaction(op='MetisCaptureCalculator'): + # tracked code here + ''' + def __init__(self, name=None, tags=None, transaction=None, op='default'): + self.op = op + self.name = name + self.tags = tags + self.hub = Hub.current + self.transaction = transaction or self.hub.scope.transaction + self.span = self.hub.scope.span + self.new_transaction = None + + def __enter__(self): + if self.transaction is None: + self.new_transaction = start_transaction( + name=self.name, op=self.op) + else: + self.new_transaction = self.span.start_child( + op=self.op, hub=self.hub + ) + if self.tags: + for key, value in self.tags.items(): + self.new_transaction.set_tag(key, value) + + def __exit__(self, type, value, traceback): + self.new_transaction.finish() + + +def monitor_performance(op=None): + ''' + Use @monitor_performance() decorator to add + sentry performance monitoring to function. + Use without arguments to use function name, + or optionally add custom name seen in sentry + ''' + def _monitor_performance(f): + + @functools.wraps(f) + def wrapper(*args, **kwargs): + op_name = op or f.__name__ + with SentryTransaction(op=op_name): + return f(*args, **kwargs) + return wrapper + return _monitor_performance \ No newline at end of file diff --git a/api/datalake_api/v0.py b/api/datalake_api/v0.py index 376c49b..dde7c3a 100644 --- a/api/datalake_api/v0.py +++ b/api/datalake_api/v0.py @@ -23,7 +23,7 @@ from .fetcher import ArchiveFileFetcher from datalake.common.errors import NoSuchDatalakeFile from datalake.common.metadata import Metadata, InvalidDatalakeMetadata - +from .sentry import monitor_performance v0 = flask.Blueprint('v0', __name__, url_prefix='/v0') @@ -143,6 +143,7 @@ def _copy_immutable_dict(d): return {k: v for k, v in d.items()} +@monitor_performance() @v0.route('/archive/files/') def files_get(): '''List files @@ -389,7 +390,7 @@ def _get_headers_for_file(f): headers['Content-Encoding'] = f.content_encoding return headers - +@monitor_performance() def _get_latest(what, where, lookback): aq = get_archive_querier() f = aq.query_latest(what, where, lookback_days=lookback)