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
|
*.jpg
|
||||||
*.png
|
*.png
|
||||||
*.jpeg
|
*.jpeg
|
||||||
.vscode/
|
.vscode/
|
||||||
|
data/actors
|
||||||
|
examples.ini
|
||||||
@ -28,7 +28,7 @@ RUN poetry config virtualenvs.create false \
|
|||||||
COPY src/ ./src/
|
COPY src/ ./src/
|
||||||
|
|
||||||
# Create directories for bot persistence
|
# Create directories for bot persistence
|
||||||
RUN mkdir -p /app/data
|
RUN mkdir -p /app/data/actors
|
||||||
|
|
||||||
# Create non-root user
|
# Create non-root user
|
||||||
RUN groupadd -r botuser && useradd -r -g botuser botuser
|
RUN groupadd -r botuser && useradd -r -g botuser botuser
|
||||||
|
|||||||
@ -2,6 +2,7 @@ import logging
|
|||||||
import sys
|
import sys
|
||||||
from logging.handlers import RotatingFileHandler
|
from logging.handlers import RotatingFileHandler
|
||||||
from typing import Sequence
|
from typing import Sequence
|
||||||
|
from threading import Lock
|
||||||
|
|
||||||
from core.config import settings
|
from core.config import settings
|
||||||
|
|
||||||
@ -23,11 +24,50 @@ class ExtendedLogger(logging.Logger):
|
|||||||
else:
|
else:
|
||||||
formatted = ", ".join(items)
|
formatted = ", ".join(items)
|
||||||
self.info(f"{message}: {formatted}")
|
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():
|
def setup_logging():
|
||||||
"""
|
"""
|
||||||
Инициализирует логирование для всего приложения.
|
Инициализирует логирование для всего приложения.
|
||||||
Конфигурирует консольный и файловый логгеры с ротацией.
|
Конфигурирует консольный логгер.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
# Используем наш кастомный класс логгера
|
# Используем наш кастомный класс логгера
|
||||||
@ -52,18 +92,6 @@ def setup_logging():
|
|||||||
# Собираем хэндлеры
|
# Собираем хэндлеры
|
||||||
handlers = [console_handler]
|
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 = logging.getLogger()
|
||||||
root_logger.setLevel(log_level)
|
root_logger.setLevel(log_level)
|
||||||
|
|||||||
@ -20,7 +20,7 @@ from docbot.services.doctors_service import (
|
|||||||
get_doctors_payment_link, get_doctor_by_code
|
get_doctors_payment_link, get_doctor_by_code
|
||||||
)
|
)
|
||||||
from docbot.services.session_service import create_session
|
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.exceptions import DatabaseError
|
||||||
from core.enums.dialog_helpers import ConfirmationMessage
|
from core.enums.dialog_helpers import ConfirmationMessage
|
||||||
from core.utils import is_phone_correct, make_a_payment_link
|
from core.utils import is_phone_correct, make_a_payment_link
|
||||||
@ -34,6 +34,7 @@ ENTER_DOCTOR_NUMBER = 5
|
|||||||
ENTER_CONSULTATION_DATE = 6
|
ENTER_CONSULTATION_DATE = 6
|
||||||
PAY_CONSULTATION = 7
|
PAY_CONSULTATION = 7
|
||||||
ERROR_PHONE_NUMBER = 8
|
ERROR_PHONE_NUMBER = 8
|
||||||
|
actor_logger = ActorLogger()
|
||||||
|
|
||||||
|
|
||||||
STOPPING = 99
|
STOPPING = 99
|
||||||
@ -78,14 +79,14 @@ async def accept_personal_data_agreement(update: Update, context: ContextTypes.D
|
|||||||
try:
|
try:
|
||||||
registered = await get_patient_by_telegram_id(user_id)
|
registered = await get_patient_by_telegram_id(user_id)
|
||||||
except DatabaseError as e:
|
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(
|
await update.message.reply_text(
|
||||||
"❌ Произошла ошибка при обработке вашего запроса. Пожалуйста, попробуйте позже."
|
"❌ Произошла ошибка при обработке вашего запроса. Пожалуйста, попробуйте позже."
|
||||||
)
|
)
|
||||||
return ConversationHandler.END
|
return ConversationHandler.END
|
||||||
|
|
||||||
logger.info(f"User {user_id} initiated consultation process.")
|
actor_logger.info(user_id, f"User {user_id} initiated consultation process.")
|
||||||
logger.info(f"User exists? {registered}")
|
actor_logger.info(user_id, f"User exists? {registered}")
|
||||||
|
|
||||||
if registered:
|
if registered:
|
||||||
await update.message.reply_text(
|
await update.message.reply_text(
|
||||||
@ -113,7 +114,7 @@ async def receive_patient_aceptance(update: Update, context: ContextTypes.DEFAUL
|
|||||||
try:
|
try:
|
||||||
await create_patient(telegram_id=user_id, terms_acceptance=True) # Создаем пациента в БД
|
await create_patient(telegram_id=user_id, terms_acceptance=True) # Создаем пациента в БД
|
||||||
except DatabaseError as e:
|
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(
|
await update.callback_query.edit_message_text(
|
||||||
text="❌ Произошла ошибка при создании вашей записи. Пожалуйста, попробуйте позже."
|
text="❌ Произошла ошибка при создании вашей записи. Пожалуйста, попробуйте позже."
|
||||||
)
|
)
|
||||||
@ -167,20 +168,20 @@ async def enter_patient_phone(update: Update, context: ContextTypes.DEFAULT_TYPE
|
|||||||
if patient:
|
if patient:
|
||||||
has_phone = await is_user_has_phone(user_id)
|
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':
|
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:
|
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(
|
await update.callback_query.message.reply_text(
|
||||||
text="Пожалуйста, введите ваш номер мобильного телефона для записи на консультацию:\n"
|
text="Пожалуйста, введите ваш номер мобильного телефона для записи на консультацию:\n"
|
||||||
"Без знака +, вида 79991112233"
|
"Без знака +, вида 79991112233"
|
||||||
)
|
)
|
||||||
return ENTER_PATIENT_PHONE
|
return ENTER_PATIENT_PHONE
|
||||||
else:
|
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(
|
await update.callback_query.edit_message_text(
|
||||||
text="Введите серийный номер врача, к которому вы хотите записаться на консультацию:",
|
text="Введите серийный номер врача, к которому вы хотите записаться на консультацию:",
|
||||||
parse_mode="Markdown"
|
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)
|
# 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):
|
if not is_phone_correct(phone=phone):
|
||||||
keyboard = [
|
keyboard = [
|
||||||
[
|
[
|
||||||
@ -213,7 +214,7 @@ async def receive_patient_phone(update: Update, context: ContextTypes.DEFAULT_TY
|
|||||||
)
|
)
|
||||||
return ERROR_PHONE_NUMBER
|
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
|
context.user_data['phone'] = phone
|
||||||
|
|
||||||
keyboard = [
|
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):
|
if not await is_user_has_phone(user_id):
|
||||||
patient_phone = context.user_data['phone']
|
patient_phone = context.user_data['phone']
|
||||||
await update_patient_phone(telegram_id=user_id, phone=patient_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(
|
await update.message.reply_text(
|
||||||
text=f"Вы ввели серийный номер врача: {doctor_number}\n"
|
text=f"Вы ввели серийный номер врача: {doctor_number}\n"
|
||||||
@ -252,7 +253,7 @@ async def receive_doctor_number(update: Update, context: ContextTypes.DEFAULT_TY
|
|||||||
parse_mode="Markdown"
|
parse_mode="Markdown"
|
||||||
)
|
)
|
||||||
else:
|
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(
|
await update.effective_message.reply_text(
|
||||||
text="Введите дату и время консультации в формате ДД.ММ.ГГ ЧЧ:ММ, например, 01.01.23 12:00.",
|
text="Введите дату и время консультации в формате ДД.ММ.ГГ ЧЧ:ММ, например, 01.01.23 12:00.",
|
||||||
parse_mode="Markdown"
|
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)
|
patient = await get_patient_by_telegram_id(user_id)
|
||||||
doctor = await get_doctor_by_code(context.user_data['doctor_number'])
|
doctor = await get_doctor_by_code(context.user_data['doctor_number'])
|
||||||
except DatabaseError as e:
|
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(
|
await update.callback_query.message.reply_text(
|
||||||
"❌ Произошла ошибка при обработке вашего запроса. Пожалуйста, попробуйте позже."
|
"❌ Произошла ошибка при обработке вашего запроса. Пожалуйста, попробуйте позже."
|
||||||
)
|
)
|
||||||
@ -316,7 +317,7 @@ async def pay_consultation(update: Update, context: ContextTypes.DEFAULT_TYPE) -
|
|||||||
doctor=doctor
|
doctor=doctor
|
||||||
)
|
)
|
||||||
except DatabaseError as e:
|
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(
|
await update.callback_query.message.reply_text(
|
||||||
"❌ Произошла ошибка при создании записи на консультацию. Пожалуйста, попробуйте позже."
|
"❌ Произошла ошибка при создании записи на консультацию. Пожалуйста, попробуйте позже."
|
||||||
)
|
)
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user