import typing from .metric_base import MetricBase, MetricGroupBase, MetricGroupDefinition, MetricMutableValue, Now, NOW from .registry import Path, GLOBAL_REGISTRY __all__ = [ 'Counter', 'Gauge', 'Summary', ] class Counter(MetricBase): metric_type: typing.ClassVar[str] = 'counter' def __init__(self, value: float = 0, path: typing.Optional[Path] = None, help: typing.Optional[str] = None): super().__init__(value=value, help=help) if not path is None: GLOBAL_REGISTRY.register(path, self) class Gauge(MetricBase): metric_type: typing.ClassVar[str] = 'gauge' def __init__(self, value: float = float('nan'), path: typing.Optional[Path] = None, help: typing.Optional[str] = None): super().__init__(value=value, help=help) if not path is None: GLOBAL_REGISTRY.register(path, self) class Summary(MetricGroupBase): metric_type: typing.ClassVar[str] = 'summary' group_definition: typing.ClassVar[MetricGroupDefinition] = MetricGroupDefinition( frozenset(['_sum', '_count']), frozenset(['quantile']), ) def __init__(self, path: typing.Optional[Path] = None, help: typing.Optional[str] = None): super().__init__(help=help) self._lock = MetricMutableValue.DEFAULT_LOCK self._sum = MetricMutableValue(0, None, self._lock) self._count = MetricMutableValue(0, None, self._lock) if not path is None: GLOBAL_REGISTRY.register(path, self) def metrics(self) -> typing.Iterator[typing.Tuple[(Path, MetricMutableValue)]]: return [ (Path('_sum'), self._sum), (Path('_count'), self._count), ] def observe(self, value: float, timestamp: typing.Union[int, None, Now] = NOW): if isinstance(timestamp, Now): timestamp = timestamp.time() with self._lock: self._count.inc_no_lock(1, timestamp) self._sum.inc_no_lock(value, timestamp)