diff --git a/bots/handlers/metrics_handler.py b/bots/handlers/metrics_handler.py new file mode 100644 index 0000000..189db59 --- /dev/null +++ b/bots/handlers/metrics_handler.py @@ -0,0 +1,62 @@ +# -*- coding: utf-8 -*- +""" +Хендлер для сбора и хранения метрик работы бота. +Счётчики: сообщения, обработанные файлы, AI-запросы, ошибки. +Предоставляет методы increment, get, reset. +""" + +import logging +from typing import Dict, Any + +logger = logging.getLogger(__name__) + + +class MetricsHandler: + """Управляет статистикой работы бота.""" + + def __init__(self): + # Внутренний словарь со счётчиками (все инициализируются нулями) + self._metrics: Dict[str, int] = { + "messages_total": 0, # общее количество входящих сообщений + "files_processed": 0, # количество файлов, загруженных и обработанных + "ai_requests": 0, # количество вызовов AI (генерация, классификация и т.д.) + "errors_total": 0 # общее количество ошибок (исключений) + } + + def increment(self, metric_name: str, value: int = 1) -> None: + """ + Увеличивает указанный счётчик на заданное значение (по умолчанию 1). + + Аргументы: + metric_name (str): имя счётчика (должно быть одним из ключей _metrics). + value (int): на сколько увеличить. + + Логирует изменение на уровне DEBUG, если счётчик существует. + Если передан неизвестный счётчик, логирует предупреждение. + """ + if metric_name in self._metrics: + self._metrics[metric_name] += value + logger.debug(f"Метрика {metric_name} увеличена до {self._metrics[metric_name]}") + else: + logger.warning(f"Попытка инкремента неизвестной метрики: {metric_name}") + + def get(self, metric_name: str = None) -> int | Dict[str, int]: + """ + Возвращает либо значение конкретной метрики, либо копию всех метрик. + + Аргументы: + metric_name (str, optional): имя счётчика. Если None, возвращается словарь всех метрик. + + Возвращает: + int или Dict[str, int]: запрошенное значение или копия словаря. + """ + if metric_name: + return self._metrics.get(metric_name, 0) + # Возвращаем копию, чтобы внешний код не мог изменить внутренний словарь напрямую + return self._metrics.copy() + + def reset(self) -> None: + """Сбрасывает все счётчики в 0. Логирует действие.""" + for key in self._metrics: + self._metrics[key] = 0 + logger.info("Все метрики сброшены") \ No newline at end of file