Esempio n. 1
0
 def new_f(*args, **kwargs):
     try:
         return f(*args, **kwargs)
     except InputParameterError as e:
         msgStr = str(e)
         log.warning('%s', msgStr)
         return HttpResponseBadRequest(msgStr)
Esempio n. 2
0
    def find(self,
             pattern,
             startTime=None,
             endTime=None,
             local=False,
             headers=None,
             leaves_only=False):
        query = FindQuery(pattern,
                          startTime,
                          endTime,
                          local=local,
                          headers=headers,
                          leaves_only=leaves_only)

        warn_threshold = settings.METRICS_FIND_WARNING_THRESHOLD
        fail_threshold = settings.METRICS_FIND_FAILURE_THRESHOLD

        matched_leafs = 0
        for match in self._find(query):
            if isinstance(match, LeafNode):
                matched_leafs += 1
            elif leaves_only:
                continue
            if matched_leafs > fail_threshold:
                raise Exception(
                    ("Query %s yields too many results and failed "
                     "(failure threshold is %d)") % (pattern, fail_threshold))
            yield match

        if matched_leafs > warn_threshold:
            log.warning(("Query %s yields large number of results up to %d "
                         "(warning threshold is %d)") %
                        (pattern, matched_leafs, warn_threshold))
Esempio n. 3
0
    def find(self, pattern, startTime=None, endTime=None, local=False, headers=None, leaves_only=False):
        query = FindQuery(
            pattern, startTime, endTime,
            local=local,
            headers=headers,
            leaves_only=leaves_only
        )

        warn_threshold = settings.METRICS_FIND_WARNING_THRESHOLD
        fail_threshold = settings.METRICS_FIND_FAILURE_THRESHOLD

        matched_leafs = 0
        for match in self._find(query):
            if isinstance(match, LeafNode):
                matched_leafs += 1
            elif leaves_only:
                continue
            if matched_leafs > fail_threshold:
                raise Exception(
                    ("Query %s yields too many results and failed "
                     "(failure threshold is %d)") % (pattern, fail_threshold))
            yield match

        if matched_leafs > warn_threshold:
            log.warning(
                ("Query %s yields large number of results up to %d "
                 "(warning threshold is %d)") % (
                     pattern, matched_leafs, warn_threshold))
Esempio n. 4
0
    def validateAggFuncs(self, value):
        if value in self.getValidAggFuncs():
            return value

        if value in self.getDeprecatedAggFuncs():
            log.warning('Deprecated aggregation function: {value}'.format(value=repr(value)))
            return value

        raise ValueError('Invalid aggregation function: {value}'.format(value=repr(value)))
Esempio n. 5
0
def epoch(dt):
  """
  Returns the epoch timestamp of a timezone-aware datetime object.
  """
  if not dt.tzinfo:
    tb = traceback.extract_stack(None, 2)
    log.warning('epoch() called with non-timezone-aware datetime in %s at %s:%d' % (tb[0][2], tb[0][0], tb[0][1]))
    return calendar.timegm(make_aware(dt, pytz.timezone(settings.TIME_ZONE)).astimezone(pytz.utc).timetuple())
  return calendar.timegm(dt.astimezone(pytz.utc).timetuple())
Esempio n. 6
0
def epoch(dt):
  """
  Returns the epoch timestamp of a timezone-aware datetime object.
  """
  if not dt.tzinfo:
    tb = traceback.extract_stack(None, 2)
    log.warning('epoch() called with non-timezone-aware datetime in %s at %s:%d' % (tb[0][2], tb[0][0], tb[0][1]))
    return calendar.timegm(make_aware(dt, pytz.timezone(settings.TIME_ZONE)).astimezone(pytz.utc).timetuple())
  return calendar.timegm(dt.astimezone(pytz.utc).timetuple())
Esempio n. 7
0
  def validateAggFuncs(self, value):
    if value in self.getValidAggFuncs():
      return True

    if value in self.getDeprecatedAggFuncs():
      log.warning('Deprecated aggregation function "{value}" used'.format(value=value))
      return True

    return False
Esempio n. 8
0
        def handleInvalidParameters(e):
            if not getattr(handleInvalidParameters, 'alreadyLogged', False):
                log.warning(
                    invalidParamLogMsg(requestContext, str(e),
                                       tokens.call.funcname, args, kwargs))

                # only log invalid parameters once
                setattr(handleInvalidParameters, 'alreadyLogged', True)

            if settings.ENFORCE_INPUT_VALIDATION:
                raise
    def handleInvalidParameters(e):
      e.setSourceIdHeaders(requestContext.get('sourceIdHeaders', {}))
      e.setTargets(requestContext.get('targets', []))
      e.setFunction(tokens.call.funcname, args, kwargs)

      if settings.ENFORCE_INPUT_VALIDATION:
        raise e

      if not getattr(handleInvalidParameters, 'alreadyLogged', False):
        log.warning('%s', str(e))

        # only log invalid parameters once
        setattr(handleInvalidParameters, 'alreadyLogged', True)
Esempio n. 10
0
  def _add(self, key, val):
    realval = None
    try:
      if val != '':
        realval = int(val)
    except:
      log.warning('unexpected val for %s: %s' % (key, val))

    branches = key.split('.')
    cursor = self.tree
    leaf = branches.pop()
    for branch in branches:
      if branch not in cursor[1]:
        cursor[1][branch] = ({}, {}) # (leaves, children)
      cursor = cursor[1][branch]
    cursor[0][leaf] =  realval # add leaf
Esempio n. 11
0
        def handleInvalidParameters(e):
            if not getattr(handleInvalidParameters, 'alreadyLogged', False):
                log.warning(
                    'Received invalid parameters ({msg}): {func} ({args})'.
                    format(msg=str(e),
                           func=tokens.call.funcname,
                           args=', '.join(argList for argList in [
                               ', '.join(str(arg) for arg in args),
                               ', '.join('{k}={v}'.format(k=str(k), v=str(v))
                                         for k, v in kwargs.items()),
                           ] if argList)))

                # only log invalid parameters once
                setattr(handleInvalidParameters, 'alreadyLogged', True)

            if settings.ENFORCE_INPUT_VALIDATION:
                raise
Esempio n. 12
0
def loadFunctions(force=False):
    if _SeriesFunctions and not force:
        return

    from graphite.render import functions

    _SeriesFunctions.clear()
    _SeriesFunctions.update(functions.SeriesFunctions)

    _PieFunctions.clear()
    _PieFunctions.update(functions.PieFunctions)

    custom_modules = []
    for filename in listdir(customDir):
        module_name, extension = splitext(filename)
        if extension != '.py' or module_name == '__init__':
            continue
        custom_modules.append(customModPrefix + module_name)

    for module_name in custom_modules + settings.FUNCTION_PLUGINS:
        try:
            module = import_module(module_name)
        except Exception as e:
            log.warning('Error loading function plugin %s: %s' %
                        (module_name, e))
            continue

        for func_name, func in getattr(module, 'SeriesFunctions', {}).items():
            try:
                addFunction(_SeriesFunctions, func, func_name)
            except Exception as e:
                log.warning('Error loading function plugin %s: %s' %
                            (module_name, e))

        for func_name, func in getattr(module, 'PieFunctions', {}).items():
            try:
                addFunction(_PieFunctions, func, func_name)
            except Exception as e:
                log.warning('Error loading function plugin %s: %s' %
                            (module_name, e))
Esempio n. 13
0
    def fetch(self, path, reqkey, start_time, end_time):
        if path in self.result:
            return self.result[path]

        if reqkey is None:
            reqkey = str(uuid.uuid4())

        profilingTime = {'start': time.time()}

        try:
            query = {'start': start_time, 'end': end_time, 'reqKey': reqkey}
            data = {'metrics': ','.join(self.paths)}
            request_url = graphouse_url + "/metricData"
            request = requests.post(request_url, params=query, data=data)

            log.debug(
                'DEBUG:graphouse_data_query: {} parameters {}, data {}'.format(
                    request_url, query, data))

            request.raise_for_status()
        except (requests.exceptions.ConnectionError,
                requests.exceptions.Timeout) as e:
            log.warning(
                'CRITICAL:graphouse_data_query: Connection error: {}'.format(
                    str(e)))
            raise
        except requests.exceptions.HTTPError as e:
            log.warning(
                'CRITICAL:graphouse_data_query: {}, message: {}'.format(
                    str(e), request.text))
            raise
        except Exception:
            log.warning('Unexpected exception!', exc_info=True)
            raise

        profilingTime['fetch'] = time.time()

        try:
            metrics_object = request.json()
        except Exception:
            log.warning(
                'CRITICAL:graphouse_parse: '
                "can't parse json from graphouse answer, got '{}'".format(
                    request.text))
            raise

        profilingTime['parse'] = time.time()

        for node in self.nodes:
            metric_object = metrics_object.get(node.path)
            if metric_object is None:
                self.result[node.path] = ((start_time, end_time, 1), [])
            else:
                self.result[node.path] = (
                    (metric_object.get("start"), metric_object.get("end"),
                     metric_object.get("step")),
                    metric_object.get("points"),
                )

        profilingTime['convert'] = time.time()

        log.debug('DEBUG:graphouse_time:[{}] full = {} '
                  'fetch = {}, parse = {}, convert = {}'.format(
                      reqkey,
                      profilingTime['convert'] - profilingTime['start'],
                      profilingTime['fetch'] - profilingTime['start'],
                      profilingTime['parse'] - profilingTime['fetch'],
                      profilingTime['convert'] - profilingTime['parse']))

        result = self.result.get(path)
        if result is None:
            log.warning(
                'WARNING:graphouse_data: something strange: '
                "path {} doesn't exist in graphouse response".format(path))
            raise ValueError(
                "path {} doesn't exist in graphouse response".format(path))
        else:
            return result
Esempio n. 14
0
def evaluateTokens(requestContext, tokens, replacements=None, pipedArg=None):
    if tokens.template:
        arglist = dict()
        if tokens.template.kwargs:
            arglist.update(
                dict([(kwarg.argname, evaluateScalarTokens(kwarg.args[0]))
                      for kwarg in tokens.template.kwargs]))
        if tokens.template.args:
            arglist.update(
                dict([(str(i + 1), evaluateScalarTokens(arg))
                      for i, arg in enumerate(tokens.template.args)]))
        if 'template' in requestContext:
            arglist.update(requestContext['template'])
        return evaluateTokens(requestContext, tokens.template, arglist)

    if tokens.expression:
        if tokens.expression.pipedCalls:
            # when the expression has piped calls, we pop the right-most call and pass the remaining
            # expression into it via pipedArg, to get the same result as a nested call
            rightMost = tokens.expression.pipedCalls.pop()
            return evaluateTokens(requestContext, rightMost, replacements,
                                  tokens)

        return evaluateTokens(requestContext, tokens.expression, replacements)

    if tokens.pathExpression:
        expression = tokens.pathExpression
        if replacements:
            for name in replacements:
                if expression == '$' + name:
                    val = replacements[name]
                    if not isinstance(val, six.string_types):
                        return val
                    elif re.match(r'^-?[\d.]+$', val):
                        return float(val)
                    else:
                        return val
                else:
                    expression = expression.replace('$' + name,
                                                    str(replacements[name]))
        return fetchData(requestContext, expression)

    if tokens.call:
        if tokens.call.funcname == 'template':
            # if template propagates down here, it means the grammar didn't match the invocation
            # as tokens.template. this generally happens if you try to pass non-numeric/string args
            raise InputParameterError(
                "invalid template() syntax, only string/numeric arguments are allowed"
            )

        if tokens.call.funcname == 'seriesByTag':
            return fetchData(requestContext, tokens.call.raw)

        try:
            func = SeriesFunction(tokens.call.funcname)
        except KeyError:
            msg = 'Received request for unknown function: {func}'.format(
                func=tokens.call.funcname)
            log.warning(msg)

            # even if input validation enforcement is disabled, there's nothing else we can do here
            raise InputParameterError(msg)

        rawArgs = tokens.call.args or []
        if pipedArg is not None:
            rawArgs.insert(0, pipedArg)
        args = [
            evaluateTokens(requestContext, arg, replacements)
            for arg in rawArgs
        ]
        requestContext['args'] = rawArgs
        kwargs = dict([(kwarg.argname,
                        evaluateTokens(requestContext, kwarg.args[0],
                                       replacements))
                       for kwarg in tokens.call.kwargs])

        def handleInvalidParameters(e):
            if not getattr(handleInvalidParameters, 'alreadyLogged', False):
                log.warning(
                    'Received invalid parameters ({msg}): {func} ({args})'.
                    format(msg=str(e),
                           func=tokens.call.funcname,
                           args=', '.join(argList for argList in [
                               ', '.join(str(arg) for arg in args),
                               ', '.join('{k}={v}'.format(k=str(k), v=str(v))
                                         for k, v in kwargs.items()),
                           ] if argList)))

                # only log invalid parameters once
                setattr(handleInvalidParameters, 'alreadyLogged', True)

            if settings.ENFORCE_INPUT_VALIDATION:
                raise

        if hasattr(func, 'params'):
            try:
                validateParams(tokens.call.funcname, func.params, args, kwargs)
            except InputParameterError as e:
                handleInvalidParameters(e)

        try:
            return func(requestContext, *args, **kwargs)
        except NormalizeEmptyResultError:
            return []
        except InputParameterError as e:
            handleInvalidParameters(e)

    return evaluateScalarTokens(tokens)
Esempio n. 15
0
def evaluateTokens(requestContext, tokens, replacements=None, pipedArg=None):
    if tokens.template:
        arglist = dict()
        if tokens.template.kwargs:
            arglist.update(
                dict([(kwarg.argname, evaluateScalarTokens(kwarg.args[0]))
                      for kwarg in tokens.template.kwargs]))
        if tokens.template.args:
            arglist.update(
                dict([(str(i + 1), evaluateScalarTokens(arg))
                      for i, arg in enumerate(tokens.template.args)]))
        if 'template' in requestContext:
            arglist.update(requestContext['template'])
        return evaluateTokens(requestContext, tokens.template, arglist)

    if tokens.expression:
        if tokens.expression.pipedCalls.asList():
            # when the expression has piped calls, we pop the right-most call and pass the remaining
            # expression into it via pipedArg, to get the same result as a nested call
            rightMost = tokens.expression.pipedCalls.pop()
            return evaluateTokens(requestContext, rightMost, replacements,
                                  tokens)

        return evaluateTokens(requestContext, tokens.expression, replacements)

    if tokens.pathExpression:
        expression = tokens.pathExpression
        if replacements:
            for name in replacements:
                if expression == '$' + name:
                    val = replacements[name]
                    if not isinstance(val, six.string_types):
                        return val
                    elif re.match(r'^-?[\d.]+$', val):
                        return float(val)
                    else:
                        return val
                else:
                    expression = expression.replace('$' + name,
                                                    str(replacements[name]))
        return fetchData(requestContext, expression)

    if tokens.call:
        if tokens.call.funcname == 'template':
            # if template propagates down here, it means the grammar didn't match the invocation
            # as tokens.template. this generally happens if you try to pass non-numeric/string args
            raise InputParameterError(
                "invalid template() syntax, only string/numeric arguments are allowed"
            )

        if tokens.call.funcname == 'seriesByTag':
            return fetchData(requestContext, tokens.call.raw)

        try:
            func = SeriesFunction(tokens.call.funcname)
        except KeyError:
            raise InputParameterError(
                'Received request for unknown function: {func}'.format(
                    func=tokens.call.funcname))

        rawArgs = tokens.call.args or []
        if pipedArg is not None:
            rawArgs.insert(0, pipedArg)
        args = [
            evaluateTokens(requestContext, arg, replacements)
            for arg in rawArgs
        ]
        requestContext['args'] = rawArgs
        kwargs = dict([(kwarg.argname,
                        evaluateTokens(requestContext, kwarg.args[0],
                                       replacements))
                       for kwarg in tokens.call.kwargs])

        if hasattr(func, 'params'):
            try:
                (args, kwargs) = validateParams(tokens.call.funcname,
                                                func.params, args, kwargs)
            except InputParameterError as e:
                e.setSourceIdHeaders(requestContext.get('sourceIdHeaders', {}))
                e.setTargets(requestContext.get('targets', []))
                e.setFunction(tokens.call.funcname, args, kwargs)
                if settings.ENFORCE_INPUT_VALIDATION:
                    raise
                else:
                    log.warning('Validation Error: %s', str(e))

        try:
            return func(requestContext, *args, **kwargs)
        except NormalizeEmptyResultError:
            return []
        except InputParameterError as e:
            e.setSourceIdHeaders(requestContext.get('sourceIdHeaders', {}))
            e.setTargets(requestContext.get('targets', []))
            e.setFunction(tokens.call.funcname, args, kwargs)
            raise

    return evaluateScalarTokens(tokens)