JavaRush /Курси /Модуль 4: FastAPI /Логування подій та помилок у боті

Логування подій та помилок у боті

Модуль 4: FastAPI
Рівень 18 , Лекція 7
Відкрита

Тепер, коли наш бот активно взаємодіє з користувачами і, можливо, вже жартує, настав час додати важливий компонент — логування. Воно допоможе нам відстежувати поведінку бота, знаходити помилки і бути справжнім "Шерлоком Холмсом" свого коду.

Уяви, ти розробив чудового Telegram-бота. Усе добре, але раптом якийсь користувач каже, що бот надіслав йому дивну, безглузду відповідь. Без логів твої спроби знайти причину помилки будуть схожі на пошук голки в сіні. Логи — це твоя карта, яка допоможе зрозуміти, що сталося, де і чому.

Основні завдання логування:

  • Діагностика помилок: відстеження помилок і проблем у боті.
  • Моніторинг: отримання інформації про те, як бот працює в реальному часі.
  • Аналітика: розуміння, які команди і функції бота використовуються найчастіше.
  • Налагодження: усунення помилок під час розробки.

У Python стандартним інструментом для логування є модуль logging із стандартної бібліотеки. Хороша новина в тому, що він легко інтегрується в наші боти!


Вступ у Python Logging

Перед тим як застосовувати логування в нашому Telegram-боті, давай розберемо основи роботи з модулем logging.

Базовий приклад логування


import logging

# Налаштування базового логування
logging.basicConfig(level=logging.INFO)

# Приклади логування повідомлень
logging.debug("Це повідомлення для налагодження.")
logging.info("Це інформаційне повідомлення.")
logging.warning("Це попередження!")
logging.error("Сталася помилка!")
logging.critical("Критична помилка!")

Рівні логування

Логування передбачає поділ повідомлень за рівнями критичності:

  1. DEBUG: Детальна інформація, корисна для налагодження.
  2. INFO: Інформаційні повідомлення про нормальну роботу.
  3. WARNING: Попередження про потенційні проблеми.
  4. ERROR: Інформація про виниклу помилку.
  5. CRITICAL: Повідомлення про критичні помилки.

Коли ти встановлюєш рівень логування, наприклад, INFO, повідомлення рівнем нижче (наприклад, DEBUG) не будуть відображатися.


Налаштування логування в Telegram-боті

Крок 1: Імпортуємо і налаштовуємо logging

Давай додамо logging у нашого бота. Налаштуємо базове логування і будемо записувати події, такі як вхідні повідомлення, команди користувачів і помилки.


import logging
from telegram import Update
from telegram.ext import ApplicationBuilder, CommandHandler, MessageHandler, filters

# Налаштовуємо базовий конфіг для логування
logging.basicConfig(
    format="%(asctime)s - %(name)s - %(levelname)s - %(message)s",
    level=logging.INFO
)

# Отримуємо об'єкт логгера
logger = logging.getLogger(__name__)

# Обробники команд
async def start(update: Update, context):
    logger.info("Отримано команду /start від користувача %s", update.effective_user.username)
    await update.message.reply_text("Привіт! Я твій бот. Чим можу допомогти?")

async def help(update: Update, context):
    logger.info("Отримано команду /help від користувача %s", update.effective_user.username)
    await update.message.reply_text("Ось список доступних команд: /start, /help")

async def echo(update: Update, context):
    logger.info("Користувач %s сказав: '%s'", update.effective_user.username, update.message.text)
    await update.message.reply_text(update.message.text)

# Основний код додатку
if __name__ == '__main__':
    app = ApplicationBuilder().token("YOUR_TELEGRAM_BOT_TOKEN").build()

    app.add_handler(CommandHandler("start", start))
    app.add_handler(CommandHandler("help", help))
    app.add_handler(MessageHandler(filters.TEXT & ~filters.COMMAND, echo))

    logger.info("Бот запущено і готовий до роботи!")
    app.run_polling()
  • %(asctime)s: Час виконання (у форматі дати та часу).
  • %(name)s: Ім'я логгера.
  • %(levelname)s: Рівень логування (INFO, DEBUG тощо).
  • %(message)s: Саме повідомлення.

Крок 2: Логування помилок

Ми можемо додати обробник помилок у наш бота. Наприклад, щоб логувати винятки, які можуть виникати.


from telegram.error import TelegramError

# Обробник помилок
async def error_handler(update: object, context):
    logger.error("Сталася помилка: %s", context.error)

# Додаємо обробник помилок у додаток
app.add_error_handler(error_handler)

Тепер будь-які помилки, що виникли під час обробки запитів бота, будуть логуватися.


Логування у файли

Логування в консоль — це добре, але що якщо бот розгорнутий на сервері, і тобі потрібні логи для аналізу пізніше? Давай налаштуємо логування у файл.


import logging

# Налаштування логування у файл
logging.basicConfig(
    filename='bot.log',  # Ім'я файлу
    filemode='a',        # Режим запису (a - append, w - overwrite)
    format="%(asctime)s - %(name)s - %(levelname)s - %(message)s",
    level=logging.INFO
)

# Приклад логування
logging.info("Логування налаштовано для запису у файл.")

Тепер усі логи будуть зберігатися у файлі bot.log.


Логування з ротацією файлів

Якщо бот активно використовується, файл логів може вирости до неймовірних розмірів (а ніхто не хоче шукати потрібне повідомлення в мільйонах рядків). Для таких випадків корисно використовувати ротацію файлів.

Розглянемо приклад з використанням TimedRotatingFileHandler із модуля logging.


from logging.handlers import TimedRotatingFileHandler

# Створюємо обробник ротації логів
handler = TimedRotatingFileHandler("bot.log", when="midnight", interval=1)
handler.suffix = "%Y-%m-%d"

# Налаштовуємо формат логування
formatter = logging.Formatter("%(asctime)s - %(name)s - %(levelname)s - %(message)s")
handler.setFormatter(formatter)

# Додаємо обробник до логгера
logger.addHandler(handler)
logger.setLevel(logging.INFO)

logger.info("Лог з ротацією готовий!")

Тепер файл логів буде автоматично ділитися на нові файли кожен день.


Відстежування користувачів та їхніх помилок

Якщо бот виконує складні завдання (наприклад, працює з базою даних), логування допоможе зрозуміти, які операції викликають збої.


async def save_user_data(update: Update, context):
    try:
        user_id = update.effective_user.id
        logger.info("Збереження даних користувача %s", user_id)
        # Приклад роботи з базою даних
        # db.save(user_id, some_data)
    except Exception as e:
        logger.error("Помилка збереження даних користувача %s: %s", user_id, str(e))
        await update.message.reply_text("Сталася помилка. Спробуйте пізніше.")

Логування в асинхронних контекстах

FastAPI і асинхронна обробка повідомлень вимагають трохи уваги при роботі з логами. Щоб спростити роботу, можна використовувати бібліотеку aiologger.

Встановимо її:


pip install aiologger

І використаємо:


from aiologger import Logger

# Створюємо асинхронний логгер
async_logger = Logger.with_default_handlers()

# Приклад асинхронного логування
await async_logger.info("Це повідомлення буде логуватися асинхронно")

Тепер твоєму боту не страшні помилки: їх можна швидко виявити і виправити, аналізуючи логи. Ти став не тільки розробником, а й справжнім "детективом" у світі програмування.

Коментарі
ЩОБ ПОДИВИТИСЯ ВСІ КОМЕНТАРІ АБО ЗАЛИШИТИ КОМЕНТАР,
ПЕРЕЙДІТЬ В ПОВНУ ВЕРСІЮ