def _should_be_instrumented(state, enable_if, disable_if): """ Returns False if the method should not be instrumented given the current state. Any value can be None to indicate no change. :param state: the new state :param enable_if: enable instrumentation iff this state is present :param disable_if: disable instrumentation iff this state is present :return: True if rules indicate this should be instrumented, false otherwise """ if enable_if and not context.has_state(enable_if): logger.debug('skipping %s instrumentation, lacks enable_if=%s', state, enable_if) return False if disable_if and context.has_state(disable_if): logger.debug('skipping %s instrumentation, has disable_if=%s', state, disable_if) return False if state and context.has_state(state): logger.debug('skipping instrumentation, state=%s already present', state) return False return True
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 has_state(name): return context.has_state(name)