mirror of
https://github.com/olegvodyanov/docbot.git
synced 2025-12-19 23:57:05 +03:00
add personal logging
This commit is contained in:
parent
9bf50b3772
commit
a1933c7b14
4
.gitignore
vendored
4
.gitignore
vendored
@ -12,4 +12,6 @@ conversations.pkl
|
||||
*.jpg
|
||||
*.png
|
||||
*.jpeg
|
||||
.vscode/
|
||||
.vscode/
|
||||
data/actors
|
||||
examples.ini
|
||||
@ -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
|
||||
|
||||
@ -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
|
||||
|
||||
@ -23,11 +24,50 @@ class ExtendedLogger(logging.Logger):
|
||||
else:
|
||||
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)
|
||||
|
||||
@ -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(
|
||||
"❌ Произошла ошибка при создании записи на консультацию. Пожалуйста, попробуйте позже."
|
||||
)
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user