add personal logging

This commit is contained in:
Oleg Oleg 2025-12-19 22:59:41 +04:00
parent 9bf50b3772
commit a1933c7b14
4 changed files with 61 additions and 30 deletions

2
.gitignore vendored
View File

@ -13,3 +13,5 @@ conversations.pkl
*.png
*.jpeg
.vscode/
data/actors
examples.ini

View File

@ -28,7 +28,7 @@ RUN poetry config virtualenvs.create false \
COPY src/ ./src/
# Create directories for bot persistence
RUN mkdir -p /app/data
RUN mkdir -p /app/data/actors
# Create non-root user
RUN groupadd -r botuser && useradd -r -g botuser botuser

View File

@ -2,6 +2,7 @@ import logging
import sys
from logging.handlers import RotatingFileHandler
from typing import Sequence
from threading import Lock
from core.config import settings
@ -24,10 +25,49 @@ class ExtendedLogger(logging.Logger):
formatted = ", ".join(items)
self.info(f"{message}: {formatted}")
class ActorLogger(logging.Logger):
def __init__(self):
self.__loggers: dict[str, logging.Logger] = {}
self.lock = Lock()
def log(self, actor_id: int, level: int, msg: str):
logger = self._get_or_create_logger(actor_id)
logger.log(level, msg)
def info(self, actor_id: int, msg: str):
self.log(actor_id, logging.INFO, msg)
def error(self, actor_id: int, msg: str):
self.log(actor_id, logging.ERROR, msg)
def warning(self, actor_id: int, msg: str):
self.log(actor_id, logging.WARNING, msg)
def _get_or_create_logger(self, actor_id: str):
with self.lock:
if actor_id not in self.__loggers:
logger = logging.getLogger(f"actor_{actor_id}")
logger.setLevel(logging.INFO)
handler = RotatingFileHandler(
filename=f"/app/data/actors/actor_{actor_id}.log",
maxBytes=5 * 1024 * 1024,
backupCount=5,
encoding='utf-8'
)
formatter = logging.Formatter(
fmt="%(asctime)s %(levelname)s [%(name)s] %(message)s",
datefmt="%Y-%m-%d %H:%M:%S"
)
handler.setFormatter(formatter)
logger.addHandler(handler)
self.__loggers[actor_id] = logger
return self.__loggers[actor_id]
def setup_logging():
"""
Инициализирует логирование для всего приложения.
Конфигурирует консольный и файловый логгеры с ротацией.
Конфигурирует консольный логгер.
"""
# Используем наш кастомный класс логгера
@ -52,18 +92,6 @@ def setup_logging():
# Собираем хэндлеры
handlers = [console_handler]
# Файловый хэндлер с ротацией (если указан путь в настройках)
if hasattr(settings, 'log_file_path') and settings.log_file_path:
file_handler = RotatingFileHandler(
filename=settings.log_file_path,
maxBytes=10 * 1024 * 1024, # 10 MB
backupCount=5,
encoding="utf-8"
)
file_handler.setLevel(log_level)
file_handler.setFormatter(formatter)
handlers.append(file_handler)
# Конфигурируем корневой логгер
root_logger = logging.getLogger()
root_logger.setLevel(log_level)

View File

@ -20,7 +20,7 @@ from docbot.services.doctors_service import (
get_doctors_payment_link, get_doctor_by_code
)
from docbot.services.session_service import create_session
from core.logging import logger
from core.logging import logger, ActorLogger
from core.exceptions import DatabaseError
from core.enums.dialog_helpers import ConfirmationMessage
from core.utils import is_phone_correct, make_a_payment_link
@ -34,6 +34,7 @@ ENTER_DOCTOR_NUMBER = 5
ENTER_CONSULTATION_DATE = 6
PAY_CONSULTATION = 7
ERROR_PHONE_NUMBER = 8
actor_logger = ActorLogger()
STOPPING = 99
@ -78,14 +79,14 @@ async def accept_personal_data_agreement(update: Update, context: ContextTypes.D
try:
registered = await get_patient_by_telegram_id(user_id)
except DatabaseError as e:
logger.error(f"Database error while fetching patient by Telegram ID {user_id}: {e}")
actor_logger.error(user_id, f"Database error while fetching patient by Telegram ID {user_id}: {e}")
await update.message.reply_text(
"❌ Произошла ошибка при обработке вашего запроса. Пожалуйста, попробуйте позже."
)
return ConversationHandler.END
logger.info(f"User {user_id} initiated consultation process.")
logger.info(f"User exists? {registered}")
actor_logger.info(user_id, f"User {user_id} initiated consultation process.")
actor_logger.info(user_id, f"User exists? {registered}")
if registered:
await update.message.reply_text(
@ -113,7 +114,7 @@ async def receive_patient_aceptance(update: Update, context: ContextTypes.DEFAUL
try:
await create_patient(telegram_id=user_id, terms_acceptance=True) # Создаем пациента в БД
except DatabaseError as e:
logger.error(f"Failed to create patient for user {user_id}: {e}")
actor_logger.error(user_id, f"Failed to create patient for user {user_id}: {e}")
await update.callback_query.edit_message_text(
text="❌ Произошла ошибка при создании вашей записи. Пожалуйста, попробуйте позже."
)
@ -167,20 +168,20 @@ async def enter_patient_phone(update: Update, context: ContextTypes.DEFAULT_TYPE
if patient:
has_phone = await is_user_has_phone(user_id)
logger.info(f"User {user_id} has phone: {has_phone}")
actor_logger.info(user_id, f"User {user_id} has phone: {has_phone}")
if update.callback_query.data == 'back':
logger.info(f"User {user_id} requested correction of their phone number")
actor_logger.info(user_id, f"User {user_id} requested correction of their phone number")
if not has_phone:
logger.info(f"Ask user {user_id} enter a phone number.")
actor_logger.info(user_id, f"Ask user {user_id} enter a phone number.")
await update.callback_query.message.reply_text(
text="Пожалуйста, введите ваш номер мобильного телефона для записи на консультацию:\n"
"Без знака +, вида 79991112233"
)
return ENTER_PATIENT_PHONE
else:
logger.info(f"Ask user {user_id} enter a doctor's id.")
actor_logger.info(user_id, f"Ask user {user_id} enter a doctor's id.")
await update.callback_query.edit_message_text(
text="Введите серийный номер врача, к которому вы хотите записаться на консультацию:",
parse_mode="Markdown"
@ -196,7 +197,7 @@ async def receive_patient_phone(update: Update, context: ContextTypes.DEFAULT_TY
# Например, вызов сервиса для обновления информации о пациенте
# await update_patient_phone(telegram_id=user_id, phone=phone)
logger.info((f"Checking user's phone {is_phone_correct(phone=phone)}"))
actor_logger.info(user_id, f"Checking user's phone {is_phone_correct(phone=phone)}")
if not is_phone_correct(phone=phone):
keyboard = [
[
@ -213,7 +214,7 @@ async def receive_patient_phone(update: Update, context: ContextTypes.DEFAULT_TY
)
return ERROR_PHONE_NUMBER
logger.info((f"receive_patient_phone User {user_id} provided phone: {phone}"))
actor_logger.info(user_id, f"receive_patient_phone User {user_id} provided phone: {phone}")
context.user_data['phone'] = phone
keyboard = [
@ -244,7 +245,7 @@ async def receive_doctor_number(update: Update, context: ContextTypes.DEFAULT_TY
if not await is_user_has_phone(user_id):
patient_phone = context.user_data['phone']
await update_patient_phone(telegram_id=user_id, phone=patient_phone)
logger.info((f"Saved patient's phone number {patient_phone}"))
actor_logger.info(user_id, f"Saved patient's phone number {patient_phone}")
await update.message.reply_text(
text=f"Вы ввели серийный номер врача: {doctor_number}\n"
@ -252,7 +253,7 @@ async def receive_doctor_number(update: Update, context: ContextTypes.DEFAULT_TY
parse_mode="Markdown"
)
else:
logger.info(f"User {user_id} requested correction of their consultation date")
actor_logger.info(user_id, f"User {user_id} requested correction of their consultation date")
await update.effective_message.reply_text(
text="Введите дату и время консультации в формате ДД.ММ.ГГ ЧЧ:ММ, например, 01.01.23 12:00.",
parse_mode="Markdown"
@ -299,7 +300,7 @@ async def pay_consultation(update: Update, context: ContextTypes.DEFAULT_TYPE) -
patient = await get_patient_by_telegram_id(user_id)
doctor = await get_doctor_by_code(context.user_data['doctor_number'])
except DatabaseError as e:
logger.error(f"Database error during payment process for user {user_id}: {e}")
actor_logger.error(user_id, f"Database error during payment process for user {user_id}: {e}")
await update.callback_query.message.reply_text(
"❌ Произошла ошибка при обработке вашего запроса. Пожалуйста, попробуйте позже."
)
@ -316,7 +317,7 @@ async def pay_consultation(update: Update, context: ContextTypes.DEFAULT_TYPE) -
doctor=doctor
)
except DatabaseError as e:
logger.error(f"Failed to create session for user {user_id}: {e}")
actor_logger.error(user_id, f"Failed to create session for user {user_id}: {e}")
await update.callback_query.message.reply_text(
"❌ Произошла ошибка при создании записи на консультацию. Пожалуйста, попробуйте позже."
)