def wrapper(*args, **keywords): # determined at run time, since this depends on the invocation context if _should_be_instrumented(state, enable_if, disable_if): # wrap the initialization elapsed = 0 context.push_state(state) t = time.time() try: gen = generator(*args, **keywords) finally: elapsed += time.time() - t context.pop_state(state) try: while True: # wrap each successive value generation context.push_state(state) t = time.time() try: v = six.next(gen) finally: elapsed += time.time() - t context.pop_state(state) yield v finally: # finish metrics (GeneratorExit or otherwise) recorder(elapsed) else: for x in generator(*args, **keywords): yield x
def _urllib_open_wrapper(func, *args, **keywords): """ Wraps urllib.request.url_open """ if not _should_be_instrumented( state='external', enable_if='web', disable_if='model'): return func(*args, **keywords) url = get_parameter(1, 'fullurl', *args, **keywords) if hasattr(url, 'get_full_url'): url = url.get_full_url() scheme = url.split(':')[0] if ':' in url else 'unknown' Timing.push_timer() try: context.push_state('external') telemetry.count('external.{}.requests'.format(scheme)) a = func(*args, **keywords) if a.getcode(): # Not meaningful for ftp etc telemetry.count('external.{}.status.%ixx'.format(scheme) % floor(a.getcode() / 100)) except: telemetry.count('external.{}.errors'.format(scheme)) raise finally: context.pop_state('external') elapsed, _ = Timing.pop_timer() telemetry.record('external.{}.response.latency'.format(scheme), elapsed) # Return a wrapped object so we can time subsequent read, readline etc calls return _response_wrapper(scheme, a)
def decorator(*args, **keywords): # The type of the returned instance depends on the url # but is typically urllib.addinfourl for the baked-in protocols if context.has_state('external'): # Avoid double counting nested calls. All metrics will be reported # relative to the outermost operation return f(*args, **keywords) url = get_parameter(1, 'fullurl', *args, **keywords) if hasattr(url, 'get_full_url'): url = url.get_full_url() scheme = url.split(':')[0] if ':' in url else 'unknown' Timing.push_timer() try: context.push_state('external') telemetry.count('external.{}.requests'.format(scheme)) a = f(*args, **keywords) if a.getcode(): # Not meaningful for ftp etc telemetry.count('external.{}.status.%ixx'.format(scheme) % floor(a.getcode() / 100)) except: telemetry.count('external.{}.errors'.format(scheme)) raise finally: context.pop_state('external') elapsed, _ = Timing.pop_timer() telemetry.record('external.{}.response.latency'.format(scheme), elapsed) # Return a wrapped object so we can time subsequent read, readline etc calls return _response_wrapper(scheme, a)
def wrapper(*args, **keywords): if _should_be_instrumented(state, enable_if, disable_if): try: context.push_state(state) return wrapper_function(f)(*args, **keywords) finally: context.pop_state(state) else: return f(*args, **keywords)
def conditional_wrapper(func, *args, **kwargs): if _should_be_instrumented(state, enable_if, disable_if): try: context.push_state(state) return wrapper(func, *args, **kwargs) finally: context.pop_state(state) else: return func(*args, **kwargs)
def process_response(self, request, response): elapsed, net_elapsed = Timing.pop_timer() if self.is_active: telemetry.record("web.response.latency", elapsed) telemetry.record("app.response.latency", net_elapsed) telemetry.count("web.status.%ixx" % floor(response.status_code / 100)) context.pop_state(STATE_NAME) self.is_active = False else: logger.warn("process_response without request") return response
def process_response(self, request, response): elapsed, net_elapsed = Timing.pop_timer() if self.is_active: telemetry.record('web.response.latency', elapsed) telemetry.record('app.response.latency', net_elapsed) telemetry.count('web.status.%ixx' % floor(response.status_code / 100)) context.pop_state(STATE_NAME) self.is_active = False else: logger.warn('process_response without request') return response
def test_web_state(self): """ Metrics should be reported in web state """ try: push_state('web') self.make_requests() finally: pop_state('web') self.assertEqual(self.reporter.counts, self.expected_web_state_counts) six.assertCountEqual(self, self.reporter.records.keys(), self.expected_web_state_gauges)
def complex_wrapper(func, *args, **keywords): if _should_be_instrumented(state, enable_if, disable_if): Timing.push_timer() context.push_state(state) try: return func(*args, **keywords) finally: elapsed, _ = Timing.pop_timer() count(metric + 'requests', reporter=reporter) record(metric + 'latency', elapsed, reporter=reporter) context.pop_state(state) else: return func(*args, **keywords)
def test_web_state(self): """ Metrics should get reported in web state """ try: push_state('web') self.run_queries() except Exception as e: logger.exception("test_web_state") finally: pop_state('web') self.assertEqual(self.reporter.counts, self.expected_web_state_counts) six.assertCountEqual(self, self.reporter.records.keys(), self.expected_web_state_gauges)
def test_model_state(self): """ Metrics shouldn't get reported in web state if also in model state """ try: push_state('web') push_state('model') self.make_requests() finally: pop_state('model') pop_state('web') self.assertFalse(self.reporter.counts) self.assertFalse(self.reporter.records)
def _wrapped_call(metric, func, *args, **keywords): """ Times and executes arbitrary method """ state = 'external' if not _should_be_instrumented(state, enable_if='web', disable_if='model'): return func(*args, **keywords) Timing.push_timer() try: context.push_state(state) return func(*args, **keywords) finally: context.pop_state(state) elapsed, _ = Timing.pop_timer() telemetry.record(metric, elapsed)
def test_web_state(self): """ Metrics should get reported in web state """ with add_tag('test-context', 'data_test'): try: push_state('web') self.run_queries() except Exception as e: logger.exception("test_web_state") finally: pop_state('web') self.assertEqual(self.reporter.counts, self.expected_web_state_counts) self.assertItemsEqual(self.reporter.records.keys(), self.expected_web_state_gauges)
def wrapper(*args, **keywords): if _should_be_instrumented(state, enable_if, disable_if): # Tags are ignored for now # tag_pairs = _build_key(mapping, args, keywords) try: context.push_state(state) with context_manager(*args, **keywords): if hasattr(f, '__get__'): self = args[0].__subject__ if hasattr(args[0], '__subject__') else args[0] return f.__get__(self)(*args[1:], **keywords) else: return f(*args, **keywords) finally: context.pop_state(state) else: return f(*args, **keywords)
def test_model_state(self): """ Metrics shouldn't get reported in web state if also in model state """ try: push_state('web') push_state('model') self.run_queries() except Exception as e: logger.exception("test_model_state") finally: pop_state('web') pop_state('model') self.assertFalse(self.reporter.counts) self.assertFalse(self.reporter.records)
def wrapper(*args, **keywords): if _should_be_instrumented(state, enable_if, disable_if): # Tags are ignored for now # tag_pairs = _build_key(mapping, args, keywords) try: context.push_state(state) with context_manager(*args, **keywords): if hasattr(f, '__get__'): self = args[0].__subject__ if hasattr( args[0], '__subject__') else args[0] return f.__get__(self)(*args[1:], **keywords) else: return f(*args, **keywords) finally: context.pop_state(state) else: return f(*args, **keywords)
def _session_send_wrapper(func, *args, **keywords): if not _should_be_instrumented(state="external", enable_if="web", disable_if="model"): return func(*args, **keywords) telemetry.count("external.http.requests") Timing.push_timer() try: context.push_state("external") a = func(*args, **keywords) telemetry.count("external.http.status.%ixx" % floor(a.status_code / 100)) return a except: telemetry.count("external.http.errors") raise finally: context.pop_state("external") elapsed, _ = Timing.pop_timer() telemetry.record("external.http.response.latency", elapsed)
def _session_send_wrapper(func, *args, **keywords): if not _should_be_instrumented( state='external', enable_if='web', disable_if='model'): return func(*args, **keywords) telemetry.count('external.http.requests') Timing.push_timer() try: context.push_state('external') a = func(*args, **keywords) telemetry.count('external.http.status.%ixx' % floor(a.status_code / 100)) return a except: telemetry.count('external.http.errors') raise finally: context.pop_state('external') elapsed, _ = Timing.pop_timer() telemetry.record('external.http.response.latency', elapsed)
def test_web_state(self): """ Metrics should get reported in web state """ try: push_state('web') logger.debug("This is a dummy debug message") logger.info("Logging test is running") logger.info("Here is another info message for the books") logger.warning("Ignore this dummy warning message") logger.error("Ignore this dummy error message as well") logger.critical("Ignore this dummy critical message") logger.critical("Ignore this dummy critical message as well") try: raise Exception("This is a dummy exception not a test failure") except: logger.exception("Dummy exception:") expected_counts = { 'logging.exception.requests': 1, 'logging.error.requests': 2, # Exception counts as an error as well 'logging.warning.requests': 1, 'logging.critical.requests': 2, } self.assertEqual(self.reporter.counts, expected_counts) self.assertFalse(self.reporter.records) except Exception as e: logger.exception("test_web_state") finally: pop_state('web')
def pop_state(name): return context.pop_state(name)