Source code for aiomisc.counters
from collections import Counter
from collections.abc import Generator, Iterator, MutableMapping, MutableSet
from dataclasses import dataclass
from typing import Any, Union
from weakref import WeakSet
[docs]
class Metric:
__slots__ = ("counter", "name")
def __init__(
self,
name: str,
counter: MutableMapping[str, float | int],
default: float | int = 0,
):
self.name: str = name
self.counter = counter
self.counter[name] = default
def __get__(self) -> float | int:
return self.counter[self.name]
def __set__(self, value: float | int) -> None:
self.counter[self.name] = value
def __iadd__(self, value: float | int) -> "Metric":
self.counter[self.name] += value
return self
def __isub__(self, value: float | int) -> "Metric":
self.counter[self.name] -= value
return self
def __eq__(self, other: Any) -> bool:
return self.counter[self.name] == other
def __hash__(self) -> int:
return hash(self.counter[self.name])
[docs]
class AbstractStatistic:
__metrics__: frozenset[str]
__instances__: MutableSet["AbstractStatistic"]
_counter: MutableMapping[str, float | int]
name: str | None
CLASS_STORE: set[type[AbstractStatistic]] = set()
[docs]
class Statistic(AbstractStatistic, metaclass=MetaStatistic):
__slots__ = ("_counter", "name")
def __init__(self, name: str | None = None) -> None:
self._counter = Counter() # type: ignore
self.name = name
for prop in self.__metrics__:
setattr(self, prop, Metric(prop, self._counter))
self.__instances__.add(self)
[docs]
@dataclass(frozen=True)
class StatisticResult:
kind: type[AbstractStatistic]
name: str | None
metric: str
value: int | float
def __iter__(self) -> Iterator:
yield self.kind
yield self.name
yield self.metric
yield self.value
# noinspection PyProtectedMember
[docs]
def get_statistics(
*kind: type[Statistic],
) -> Generator[Any, tuple[Statistic, str, int], None]:
for klass in CLASS_STORE:
if kind and not issubclass(klass, kind):
continue
for instance in klass.__instances__:
for metric, value in instance._counter.items():
yield StatisticResult(
kind=klass, name=instance.name, metric=metric, value=value
)