Как можно сделать, чтобы ваше собственное исключение передавалось в лог?

Для передачи собственного исключения в лог, нужно:
  1. Создать класс исключения, наследуя его от `Exception`.
  2. В блоке `except` перехватить исключение.
  3. Использовать модуль `logging` для записи информации об исключении в лог. Можно использовать `logging.exception()` (запишет сообщение и traceback) или `logging.error(..., exc_info=True)` (тоже запишет traceback).
Пример:

import logging

logging.basicConfig(level=logging.ERROR)

class MyCustomError(Exception):
    pass

try:
    # Код, который может вызвать исключение
    raise MyCustomError("Произошла ошибка!")
except MyCustomError as e:
    logging.exception(e) # или logging.error("Ошибка!", exc_info=True)
  

Для того, чтобы собственное исключение передавалось в лог, нужно сделать несколько вещей:

  1. Определить собственное исключение: Создайте класс исключения, наследующийся от `Exception` или его подклассов (например, `ValueError`, `TypeError`). Это позволит вам выделить конкретную ситуацию, которую вы хотите логировать.
    
    class MyCustomException(Exception):
        def __init__(self, message, details=None):
            super().__init__(message)
            self.details = details
    
        def __str__(self): # Переопределяем __str__ для более информативного логирования
            base_message = super().__str__()
            if self.details:
                return f"{base_message} (Details: {self.details})"
            return base_message
          
  2. Настроить логирование: Используйте модуль `logging` для настройки логирования. Вам потребуется создать логгер и настроить обработчики (handlers) для записи логов в файл, консоль или другое место.
    
    import logging
    
    # Настройка логгера
    logger = logging.getLogger(__name__)
    logger.setLevel(logging.ERROR) # Устанавливаем минимальный уровень логирования
    
    # Создаем обработчик для записи в файл (или в консоль, или куда угодно)
    file_handler = logging.FileHandler('my_app.log')
    file_handler.setLevel(logging.ERROR)
    
    # Создаем форматтер для логов (определяет формат записи)
    formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')
    file_handler.setFormatter(formatter)
    
    # Добавляем обработчик к логгеру
    logger.addHandler(file_handler)
    
    # Пример с записью в консоль:
    # console_handler = logging.StreamHandler()
    # console_handler.setLevel(logging.ERROR) # можно задать другой уровень для консоли
    # console_handler.setFormatter(formatter)
    # logger.addHandler(console_handler)
          
  3. Перехватывать исключения и логировать их: Используйте блоки `try...except` для перехвата исключений. Внутри блока `except` используйте `logger.exception()` или `logger.error()` для записи исключения в лог. `logger.exception()` автоматически включает трассировку стека (stack trace), что очень полезно для отладки.
    
    def my_function(value):
        try:
            if value < 0:
                raise MyCustomException("Value must be non-negative", details={"value": value})
            result = 10 / value # Можем спровоцировать ZeroDivisionError
            return result
        except MyCustomException as e:
            logger.exception("Caught MyCustomException:") # Записывает исключение с трассировкой
            # Дополнительная обработка исключения (например, graceful shutdown)
        except ZeroDivisionError as e:
             logger.exception("Caught ZeroDivisionError:")
             # Альтернатива: logger.error(f"ZeroDivisionError: {e}", exc_info=True) # exc_info=True тоже добавляет трассировку
        except Exception as e: # Ловим все остальные исключения.  Важно, чтобы это был последний except
            logger.exception("An unexpected error occurred:") # Логируем любое другое исключение
        finally:
            #  Код, который всегда выполняется (например, освобождение ресурсов)
            pass
    
    
    # Пример использования
    my_function(-5)
    my_function(0)
    my_function(5)
    
    
          
  4. Дополнительные советы:
    • Используйте осмысленные сообщения в исключениях и в логах.
    • Включайте в логи достаточно информации для диагностики проблемы (например, значения переменных, контекст выполнения).
    • Рассмотрите возможность использования контекстного менеджера (`with`) для автоматической очистки ресурсов и логирования начала и конца выполнения важных операций.
    • Для более сложной конфигурации логирования, можно использовать файлы конфигурации (например, в формате YAML или JSON).
    • Устанавливайте разные уровни логирования (DEBUG, INFO, WARNING, ERROR, CRITICAL) в зависимости от важности сообщения. Это позволяет фильтровать логи при необходимости.
0