Beispiel #1
0
def fetch(request):
    if request.GET.get('from') is not None:
        time_from = parseATTime(request.GET['from'])
    else:
        time_from = epoch_to_dt(0)

    if request.GET.get('until') is not None:
        time_until = parseATTime(request.GET['until'])
    else:
        time_until = now()

    set_operation = request.GET.get('set')

    tags = request.GET.get('tags')
    if tags is not None:
        tags = request.GET.get('tags').split(' ')

    result = []
    for x in Event.find_events(time_from, time_until, tags=tags, set_operation=set_operation):

        # django-tagging's with_intersection() returns matches with unknown tags
        # this is a workaround to ensure we only return positive matches
        if set_operation == 'intersection':
            if len(set(tags) & set(x.as_dict()['tags'])) == len(tags):
                result.append(x.as_dict())
        else:
            result.append(x.as_dict())
    return result
Beispiel #2
0
def fetch(request):
    #XXX we need to move to USE_TZ=True to get rid of naive-time conversions
    def make_naive(dt):
      tz = timezone(request.GET.get('tz', settings.TIME_ZONE))
      local_dt = dt.astimezone(tz)
      if hasattr(local_dt, 'normalize'):
        local_dt = local_dt.normalize()
      return local_dt.replace(tzinfo=None)

    if request.GET.get("from", None) is not None:
        time_from = make_naive(parseATTime(request.GET["from"]))
    else:
        time_from = datetime.datetime.fromtimestamp(0)

    if request.GET.get("until", None) is not None:
        time_until = make_naive(parseATTime(request.GET["until"]))
    else:
        time_until = datetime.datetime.now()

    tags = request.GET.get("tags", None)
    if tags is not None:
        tags = request.GET.get("tags").split(" ")

    return [x.as_dict() for x in
            models.Event.find_events(time_from, time_until, tags=tags)]
Beispiel #3
0
def _get_latest_graphite(metric):
    """
    Get the latest value of a named graphite metric
    """

    tzinfo = pytz.timezone("UTC")
    until_time = parseATTime('now', tzinfo)

    def _get(from_time):
        series = fetchData({
            'startTime': from_time,
            'endTime': until_time,
            'now': until_time,
            'localOnly': False},
            metric
        )
        try:
            return [k for k in series[0] if k is not None][-1]
        except IndexError:
            return None

    # In case the cluster has been offline for some time, try looking progressively
    # further back in time for data.  This would not be necessary if graphite simply
    # let us ask for the latest value (Calamari issue #6876)
    for trange in ['-1min', '-10min', '-60min', '-1d', '-7d']:
        val = _get(parseATTime(trange, tzinfo))
        if val is not None:
            return val

    log.warn("No graphite data for %s" % metric)
Beispiel #4
0
def parseOptions(request):
  queryParams = request.REQUEST

  # Start with some defaults
  graphOptions = {'width' : 330, 'height' : 250}
  requestOptions = {}

  graphType = queryParams.get('graphType','line')
  assert graphType in GraphTypes, "Invalid graphType '%s', must be one of %s" % (graphType,GraphTypes.keys())
  graphClass = GraphTypes[graphType]

  # Fill in the requestOptions
  requestOptions['graphType'] = graphType
  requestOptions['graphClass'] = graphClass
  requestOptions['targets'] = []
  for target in queryParams.getlist('target'):
    if target.lower().startswith('graphite.'): #Strip leading "Graphite." as a convenience
      target = target[9:]
    requestOptions['targets'].append(target)

  if 'pickle' in queryParams:
    requestOptions['pickle'] = True
  if 'rawData' in queryParams:
    requestOptions['rawData'] = True
  if 'noCache' in queryParams:
    requestOptions['noCache'] = True

  # Fill in the graphOptions
  for opt in graphClass.customizable:
    if opt in queryParams:
      val = queryParams[opt]
      if (val.isdigit() or (val.startswith('-') and val[1:].isdigit())) and opt not in ('fgcolor','bgcolor','fontColor'):
        val = int(val)
      elif '.' in val and (val.replace('.','',1).isdigit() or (val.startswith('-') and val[1:].replace('.','',1).isdigit())):
        val = float(val)
      elif val.lower() in ('true','false'):
        val = eval( val.lower().capitalize() )
      elif val.lower() == 'default' or val == '':
        continue
      graphOptions[opt] = val

  # Get the time interval for time-oriented graph types
  if graphType == 'line':
    if 'until' in queryParams:
      endTime = parseATTime( queryParams['until'] )
    else:
      endTime = datetime.now()
    if 'from' in queryParams:
      startTime = parseATTime( queryParams['from'] )
    else:
      startTime = endTime - timedelta(days=1)
    if endTime > datetime.now():
      endTime = datetime.now()
    assert startTime < endTime, "Invalid time range!"
    
    requestOptions['startTime'] = startTime
    requestOptions['endTime'] = endTime

  return (graphOptions, requestOptions)
Beispiel #5
0
def fetch(request):
    if request.GET.get("from", None) is not None:
        time_from = parseATTime(request.GET["from"])
    else:
        time_from = datetime.datetime.fromtimestamp(0)

    if request.GET.get("until", None) is not None:
        time_until = parseATTime(request.GET["until"])
    else:
        time_until = datetime.datetime.now()

    tags = request.GET.get("tags", None)
    if tags is not None:
        tags = request.GET.get("tags").split(" ")

    return [x.as_dict() for x in
            models.Event.find_events(time_from, time_until, tags=tags)]
Beispiel #6
0
def fetch(request):
    #XXX we need to move to USE_TZ=True to get rid of localtime() conversions
    if request.GET.get("from", None) is not None:
        time_from = localtime(parseATTime(request.GET["from"])).replace(tzinfo=None)
    else:
        time_from = datetime.datetime.fromtimestamp(0)

    if request.GET.get("until", None) is not None:
        time_until = localtime(parseATTime(request.GET["until"])).replace(tzinfo=None)
    else:
        time_until = now()

    tags = request.GET.get("tags", None)
    if tags is not None:
        tags = request.GET.get("tags").split(" ")

    return [x.as_dict() for x in
            models.Event.find_events(time_from, time_until, tags=tags)]
def evaluateTokens(tokens, timeInterval, originalTime = None):
  if tokens.expression:
    if tokens[0][0][0] == "timeShift":
      delta = timeInterval[0] - parseATTime(tokens[0][0][1][1]['string'].strip('"'))
      delta += timeInterval[1] - timeInterval[0]
      originalTime = timeInterval
      timeInterval = (timeInterval[0] - delta, timeInterval[1] - delta)
    return evaluateTokens(tokens.expression, timeInterval, originalTime)

  elif tokens.pathExpression:
    pathExpr = tokens.pathExpression
    if pathExpr.lower().startswith('graphite.'):
      pathExpr = pathExpr[9:]

    seriesList = []
    (startTime,endTime) = originalTime or timeInterval

    for dbFile in settings.STORE.find(pathExpr):
      log.metric_access(dbFile.metric_path)
      getCacheResults = CarbonLink.sendRequest(dbFile.real_metric)
      dbResults = dbFile.fetch( timestamp(startTime), timestamp(endTime) )
      results = mergeResults(dbResults, getCacheResults())

      if not results:
        continue

      (timeInfo,values) = results
      (start,end,step) = timeInfo
      series = TimeSeries(dbFile.metric_path, start, end, step, values)
      series.pathExpression = pathExpr #hack to pass expressions through to render functions
      series.start = time.mktime(startTime.timetuple())
      series.end = time.mktime(endTime.timetuple())
      seriesList.append(series)

    return seriesList

  elif tokens.call:
    func = SeriesFunctions[tokens.call.func]
    args = [evaluateTokens(arg, timeInterval, originalTime) for arg in tokens.call.args]
    return func(*args)

  elif tokens.number:
    if tokens.number.integer:
      return int(tokens.number.integer)

    elif tokens.number.float:
      return float(tokens.number.float)

  elif tokens.string:
    return str(tokens.string)[1:-1]
Beispiel #8
0
 def test_should_return_current_time(self):
     expected_time = self.default_tz.localize(datetime.strptime("12:00_20150308", '%H:%M_%Y%m%d'))
     actual_time = parseATTime("now")
     self.assertEqual(actual_time, expected_time)
Beispiel #9
0
 def test_offset_with_tz(self):
     expected_time = self.specified_tz.localize(datetime.strptime("1:00_20150308", '%H:%M_%Y%m%d'))
     actual_time = parseATTime("midnight+1h", self.specified_tz)
     self.assertEqual(actual_time, expected_time)
Beispiel #10
0
 def test_parse_zone_aware_datetime(self):
     time_ref = parseATTime(self.specified_tz.localize(datetime(self.MOCK_DATE.year, self.MOCK_DATE.month, self.MOCK_DATE.day, 8, 50)), self.specified_tz, now=self.now)
     expected = self.specified_tz.localize(datetime(self.MOCK_DATE.year, self.MOCK_DATE.month, self.MOCK_DATE.day, 8, 50))
     self.assertEquals(time_ref, expected)
Beispiel #11
0
def parseOptions(request):
  queryParams = request.REQUEST

  # Start with some defaults
  graphOptions = {'width' : 330, 'height' : 250}
  requestOptions = {}

  graphType = queryParams.get('graphType','line')
  assert graphType in GraphTypes, "Invalid graphType '%s', must be one of %s" % (graphType,GraphTypes.keys())
  graphClass = GraphTypes[graphType]

  # Fill in the requestOptions
  requestOptions['graphType'] = graphType
  requestOptions['graphClass'] = graphClass
  requestOptions['pieMode'] = queryParams.get('pieMode', 'average')
  requestOptions['cacheTimeout'] = int( queryParams.get('cacheTimeout', settings.DEFAULT_CACHE_DURATION) )
  requestOptions['targets'] = []
  for target in queryParams.getlist('target'):
    requestOptions['targets'].append(target)

  if 'pickle' in queryParams:
    requestOptions['pickle'] = True
  if 'rawData' in queryParams:
    requestOptions['format'] = 'raw'
  if 'format' in queryParams:
    requestOptions['format'] = queryParams['format']
    if 'jsonp' in queryParams:
      requestOptions['jsonp'] = queryParams['jsonp']
  if 'noCache' in queryParams:
    requestOptions['noCache'] = True

  requestOptions['localOnly'] = queryParams.get('local') == '1'

  # Fill in the graphOptions
  for opt in graphClass.customizable:
    if opt in queryParams:
      val = queryParams[opt]
      if (val.isdigit() or (val.startswith('-') and val[1:].isdigit())) and opt not in ('fgcolor','bgcolor','fontColor'):
        val = int(val)
      elif '.' in val and (val.replace('.','',1).isdigit() or (val.startswith('-') and val[1:].replace('.','',1).isdigit())):
        val = float(val)
      elif val.lower() in ('true','false'):
        val = val.lower() == 'true'
      elif val.lower() == 'default' or val == '':
        continue
      graphOptions[opt] = val

  # Get the time interval for time-oriented graph types
  if graphType == 'line' or graphType == 'pie':
    if 'until' in queryParams:
      untilTime = parseATTime( queryParams['until'] )
    else:
      untilTime = parseATTime('now')
    if 'from' in queryParams:
      fromTime = parseATTime( queryParams['from'] )
    else:
      fromTime = parseATTime('-1d')

    startTime = min(fromTime, untilTime)
    endTime = max(fromTime, untilTime)
    assert startTime != endTime, "Invalid empty time range"
    
    requestOptions['startTime'] = startTime
    requestOptions['endTime'] = endTime

  return (graphOptions, requestOptions)
Beispiel #12
0
def parseOptions(request):
    queryParams = request.REQUEST

    # Start with some defaults
    graphOptions = {'width': 330, 'height': 250}
    requestOptions = {}

    graphType = queryParams.get('graphType', 'line')
    assert graphType in GraphTypes, "Invalid graphType '%s', must be one of %s" % (
        graphType, GraphTypes.keys())
    graphClass = GraphTypes[graphType]

    # Fill in the requestOptions
    requestOptions['graphType'] = graphType
    requestOptions['graphClass'] = graphClass
    requestOptions['pieMode'] = queryParams.get('pieMode', 'average')
    requestOptions['cacheTimeout'] = int(
        queryParams.get('cacheTimeout', settings.DEFAULT_CACHE_DURATION))
    requestOptions['targets'] = []

    # Extract the targets out of the queryParams
    mytargets = []
    # Normal format: ?target=path.1&target=path.2
    if len(queryParams.getlist('target')) > 0:
        mytargets = queryParams.getlist('target')

    # Rails/PHP/jQuery common practice format: ?target[]=path.1&target[]=path.2
    elif len(queryParams.getlist('target[]')) > 0:
        mytargets = queryParams.getlist('target[]')

    # Collect the targets
    for target in mytargets:
        requestOptions['targets'].append(target)

    if 'pickle' in queryParams:
        requestOptions['format'] = 'pickle'
    if 'rawData' in queryParams:
        requestOptions['format'] = 'raw'
    if 'format' in queryParams:
        requestOptions['format'] = queryParams['format']
        if 'jsonp' in queryParams:
            requestOptions['jsonp'] = queryParams['jsonp']
    if 'noCache' in queryParams:
        requestOptions['noCache'] = True
    if 'maxDataPoints' in queryParams and queryParams['maxDataPoints'].isdigit(
    ):
        requestOptions['maxDataPoints'] = int(queryParams['maxDataPoints'])

    requestOptions['localOnly'] = queryParams.get('local') == '1'

    # Fill in the graphOptions
    for opt in graphClass.customizable:
        if opt in queryParams:
            val = queryParams[opt]
            if (val.isdigit() or
                (val.startswith('-')
                 and val[1:].isdigit())) and 'color' not in opt.lower():
                val = int(val)
            elif '.' in val and (val.replace('.', '', 1).isdigit() or
                                 (val.startswith('-')
                                  and val[1:].replace('.', '', 1).isdigit())):
                val = float(val)
            elif val.lower() in ('true', 'false'):
                val = val.lower() == 'true'
            elif val.lower() == 'default' or val == '':
                continue
            graphOptions[opt] = val

    tzinfo = pytz.timezone(settings.TIME_ZONE)
    if 'tz' in queryParams:
        try:
            tzinfo = pytz.timezone(queryParams['tz'])
        except pytz.UnknownTimeZoneError:
            pass
    requestOptions['tzinfo'] = tzinfo

    # Get the time interval for time-oriented graph types
    if graphType == 'line' or graphType == 'pie':
        if 'until' in queryParams:
            untilTime = parseATTime(queryParams['until'], tzinfo)
        else:
            untilTime = parseATTime('now', tzinfo)
        if 'from' in queryParams:
            fromTime = parseATTime(queryParams['from'], tzinfo)
        else:
            fromTime = parseATTime('-1d', tzinfo)

        startTime = min(fromTime, untilTime)
        endTime = max(fromTime, untilTime)
        assert startTime != endTime, "Invalid empty time range"

        requestOptions['startTime'] = startTime
        requestOptions['endTime'] = endTime

    return (graphOptions, requestOptions)
Beispiel #13
0
 def test_relative_time_in_alternate_zone(self):
     expected_time = self.specified_tz.localize(
         datetime.strptime("11:00_20150308", '%H:%M_%Y%m%d'))
     actual_time = parseATTime("-1h", self.specified_tz)
     self.assertEqual(actual_time.hour, expected_time.hour)
Beispiel #14
0
def parseOptions(request):
  queryParams = request.REQUEST

  # Start with some defaults
  graphOptions = {'width' : 330, 'height' : 250}
  requestOptions = {}

  graphType = queryParams.get('graphType','line')
  assert graphType in GraphTypes, "Invalid graphType '%s', must be one of %s" % (graphType,GraphTypes.keys())
  graphClass = GraphTypes[graphType]

  # Fill in the requestOptions
  requestOptions['graphType'] = graphType
  requestOptions['graphClass'] = graphClass
  requestOptions['pieMode'] = queryParams.get('pieMode', 'average')
  requestOptions['cacheTimeout'] = int( queryParams.get('cacheTimeout', settings.DEFAULT_CACHE_DURATION) )
  requestOptions['targets'] = []

  # Extract the targets out of the queryParams
  mytargets = []
  # Normal format: ?target=path.1&target=path.2
  if len(queryParams.getlist('target')) > 0:
    mytargets = queryParams.getlist('target')

  # Rails/PHP/jQuery common practice format: ?target[]=path.1&target[]=path.2
  elif len(queryParams.getlist('target[]')) > 0:
    mytargets = queryParams.getlist('target[]')

  # Collect the targets
  for target in mytargets:
    requestOptions['targets'].append(target)

  template = dict()
  for key, val in queryParams.items():
    if key.startswith("template["):
      template[key[9:-1]] = val
  requestOptions['template'] = template

  if 'pickle' in queryParams:
    requestOptions['format'] = 'pickle'
  if 'rawData' in queryParams:
    requestOptions['format'] = 'raw'
  if 'format' in queryParams:
    requestOptions['format'] = queryParams['format']
    if 'jsonp' in queryParams:
      requestOptions['jsonp'] = queryParams['jsonp']
  if 'noCache' in queryParams:
    requestOptions['noCache'] = True
  if 'maxDataPoints' in queryParams and queryParams['maxDataPoints'].isdigit():
    requestOptions['maxDataPoints'] = int(queryParams['maxDataPoints'])

  requestOptions['localOnly'] = queryParams.get('local') == '1'

  # Fill in the graphOptions
  for opt in graphClass.customizable:
    if opt in queryParams:
      val = queryParams[opt]
      if (val.isdigit() or (val.startswith('-') and val[1:].isdigit())) and 'color' not in opt.lower():
        val = int(val)
      elif '.' in val and (val.replace('.','',1).isdigit() or (val.startswith('-') and val[1:].replace('.','',1).isdigit())):
        val = float(val)
      elif val.lower() in ('true','false'):
        val = val.lower() == 'true'
      elif val.lower() == 'default' or val == '':
        continue
      graphOptions[opt] = val

  tzinfo = pytz.timezone(settings.TIME_ZONE)
  if 'tz' in queryParams:
    try:
      tzinfo = pytz.timezone(queryParams['tz'])
    except pytz.UnknownTimeZoneError:
      pass
  requestOptions['tzinfo'] = tzinfo

  # Get the time interval for time-oriented graph types
  if graphType == 'line' or graphType == 'pie':
    if 'until' in queryParams:
      untilTime = parseATTime(queryParams['until'], tzinfo)
    else:
      untilTime = parseATTime('now', tzinfo)
    if 'from' in queryParams:
      fromTime = parseATTime(queryParams['from'], tzinfo)
    else:
      fromTime = parseATTime('-1d', tzinfo)

    startTime = min(fromTime, untilTime)
    endTime = max(fromTime, untilTime)
    assert startTime != endTime, "Invalid empty time range"

    requestOptions['startTime'] = startTime
    requestOptions['endTime'] = endTime
    timeRange = endTime - startTime
    queryTime = timeRange.days * 86400 + timeRange.seconds # convert the time delta to seconds
    if settings.DEFAULT_CACHE_POLICY and not queryParams.get('cacheTimeout'):
      requestOptions['cacheTimeout'] = max(timeout for period,timeout in settings.DEFAULT_CACHE_POLICY if period <= queryTime)

  return (graphOptions, requestOptions)
Beispiel #15
0
 def test_should_return_absolute_time_short(self):
     time_string = '9:0020150308'
     expected_time = self.default_tz.localize(
         datetime.strptime(time_string, '%H:%M%Y%m%d'))
     actual_time = parseATTime(time_string, now=self.now)
     self.assertEqual(actual_time, expected_time)
Beispiel #16
0
 def test_midnight(self):
     expected_time = self.default_tz.localize(datetime.strptime("0:00_20150308", '%H:%M_%Y%m%d'))
     actual_time = parseATTime("midnight", self.specified_tz)
     self.assertEqual(actual_time, expected_time.astimezone(self.specified_tz))
Beispiel #17
0
def find_view(request):
    "View for finding metrics matching a given pattern"

    queryParams = request.GET.copy()
    queryParams.update(request.POST)

    format = queryParams.get('format', 'treejson')
    local_only = int(queryParams.get('local', 0))
    wildcards = int(queryParams.get('wildcards', 0))

    tzinfo = pytz.timezone(settings.TIME_ZONE)
    if 'tz' in queryParams:
        try:
            tzinfo = pytz.timezone(queryParams['tz'])
        except pytz.UnknownTimeZoneError:
            pass

    if 'now' in queryParams:
        now = parseATTime(queryParams['now'], tzinfo)
    else:
        now = datetime.now(tzinfo)

    if 'from' in queryParams and str(queryParams['from']) != '-1':
        fromTime = int(epoch(parseATTime(queryParams['from'], tzinfo, now)))
    else:
        fromTime = -1

    if 'until' in queryParams and str(queryParams['from']) != '-1':
        untilTime = int(epoch(parseATTime(queryParams['until'], tzinfo, now)))
    else:
        untilTime = -1

    nodePosition = int(queryParams.get('position', -1))
    jsonp = queryParams.get('jsonp', False)
    forward_headers = extractForwardHeaders(request)

    if fromTime == -1:
        fromTime = None
    if untilTime == -1:
        untilTime = None

    automatic_variants = int(queryParams.get('automatic_variants', 0))

    try:
        query = str(queryParams['query'])
    except:
        return HttpResponseBadRequest(
            content="Missing required parameter 'query'",
            content_type='text/plain')

    if '.' in query:
        base_path = query.rsplit('.', 1)[0] + '.'
    else:
        base_path = ''

    if format == 'completer':
        query = query.replace('..', '*.')
        if not query.endswith('*'):
            query += '*'

        if automatic_variants:
            query_parts = query.split('.')
            for i, part in enumerate(query_parts):
                if ',' in part and '{' not in part:
                    query_parts[i] = '{%s}' % part
            query = '.'.join(query_parts)

    try:
        matches = list(
            STORE.find(query,
                       fromTime,
                       untilTime,
                       local=local_only,
                       headers=forward_headers))
    except:
        log.exception()
        raise

    log.info('find_view query=%s local_only=%s matches=%d' %
             (query, local_only, len(matches)))
    matches.sort(key=lambda node: node.name)
    log.info(
        "received remote find request: pattern=%s from=%s until=%s local_only=%s format=%s matches=%d"
        % (query, fromTime, untilTime, local_only, format, len(matches)))

    if format == 'treejson':
        profile = getProfile(request)
        content = tree_json(matches,
                            base_path,
                            wildcards=profile.advancedUI or wildcards)
        response = json_response_for(request, content, jsonp=jsonp)

    elif format == 'nodelist':
        content = nodes_by_position(matches, nodePosition)
        response = json_response_for(request, content, jsonp=jsonp)

    elif format == 'pickle':
        content = pickle_nodes(matches)
        response = HttpResponse(content, content_type='application/pickle')

    elif format == 'msgpack':
        content = msgpack_nodes(matches)
        response = HttpResponse(content, content_type='application/x-msgpack')

    elif format == 'json':
        content = json_nodes(matches)
        response = json_response_for(request, content, jsonp=jsonp)

    elif format == 'completer':
        results = []
        for node in matches:
            node_info = dict(path=node.path,
                             name=node.name,
                             is_leaf=str(int(node.is_leaf)))
            if not node.is_leaf:
                node_info['path'] += '.'
            results.append(node_info)

        if len(results) > 1 and wildcards:
            wildcardNode = {'name': '*'}
            results.append(wildcardNode)

        response = json_response_for(request, {'metrics': results},
                                     jsonp=jsonp)

    else:
        return HttpResponseBadRequest(
            content="Invalid value for 'format' parameter",
            content_type='text/plain')

    response['Pragma'] = 'no-cache'
    response['Cache-Control'] = 'no-cache'
    return response
Beispiel #18
0
def find_view(request):
  "View for finding metrics matching a given pattern"

  queryParams = request.GET.copy()
  queryParams.update(request.POST)

  format = queryParams.get('format', 'treejson')
  leaves_only = int( queryParams.get('leavesOnly', 0) )
  local_only = int( queryParams.get('local', 0) )
  wildcards = int( queryParams.get('wildcards', 0) )

  tzinfo = pytz.timezone(settings.TIME_ZONE)
  if 'tz' in queryParams:
    try:
      tzinfo = pytz.timezone(queryParams['tz'])
    except pytz.UnknownTimeZoneError:
      pass

  if 'now' in queryParams:
    now = parseATTime(queryParams['now'], tzinfo)
  else:
    now = datetime.now(tzinfo)

  if 'from' in queryParams and str(queryParams['from']) != '-1':
    fromTime = int(epoch(parseATTime(queryParams['from'], tzinfo, now)))
  else:
    fromTime = -1

  if 'until' in queryParams and str(queryParams['from']) != '-1':
    untilTime = int(epoch(parseATTime(queryParams['until'], tzinfo, now)))
  else:
    untilTime = -1

  nodePosition = int( queryParams.get('position', -1) )
  jsonp = queryParams.get('jsonp', False)
  forward_headers = extractForwardHeaders(request)

  if fromTime == -1:
    fromTime = None
  if untilTime == -1:
    untilTime = None

  automatic_variants = int( queryParams.get('automatic_variants', 0) )

  try:
    query = str(queryParams['query'])
  except KeyError:
    return HttpResponseBadRequest(content="Missing required parameter 'query'",
                                  content_type='text/plain')

  if query == '':
    return HttpResponseBadRequest(content="Required parameter 'query' is empty",
                                  content_type='text/plain')

  if '.' in query:
    base_path = query.rsplit('.', 1)[0] + '.'
  else:
    base_path = ''

  if format == 'completer':
    query = query.replace('..', '*.')
    if not query.endswith('*'):
      query += '*'

    if automatic_variants:
      query_parts = query.split('.')
      for i,part in enumerate(query_parts):
        if ',' in part and '{' not in part:
          query_parts[i] = '{%s}' % part
      query = '.'.join(query_parts)

  try:
    matches = list(STORE.find(
      query, fromTime, untilTime,
      local=local_only,
      headers=forward_headers,
      leaves_only=leaves_only,
    ))
  except Exception:
    log.exception()
    raise

  log.info('find_view query=%s local_only=%s matches=%d' % (query, local_only, len(matches)))
  matches.sort(key=lambda node: node.name)
  log.info("received remote find request: pattern=%s from=%s until=%s local_only=%s format=%s matches=%d" % (query, fromTime, untilTime, local_only, format, len(matches)))

  if format == 'treejson':
    profile = getProfile(request)
    content = tree_json(matches, base_path, wildcards=profile.advancedUI or wildcards)
    response = json_response_for(request, content, jsonp=jsonp)

  elif format == 'nodelist':
    content = nodes_by_position(matches, nodePosition)
    response = json_response_for(request, content, jsonp=jsonp)

  elif format == 'pickle':
    content = pickle_nodes(matches)
    response = HttpResponse(content, content_type='application/pickle')

  elif format == 'msgpack':
    content = msgpack_nodes(matches)
    response = HttpResponse(content, content_type='application/x-msgpack')

  elif format == 'json':
    content = json_nodes(matches)
    response = json_response_for(request, content, jsonp=jsonp)

  elif format == 'completer':
    results = []
    for node in matches:
      node_info = dict(path=node.path, name=node.name, is_leaf=str(int(node.is_leaf)))
      if not node.is_leaf:
        node_info['path'] += '.'
      results.append(node_info)

    if len(results) > 1 and wildcards:
      wildcardNode = {'name' : '*'}
      results.append(wildcardNode)

    response = json_response_for(request, { 'metrics' : results }, jsonp=jsonp)

  else:
    return HttpResponseBadRequest(
        content="Invalid value for 'format' parameter",
        content_type='text/plain')

  response['Pragma'] = 'no-cache'
  response['Cache-Control'] = 'no-cache'
  return response
Beispiel #19
0
def parseOptions(request):
    queryParams = request.GET.copy()
    queryParams.update(request.POST)

    # Start with some defaults
    graphOptions = {'width': 330, 'height': 250}
    requestOptions = {}

    graphType = queryParams.get('graphType', 'line')
    if graphType not in GraphTypes:
        raise AssertionError("Invalid graphType '%s', must be one of %s" %
                             (graphType, list(GraphTypes)))
    graphClass = GraphTypes[graphType]

    # Fill in the requestOptions
    requestOptions['graphType'] = graphType
    requestOptions['graphClass'] = graphClass
    requestOptions['pieMode'] = queryParams.get('pieMode', 'average')
    cacheTimeout = int(
        queryParams.get('cacheTimeout', settings.DEFAULT_CACHE_DURATION))
    requestOptions['targets'] = []
    requestOptions['forwardHeaders'] = extractForwardHeaders(request)

    # Extract the targets out of the queryParams
    mytargets = []
    # Normal format: ?target=path.1&target=path.2
    if len(queryParams.getlist('target')) > 0:
        mytargets = queryParams.getlist('target')

    # Rails/PHP/jQuery common practice format: ?target[]=path.1&target[]=path.2
    elif len(queryParams.getlist('target[]')) > 0:
        mytargets = queryParams.getlist('target[]')

    # Collect the targets
    for target in mytargets:
        requestOptions['targets'].append(target)

    template = dict()
    for key, val in queryParams.items():
        if key.startswith("template["):
            template[key[9:-1]] = val
    requestOptions['template'] = template

    if 'pickle' in queryParams:
        requestOptions['format'] = 'pickle'
    if 'rawData' in queryParams:
        requestOptions['format'] = 'raw'
    if 'format' in queryParams:
        requestOptions['format'] = queryParams['format']
        if 'jsonp' in queryParams:
            requestOptions['jsonp'] = queryParams['jsonp']

    requestOptions['pretty'] = bool(queryParams.get('pretty'))

    if 'noCache' in queryParams:
        requestOptions['noCache'] = True
    if 'maxDataPoints' in queryParams and queryParams['maxDataPoints'].isdigit(
    ):
        requestOptions['maxDataPoints'] = int(queryParams['maxDataPoints'])
    if 'noNullPoints' in queryParams:
        requestOptions['noNullPoints'] = True

    requestOptions['localOnly'] = queryParams.get('local') == '1'

    # Fill in the graphOptions
    format = requestOptions.get('format')
    if format == 'svg':
        graphOptions['outputFormat'] = 'svg'
    elif format == 'pdf':
        graphOptions['outputFormat'] = 'pdf'
    else:
        graphOptions['outputFormat'] = 'png'

    for opt in graphClass.customizable:
        if opt in queryParams:
            val = queryParams[opt]
            if (val.isdigit() or
                (val.startswith('-')
                 and val[1:].isdigit())) and 'color' not in opt.lower():
                val = int(val)
            elif '.' in val and (val.replace('.', '', 1).isdigit() or
                                 (val.startswith('-')
                                  and val[1:].replace('.', '', 1).isdigit())):
                val = float(val)
            elif val.lower() in ('true', 'false'):
                val = val.lower() == 'true'
            elif val.lower() == 'default' or val == '':
                continue
            graphOptions[opt] = val

    tzinfo = pytz.timezone(settings.TIME_ZONE)
    if 'tz' in queryParams:
        try:
            tzinfo = pytz.timezone(queryParams['tz'])
        except pytz.UnknownTimeZoneError:
            pass
    requestOptions['tzinfo'] = tzinfo

    # Get the time interval for time-oriented graph types
    if graphType == 'line' or graphType == 'pie':
        if 'now' in queryParams:
            now = parseATTime(queryParams['now'], tzinfo)
        else:
            now = datetime.now(tzinfo)

        if 'until' in queryParams:
            untilTime = parseATTime(queryParams['until'], tzinfo, now)
        else:
            untilTime = now
        if 'from' in queryParams:
            fromTime = parseATTime(queryParams['from'], tzinfo, now)
        else:
            fromTime = parseATTime('-1d', tzinfo, now)

        startTime = min(fromTime, untilTime)
        endTime = max(fromTime, untilTime)
        assert startTime != endTime, "Invalid empty time range"

        requestOptions['startTime'] = startTime
        requestOptions['endTime'] = endTime
        timeRange = endTime - startTime
        queryTime = timeRange.days * 86400 + timeRange.seconds  # convert the time delta to seconds
        if settings.DEFAULT_CACHE_POLICY and not queryParams.get(
                'cacheTimeout'):
            timeouts = [
                timeout for period, timeout in settings.DEFAULT_CACHE_POLICY
                if period <= queryTime
            ]
            cacheTimeout = max(timeouts or (0, ))
        requestOptions['now'] = now

    if cacheTimeout == 0:
        requestOptions['noCache'] = True
    requestOptions['cacheTimeout'] = cacheTimeout

    requestOptions['xFilesFactor'] = float(
        queryParams.get('xFilesFactor', settings.DEFAULT_XFILES_FACTOR))

    return (graphOptions, requestOptions)
Beispiel #20
0
def parseOptions(request):
  queryParams = request.REQUEST

  # Start with some defaults
  graphOptions = {'width' : 330, 'height' : 250}
  requestOptions = {}

  graphType = queryParams.get('graphType','line')
  assert graphType in GraphTypes, "Invalid graphType '%s', must be one of %s" % (graphType,GraphTypes.keys())
  graphClass = GraphTypes[graphType]

  # Fill in the requestOptions
  requestOptions['graphType'] = graphType
  requestOptions['graphClass'] = graphClass
  requestOptions['pieMode'] = queryParams.get('pieMode', 'average')
  requestOptions['cacheTimeout'] = int( queryParams.get('cacheTimeout', settings.DEFAULT_CACHE_DURATION) )
  requestOptions['targets'] = []
  for target in queryParams.getlist('target'):
    requestOptions['targets'].append(target)

  if 'pickle' in queryParams:
    requestOptions['format'] = 'pickle'
  if 'rawData' in queryParams:
    requestOptions['format'] = 'raw'
  if 'format' in queryParams:
    requestOptions['format'] = queryParams['format']
    if 'jsonp' in queryParams:
      requestOptions['jsonp'] = queryParams['jsonp']
  if 'noCache' in queryParams:
    requestOptions['noCache'] = True

  requestOptions['localOnly'] = queryParams.get('local') == '1'

  # Fill in the graphOptions
  for opt in graphClass.customizable:
    if opt in queryParams:
      val = queryParams[opt]
      if (val.isdigit() or (val.startswith('-') and val[1:].isdigit())) and opt not in ('fgcolor','bgcolor','fontColor'):
        val = int(val)
      elif '.' in val and (val.replace('.','',1).isdigit() or (val.startswith('-') and val[1:].replace('.','',1).isdigit())):
        val = float(val)
      elif val.lower() in ('true','false'):
        val = val.lower() == 'true'
      elif val.lower() == 'default' or val == '':
        continue
      graphOptions[opt] = val

  # Get the time interval for time-oriented graph types
  if graphType == 'line' or graphType == 'pie':
    if 'until' in queryParams:
      untilTime = parseATTime( queryParams['until'] )
    else:
      untilTime = parseATTime('now')
    if 'from' in queryParams:
      fromTime = parseATTime( queryParams['from'] )
    else:
      fromTime = parseATTime('-1d')

    startTime = min(fromTime, untilTime)
    endTime = max(fromTime, untilTime)
    assert startTime != endTime, "Invalid empty time range"
    
    requestOptions['startTime'] = startTime
    requestOptions['endTime'] = endTime

  return (graphOptions, requestOptions)
Beispiel #21
0
 def test_relative_time_in_alternate_zone(self):
     expected_time = self.specified_tz.localize(datetime.strptime("11:00_20150308", '%H:%M_%Y%m%d'))
     actual_time = parseATTime("-1h", self.specified_tz)
     self.assertEqual(actual_time.hour, expected_time.hour)
Beispiel #22
0
def parseOptions(request):
    queryParams = request.GET.copy()
    queryParams.update(request.POST)

    # Start with some defaults
    graphOptions = {"width": 330, "height": 250}
    requestOptions = {}

    graphType = queryParams.get("graphType", "line")
    assert graphType in GraphTypes, "Invalid graphType '%s', must be one of %s" % (graphType, GraphTypes.keys())
    graphClass = GraphTypes[graphType]

    # Fill in the requestOptions
    requestOptions["graphType"] = graphType
    requestOptions["graphClass"] = graphClass
    requestOptions["pieMode"] = queryParams.get("pieMode", "average")
    requestOptions["cacheTimeout"] = int(queryParams.get("cacheTimeout", settings.DEFAULT_CACHE_DURATION))
    requestOptions["targets"] = []

    # Extract the targets out of the queryParams
    mytargets = []
    # Normal format: ?target=path.1&target=path.2
    if len(queryParams.getlist("target")) > 0:
        mytargets = queryParams.getlist("target")

    # Rails/PHP/jQuery common practice format: ?target[]=path.1&target[]=path.2
    elif len(queryParams.getlist("target[]")) > 0:
        mytargets = queryParams.getlist("target[]")

    # Collect the targets
    for target in mytargets:
        requestOptions["targets"].append(target)

    template = dict()
    for key, val in queryParams.items():
        if key.startswith("template["):
            template[key[9:-1]] = val
    requestOptions["template"] = template

    if "pickle" in queryParams:
        requestOptions["format"] = "pickle"
    if "rawData" in queryParams:
        requestOptions["format"] = "raw"
    if "format" in queryParams:
        requestOptions["format"] = queryParams["format"]
        if "jsonp" in queryParams:
            requestOptions["jsonp"] = queryParams["jsonp"]
    if "noCache" in queryParams:
        requestOptions["noCache"] = True
    if "maxDataPoints" in queryParams and queryParams["maxDataPoints"].isdigit():
        requestOptions["maxDataPoints"] = int(queryParams["maxDataPoints"])

    requestOptions["localOnly"] = queryParams.get("local") == "1"

    # Fill in the graphOptions
    for opt in graphClass.customizable:
        if opt in queryParams:
            val = queryParams[opt]
            if (val.isdigit() or (val.startswith("-") and val[1:].isdigit())) and "color" not in opt.lower():
                val = int(val)
            elif "." in val and (
                val.replace(".", "", 1).isdigit() or (val.startswith("-") and val[1:].replace(".", "", 1).isdigit())
            ):
                val = float(val)
            elif val.lower() in ("true", "false"):
                val = val.lower() == "true"
            elif val.lower() == "default" or val == "":
                continue
            graphOptions[opt] = val

    tzinfo = pytz.timezone(settings.TIME_ZONE)
    if "tz" in queryParams:
        try:
            tzinfo = pytz.timezone(queryParams["tz"])
        except pytz.UnknownTimeZoneError:
            pass
    requestOptions["tzinfo"] = tzinfo

    # Get the time interval for time-oriented graph types
    if graphType == "line" or graphType == "pie":
        if "until" in queryParams:
            untilTime = parseATTime(queryParams["until"], tzinfo)
        else:
            untilTime = parseATTime("now", tzinfo)
        if "from" in queryParams:
            fromTime = parseATTime(queryParams["from"], tzinfo)
        else:
            fromTime = parseATTime("-1d", tzinfo)

        startTime = min(fromTime, untilTime)
        endTime = max(fromTime, untilTime)
        assert startTime != endTime, "Invalid empty time range"

        requestOptions["startTime"] = startTime
        requestOptions["endTime"] = endTime
        timeRange = endTime - startTime
        queryTime = timeRange.days * 86400 + timeRange.seconds  # convert the time delta to seconds
        if settings.DEFAULT_CACHE_POLICY and not queryParams.get("cacheTimeout"):
            requestOptions["cacheTimeout"] = max(
                timeout for period, timeout in settings.DEFAULT_CACHE_POLICY if period <= queryTime
            )

    return (graphOptions, requestOptions)
Beispiel #23
0
 def test_midnight(self):
     expected_time = self.default_tz.localize(
         datetime.strptime("0:00_20150308", '%H:%M_%Y%m%d'))
     actual_time = parseATTime("midnight", self.specified_tz)
     self.assertEqual(actual_time,
                      expected_time.astimezone(self.specified_tz))
Beispiel #24
0
    def test_should_return_absolute_time(self):
        time_string = "12:0020150308"

        expected_time = self.default_tz.localize(datetime.strptime(time_string, "%H:%M%Y%m%d"))
        actual_time = parseATTime(time_string)
        self.assertEqual(actual_time, expected_time)
Beispiel #25
0
 def test_parse_last_leap_year(self):
     time_ref = parseATTime("-4years")
     expected = self.zone.localize(datetime(2009, 3, 1, 0, 0))
     self.assertEquals(time_ref, expected)
Beispiel #26
0
 def test_should_handle_dst_boundary(self):
     expected_time = self.specified_tz.localize(
         datetime.strptime("04:00_20150308", '%H:%M_%Y%m%d'))
     actual_time = parseATTime("midnight+3h", self.specified_tz)
     self.assertEqual(actual_time, expected_time)
Beispiel #27
0
 def test_should_return_absolute_time_short(self):
     time_string = '9:0020150308'
     expected_time = self.default_tz.localize(datetime.strptime(time_string,'%H:%M%Y%m%d'))
     actual_time = parseATTime(time_string, now=self.now)
     self.assertEqual(actual_time, expected_time)
Beispiel #28
0
 def test_midnight(self):
     expected_time = self.specified_tz.localize(
         datetime.strptime("0:00_20171013", '%H:%M_%Y%m%d'))
     actual_time = parseATTime("midnight", self.specified_tz, now=self.now)
     self.assertEqual(actual_time, expected_time)
Beispiel #29
0
 def test_midnight(self):
     expected_time = self.specified_tz.localize(datetime.strptime("0:00_20171013", '%H:%M_%Y%m%d'))
     actual_time = parseATTime("midnight", self.specified_tz, now=self.now)
     self.assertEqual(actual_time, expected_time)
Beispiel #30
0
 def test_parse_last_year(self):
     time_ref = parseATTime("-1year")
     expected = self.zone.localize(datetime(2012, 2, 29, 0, 0))
     self.assertEquals(time_ref, expected)
Beispiel #31
0
 def test_absolute_time_should_respect_tz(self):
     time_string = '12:0020150308'
     expected_time = self.specified_tz.localize(
         datetime.strptime(time_string, '%H:%M%Y%m%d'))
     actual_time = parseATTime(time_string, self.specified_tz)
     self.assertEqual(actual_time, expected_time)
Beispiel #32
0
 def test_parse_last_month(self):
     time_ref = parseATTime("-1month")
     expected = self.zone.localize(datetime(2013, 1, 29, 0, 0))
     self.assertEquals(time_ref, expected)
Beispiel #33
0
 def test_absolute_time_YYYYMMDD(self):
     time_string = '20150110'
     expected_time = self.specified_tz.localize(
         datetime.strptime(time_string, '%Y%m%d'))
     actual_time = parseATTime(time_string, self.specified_tz)
     self.assertEqual(actual_time, expected_time)
Beispiel #34
0
 def test_absolute_time_should_respect_tz_short(self):
     time_string = '9:0020150308'
     expected_time = self.specified_tz.localize(datetime.strptime(time_string, '%H:%M%Y%m%d'))
     actual_time = parseATTime(time_string, self.specified_tz)
     self.assertEqual(actual_time, expected_time)
Beispiel #35
0
 def test_parse_last_year(self):
     time_ref = parseATTime("-1year")
     expected = self.zone.localize(datetime(2012, 2, 29, 0, 0))
     self.assertEquals(time_ref, expected)
Beispiel #36
0
 def test_relative_day_with_tz(self):
     expected_time = self.specified_tz.localize(datetime.strptime("0:00_20171014", '%H:%M_%Y%m%d'))
     actual_time = parseATTime("midnight_tomorrow", self.specified_tz, now=self.now)
     self.assertEqual(actual_time, expected_time)
Beispiel #37
0
 def test_parse_last_leap_year(self):
     time_ref = parseATTime("-4years")
     expected = self.zone.localize(datetime(2009, 3, 1, 0, 0))
     self.assertEquals(time_ref, expected)
Beispiel #38
0
 def test_absolute_time_YYYYMMDD(self):
     time_string = '20150110'
     expected_time = self.specified_tz.localize(datetime.strptime(time_string, '%Y%m%d'))
     actual_time = parseATTime(time_string, self.specified_tz)
     self.assertEqual(actual_time, expected_time)
Beispiel #39
0
 def test_parse_last_month(self):
     time_ref = parseATTime("-1month")
     expected = self.zone.localize(datetime(2013, 1, 29, 0, 0))
     self.assertEquals(time_ref, expected)
Beispiel #40
0
 def test_relative_day_and_offset_with_tz(self):
     expected_time = self.specified_tz.localize(datetime.strptime("3:00_20150309", '%H:%M_%Y%m%d'))
     actual_time = parseATTime("midnight_tomorrow+3h", self.specified_tz)
     self.assertEqual(actual_time, expected_time)
Beispiel #41
0
 def test_parse_noon_plus_yesterday(self):
     time_ref = parseATTime("noon+yesterday")
     expected = datetime(self.MOCK_DATE.year, self.MOCK_DATE.month,
                         self.MOCK_DATE.day - 1, 12, 00)
     self.assertEquals(time_ref, expected)
Beispiel #42
0
 def test_now_should_respect_tz(self):
     expected_time = self.specified_tz.localize(datetime.strptime("12:00_20150308", '%H:%M_%Y%m%d'))
     actual_time = parseATTime("now", self.specified_tz)
     self.assertEqual(actual_time, expected_time)
Beispiel #43
0
 def test_offset_with_tz(self):
     expected_time = self.specified_tz.localize(
         datetime.strptime("1:00_20150308", '%H:%M_%Y%m%d'))
     actual_time = parseATTime("midnight+1h", self.specified_tz)
     self.assertEqual(actual_time, expected_time)
Beispiel #44
0
 def test_should_handle_dst_boundary(self):
     expected_time = self.specified_tz.localize(datetime.strptime("04:00_20150308", '%H:%M_%Y%m%d'))
     actual_time = parseATTime("midnight+3h", self.specified_tz)
     self.assertEqual(actual_time, expected_time)
Beispiel #45
0
 def test_relative_day_and_offset_with_tz(self):
     expected_time = self.specified_tz.localize(
         datetime.strptime("3:00_20150309", '%H:%M_%Y%m%d'))
     actual_time = parseATTime("midnight_tomorrow+3h", self.specified_tz)
     self.assertEqual(actual_time, expected_time)
Beispiel #46
0
 def test_should_return_current_time(self):
     expected_time = self.default_tz.localize(
         datetime.strptime("12:00_20150308", '%H:%M_%Y%m%d'))
     actual_time = parseATTime("now")
     self.assertEqual(actual_time, expected_time)
Beispiel #47
0
 def test_now_should_respect_tz(self):
     expected_time = self.specified_tz.localize(
         datetime.strptime("12:00_20150308", '%H:%M_%Y%m%d'))
     actual_time = parseATTime("now", self.specified_tz)
     self.assertEqual(actual_time, expected_time)
Beispiel #48
0
 def test_parse_noon_plus_yesterday(self):
     time_ref = parseATTime("noon+yesterday")
     expected = datetime.datetime(MOCK_DATE.year, MOCK_DATE.month, MOCK_DATE.day - 1, 12, 00)
     self.assertEquals(time_ref, expected)
Beispiel #49
0
def parseOptions(request):
    queryParams = request.REQUEST

    # Start with some defaults
    graphOptions = {'width': 330, 'height': 250}
    requestOptions = {}

    graphType = queryParams.get('graphType', 'line')
    assert graphType in GraphTypes, "Invalid graphType '%s', must be one of %s" % (
        graphType, GraphTypes.keys())
    graphClass = GraphTypes[graphType]

    # Fill in the requestOptions
    requestOptions['graphType'] = graphType
    requestOptions['graphClass'] = graphClass
    requestOptions['pieMode'] = queryParams.get('pieMode', 'average')
    requestOptions['targets'] = []
    for target in queryParams.getlist('target'):
        if target.lower().startswith(
                'graphite.'):  #Strip leading "Graphite." as a convenience
            target = target[9:]
        requestOptions['targets'].append(target)

    if 'pickle' in queryParams:
        requestOptions['pickle'] = True
    if 'rawData' in queryParams:
        requestOptions['rawData'] = True
    if 'format' in queryParams:
        requestOptions['format'] = queryParams['format']
    if 'noCache' in queryParams:
        requestOptions['noCache'] = True

    requestOptions['localOnly'] = queryParams.get('local') == '1'

    # Fill in the graphOptions
    for opt in graphClass.customizable:
        if opt in queryParams:
            val = queryParams[opt]
            if (val.isdigit() or
                (val.startswith('-') and val[1:].isdigit())) and opt not in (
                    'fgcolor', 'bgcolor', 'fontColor'):
                val = int(val)
            elif '.' in val and (val.replace('.', '', 1).isdigit() or
                                 (val.startswith('-')
                                  and val[1:].replace('.', '', 1).isdigit())):
                val = float(val)
            elif val.lower() in ('true', 'false'):
                val = val.lower() == 'true'
            elif val.lower() == 'default' or val == '':
                continue
            graphOptions[opt] = val

    # Get the time interval for time-oriented graph types
    if graphType == 'line' or graphType == 'pie':
        if 'until' in queryParams:
            endTime = parseATTime(queryParams['until'])
        else:
            endTime = datetime.now()
        if 'from' in queryParams:
            startTime = parseATTime(queryParams['from'])
        else:
            startTime = endTime - timedelta(days=1)
        if endTime > datetime.now():
            endTime = datetime.now()
        assert startTime < endTime, "Invalid time range!"

        requestOptions['startTime'] = startTime
        requestOptions['endTime'] = endTime

    return (graphOptions, requestOptions)