def test_history_insert_with_epoch_set(history_with_epoch_set): # Inserting a transition into a history with an epoch already set should # make that transition the most recent transition of that history. ts = history_with_epoch_set.epoch + Timedelta.from_s(1) history_with_epoch_set.insert(ts, State.OK) assert history_with_epoch_set.transitions[-1].time == ts
def test_history_monotonous(history_with_epoch_set): ts = history_with_epoch_set.epoch for delta in (Timedelta.from_s(1), Timedelta.from_string("20s")): new_ts = ts + delta history_with_epoch_set.insert(new_ts, State.OK) assert history_with_epoch_set.transitions[-1].time == new_ts
def __init__(self, time_window: Optional[Timedelta]): """A history of state transitions for some metric, spanning at most a duration of ``time_window``. It contains a point in time called 'epoch' that signifies when the state that the first transition switched from was entered. In a graph (t[0] is the first transition, t[1] the second etc.): ┌┄┄┄┄┄┄┄┄┄┄┄┄┄┄╮┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄╮ ⋯ │ t[0].state │ t[1].state │ ⋯──────┴──────────────┴────────────────────┴────────────→ epoch t[0].time t[1].time time """ # The list of state transitions for this metric. self._transitions: List[StateTransition] = list() # The point in time at which we assume the metric entered the state # given by the first transition ``self._transitions[0]``, if present. # This is necessary as transitions have last semantics, and we otherwise # had to assume that it was in this state since forever (which skews # statistics significantly, as you can imagine). self._epoch: Optional[Timestamp] = None # Use a sensible default time window for keeping past transitions. self._time_window: Timedelta if time_window is None: self._time_window = Timedelta.from_s(30) else: if time_window.ns > 0: self._time_window = time_window else: raise ValueError( "State transition history time window must be a positive duration" )
def test_history_non_monotonous(history_with_epoch_set, delta, caplog): ts = history_with_epoch_set.epoch + Timedelta.from_s(1) history_with_epoch_set.insert(ts, State.OK) next_ts = ts + delta with caplog.at_level(logging.WARNING): history_with_epoch_set.insert(next_ts, State.OK) assert "Times of state transitions must be strictly increasing" in caplog.text
def _metric(): timestamp = Timestamp(0) delta = Timedelta.from_s(1) value = 0.0 while True: yield (timestamp, value) timestamp += delta value += 1.0
class Ticker: DEFAULT_DELTA = Timedelta.from_s(1) DEFAULT_START = Timestamp(0) def __init__(self, delta=DEFAULT_DELTA, start=DEFAULT_START): self.delta = delta self.start = start self.now = self.start def __next__(self): now = self.now self.now += self.delta return now def __iter__(self): return self
def test_history_monotonous(history_with_epoch_set): ts = history_with_epoch_set.epoch for delta in (Timedelta.from_s(1), Timedelta.from_string("20s")): new_ts = ts + delta history_with_epoch_set.insert(new_ts, State.OK) assert history_with_epoch_set.transitions[-1].time == new_ts @pytest.mark.parametrize( "delta", [ Timedelta(0), Timedelta.from_s(-1), ], ) def test_history_non_monotonous(history_with_epoch_set, delta, caplog): ts = history_with_epoch_set.epoch + Timedelta.from_s(1) history_with_epoch_set.insert(ts, State.OK) next_ts = ts + delta with caplog.at_level(logging.WARNING): history_with_epoch_set.insert(next_ts, State.OK) assert "Times of state transitions must be strictly increasing" in caplog.text @pytest.mark.parametrize( "ticker", [Timedelta.from_string("30s"), Timedelta(1)], indirect=True)
@pytest.fixture def interval_source(): with patch("metricq.interval_source.IntervalSource.rpc"): source = _TestIntervalSource(token="source-interval-test", management_url="amqps://test.invalid") yield source @pytest.mark.parametrize( ("period", "normalized"), [ (Timedelta(1337), Timedelta(1337)), (4, Timedelta.from_s(4)), ], ) def test_period_setter_normalizing(interval_source: _TestIntervalSource, period, normalized): """Internally, the interval source period is normalized to a Timedelta""" assert interval_source.period is None interval_source.period = period assert interval_source.period == normalized def test_period_no_reset(interval_source: _TestIntervalSource): """Currently, the interval source period cannot be reset to None""" with pytest.raises(TypeError,
def tick() -> Timedelta: return Timedelta.from_s(0.1)