لاگ‌هات رو بریز توی تلگرام

تصور کن:

* یک ارور Critical در اپلیکیشن شما اتفاق میفته.

* بلافاصله، یک نوتیفیکیشن با اموجی ‼️ روی گوشیت میاد.

چرا تلگرام؟

1. فوری و همیشه در دسترس: کیه که تلگرام رو روی گوشیش نداشته باشه؟

2. فرمت‌بندی عالی: می‌تونید پیام‌ها رو با Markdown خوشگل کنید، کدها رو متمایز کنید و با اموجی، سطح خطا رو مشخص کنید.

3. رایگان و بی‌دردسر: ساختن ربات تلگرام رایگانه و API اون بسیار ساده و قدرتمنده.

4. گروهی و تیمی: می‌تونید لاگ‌ها رو تو یه گروه تلگرامی بفرستید تا کل تیم فنی در لحظه از وقایع باخبر بشن.

ما با استفاده از کتابخانه استاندارد logging پایتون، یک Handler شخصی‌سازی شده می‌نویسیم که هر لاگ رو به یک پیام تلگرامی تبدیل می‌کنه.

import logging
import requests
from database import settings  # Assuming settings are read from here

# --- Settings ---
# Load settings like bot token and admin ID from a central settings module
config = settings.get_all()
LOG_LEVEL = logging.INFO  # Only send INFO level and higher logs
BOT_TOKEN = config.get('control_bot', {}).get('token')
ADMIN_ID = config.get('telegram', {}).get('admin_ids', [None])[0]
CHAT_ID = settings.get('logging.telegram_chat_id', ADMIN_ID)


class TelegramLogHandler(logging.Handler):
    """
    A custom logging handler that sends log records to a Telegram chat.
    """
    def __init__(self, token, chat_id):
        super().__init__()
        self.token = token
        self.chat_id = chat_id

    def emit(self, record):
        """
        Formats and sends the log record.
        This method is called by the logging framework.
        """
        if not self.token or not self.chat_id:
            return  # Do nothing if token or chat_id is not set

        log_entry = self.format(record)
        
        # Use a simple emoji prefix for different log levels
        if record.levelno >= logging.CRITICAL:
            prefix = "‼️ CRITICAL"
        elif record.levelno >= logging.ERROR:
            prefix = "❌ ERROR"
        elif record.levelno >= logging.WARNING:
            prefix = "⚠️ WARNING"
        else:
            prefix = "ℹ️ INFO"

        # Format the message with level, service name, and log content
        message = f"{prefix}\n**Service:** `{record.name}`\n**Message:** `{log_entry}`"
        
        url = f"https://api.telegram.org/bot{self.token}/sendMessage"
        payload = {
            'chat_id': self.chat_id,
            'text': message,
            'parse_mode': 'Markdown'
        }
        try:
            requests.post(url, data=payload, timeout=5)
        except requests.RequestException as e:
            # If sending the log to Telegram fails, print the error to the console
            print(f"Failed to send log to Telegram: {e}")


def setup_telegram_logging():
    """
    Sets up the custom Telegram handler for the root logger.
    Call this function once at the start of each service.
    """
    if CHAT_ID and BOT_TOKEN:
        # Get the root logger
        logger = logging.getLogger()

        # Create a handler and set its level
        telegram_handler = TelegramLogHandler(BOT_TOKEN, CHAT_ID)
        telegram_handler.setLevel(LOG_LEVEL)

        # Create a formatter and add it to the handler
        formatter = logging.Formatter('%(message)s')
        telegram_handler.setFormatter(formatter)

        # Add the handler to the root logger
        logger.addHandler(telegram_handler)
        logger.info("Telegram logging handler has been set up.")

چطور راه اندازی کنیم؟

1. ساخت ربات تلگرام: به BotFather در تلگرام پیام بدید، دستور /newbot رو بزنید و یک ربات بسازید.

3. فراخوانی در پروژه:

کافیست در ابتدای فایل اصلی اپلیکیشن خود (مثلاً main.py)، پکیج logging پایتون رو ایمپورت کنید و تابع setup_telegram_logging را فراخوانی کنید.

قدم بعدی چیه؟

* برای سرویس‌های مختلف، از CHAT_ID های متفاوت استفاده کنید.

* به پیام‌های خطا دکمه‌های شیشه‌ای (Inline Buttons) اضافه کنید؛ مثلاً دکمه "Restart Service" یا "View Full Traceback".

* سطح لاگ‌ها را بر اساس محیط (Development/Production) تغییر دهید.

* حواستون باشه تلگرام نباید تنها مکانی باشه که لاگ هاتون ذخیره میشه.