logging для записи информации об исключении, включая трассировку стека, в файл или другой источник данных. Это позволяет отслеживать возникновение и контекст ошибки.traceback.format_exc() позволяет получить отформатированную строку трассировки.Для регистрации ошибок, вызванных собственными исключениями в Python, используется несколько техник, позволяющих отслеживать, анализировать и исправлять проблемы в коде. Вот основные из них:
logging:
    logging - это стандартный модуль Python для гибкой и мощной регистрации событий, включая ошибки.  При возникновении собственного исключения можно записать информацию об ошибке в лог с использованием разных уровней (DEBUG, INFO, WARNING, ERROR, CRITICAL) в зависимости от серьезности.
import logging
logging.basicConfig(level=logging.ERROR, 
                    filename='my_app.log', 
                    format='%(asctime)s - %(name)s - %(levelname)s - %(message)s')
class MyCustomError(Exception):
    pass
def my_function(value):
    try:
        if value < 0:
            raise MyCustomError("Value must be non-negative")
        # ... остальной код
    except MyCustomError as e:
        logging.error(f"An error occurred: {e}", exc_info=True) # exc_info=True включает трассировку стека
        # Дополнительная обработка ошибки (например, отправка уведомления)
        # raise  # Переброс исключения, если это необходимо для дальнейшей обработки
Ключевые моменты:
logging позволяет определить куда будут записываться логи (файл, консоль, сетевой ресурс), какой уровень сообщений будет регистрироваться, и формат сообщения.exc_info=True включает в лог трассировку стека, что критически важно для отладки.raise) после логирования, если необходимо, чтобы ошибка обрабатывалась на более высоком уровне.Когда происходит исключение, Python автоматически генерирует трассировку стека, которая показывает последовательность вызовов функций, приведших к исключению.  Модули traceback и sys позволяют получать и обрабатывать эту информацию.
import traceback
import sys
class MyCustomError(Exception):
    pass
def my_function(value):
    try:
        if value < 0:
            raise MyCustomError("Value must be non-negative")
        # ... остальной код
    except MyCustomError as e:
        print("Exception occurred:")
        traceback.print_exc() # Печатает трассировку стека в стандартный поток ошибок
        # Или можно получить трассировку в виде строки:
        # exc_type, exc_value, exc_traceback = sys.exc_info()
        # traceback_details = traceback.format_exception(exc_type, exc_value, exc_traceback)
        # for line in traceback_details:
        #     print(line, end="")
Трассировку можно отправить в лог-файл или использовать для создания детального сообщения об ошибке.
Для больших и сложных приложений рекомендуется использовать внешние системы мониторинга, такие как Sentry, Rollbar, ELK stack (Elasticsearch, Logstash, Kibana), Prometheus + Grafana, которые позволяют централизованно собирать, анализировать и визуализировать логи и ошибки.
# Пример интеграции с Sentry (псевдокод):
# import sentry_sdk
# from sentry_sdk import capture_exception
# sentry_sdk.init(dsn="YOUR_SENTRY_DSN")
# class MyCustomError(Exception):
#     pass
# def my_function(value):
#     try:
#         if value < 0:
#             raise MyCustomError("Value must be non-negative")
#         # ... остальной код
#     except MyCustomError as e:
#         capture_exception(e)  # Отправляет исключение в Sentry
#         raise
Эти системы предоставляют мощные инструменты для фильтрации, поиска, группировки ошибок и уведомлений о новых или повторяющихся проблемах.
Помимо стандартной трассировки стека, важно включать в логи дополнительную контекстную информацию, которая поможет понять, что происходило в системе в момент возникновения ошибки. Это может быть:
import logging
class MyCustomError(Exception):
    def __init__(self, message, user_id=None, transaction_id=None):
        super().__init__(message)
        self.user_id = user_id
        self.transaction_id = transaction_id
def my_function(value, user_id, transaction_id):
    try:
        if value < 0:
            raise MyCustomError("Value must be non-negative", user_id=user_id, transaction_id=transaction_id)
        # ... остальной код
    except MyCustomError as e:
        logging.error(f"Error: {e}, User ID: {e.user_id}, Transaction ID: {e.transaction_id}", exc_info=True)
        raise
Передача контекстной информации в исключение и ее последующее логирование значительно упрощает отладку и анализ причин возникновения ошибок.
Правильное форматирование логов делает их более читабельными и удобными для анализа. Важно включать в лог-сообщения дату и время, уровень сообщения, имя модуля и функции, вызвавшей ошибку, и саму ошибку.
logging.basicConfig(level=logging.ERROR,
                    format='%(asctime)s - %(levelname)s - %(module)s.%(funcName)s:%(lineno)d - %(message)s')
Выбор конкретной техники зависит от масштаба и сложности приложения, а также от требований к отладке и мониторингу. Часто используется комбинация нескольких подходов для обеспечения наиболее полной и эффективной регистрации ошибок.