Example #1
0
 def _sanity_check_time(self, start_time, end_time):
   assert isinstance(start_time, datetime)
   assert isinstance(end_time, datetime)
   assert start_time < end_time
   # TODO(marcua): turn these into a value error
   if (((datetime_to_epoch_time(start_time) % self._bucket_width) != 0) or
       ((datetime_to_epoch_time(end_time) % self._bucket_width) != 0)):
     raise ValueError('start_time and end_time must be on bucket_width '
                      'boundaries')
Example #2
0
  def _get_timeframe_bounds(self, timeframe, bucket_width):
    """
    Get a `bucket_width` aligned `start_time` and `end_time` from a
    `timeframe` dict
    """
    if bucket_width:
      bucket_width_seconds = bucket_width
      bucket_width = epoch_time_to_kronos_time(bucket_width)

    # TODO(derek): Potential optimization by setting the end_time equal to the
    # untrusted_time if end_time > untrusted_time and the results are not being
    # output to the user (only for caching)
    if timeframe['mode'] == 'recent':
      # Set end_time equal to now and align to bucket width
      end_time = datetime_to_kronos_time(datetime.datetime.now())
      original_end_time = end_time
      duration = get_seconds(timeframe['value'], timeframe['scale'])
      duration = epoch_time_to_kronos_time(duration)
      start_time = original_end_time - duration

      if bucket_width:
        # Align values to the bucket width
        # TODO(derek): Warn the user that the timeframe has been altered to fit
        # the bucket width
        if (end_time % bucket_width) != 0:
          end_time += bucket_width - (end_time % bucket_width)

        if (start_time % bucket_width) != 0:
          start_time -= (start_time % bucket_width)

      start = kronos_time_to_datetime(start_time)
      end = kronos_time_to_datetime(end_time)
    elif timeframe['mode'] == 'range':
      end = datetime.datetime.strptime(timeframe['to'], DT_FORMAT)
      end_seconds = datetime_to_epoch_time(end)

      start = datetime.datetime.strptime(timeframe['from'], DT_FORMAT)
      start_seconds = datetime_to_epoch_time(start)

      if bucket_width:
        # Align values to the bucket width
        # TODO(derek): Warn the user that the timeframe has been altered to fit
        # the bucket width
        start_bump = start_seconds % bucket_width_seconds
        start -= datetime.timedelta(seconds=start_bump)
        if (end_seconds % bucket_width_seconds) != 0:
          end_bump = bucket_width_seconds - (end_seconds % bucket_width_seconds)
          end += datetime.timedelta(seconds=end_bump)
    else:
      raise ValueError("Timeframe mode must be 'recent' or 'range'")

    return start, end
Example #3
0
  def _compute_buckets(self, start_time, end_time, compute_missing=True,
                       cache=False, untrusted_time=None,
                       force_recompute=False):
    self._sanity_check_time(start_time, end_time)

    # Generate a list of all cached buckets we need to see data for.
    required_buckets = xrange(int(datetime_to_epoch_time(start_time)),
                              int(datetime_to_epoch_time(end_time)),
                              self._bucket_width)

    # Get any cached results, grouped by bucket.
    if force_recompute is True:
      cached_bucket_iterator = iter([])
    else:
      cached_bucket_iterator = iter(self._cached_results(start_time, end_time))

    # Use either the cached results or compute any uncached buckets.
    # Cache previously uncached results if they are guaranteed to have
    # happened before the untrusted time.
    current_cached_bucket = None
    for required_bucket in required_buckets:
      if current_cached_bucket is None:
        try:
          current_cached_bucket = cached_bucket_iterator.next()
        except StopIteration:
          pass
      emit_events = None
      if (current_cached_bucket is not None) and (
          current_cached_bucket[0] == required_bucket):
        emit_events = current_cached_bucket[1]
        current_cached_bucket = None
      else:
        if compute_missing is True:
          # We don't have cached events, so compute the query.
          emit_events = self._compute_bucket(required_bucket, untrusted_time,
                                             cache=cache)
        else:
          emit_events = []
      for event in emit_events:
        yield event
    self._client.flush()