Практические решения для логирования
Комплексная стратегия логирования
Разработка надежной стратегии логирования включает в себя множество компонентов и аспектов, чтобы обеспечить эффективный мониторинг и отладку приложений.
Централизованная настройка логирования
import logging
import logging.config
import yaml
def setup_logging(config_path='logging.yaml'):
"""
Configure logging from YAML configuration file
"""
try:
with open(config_path, 'rt') as f:
config = yaml.safe_load(f.read())
logging.config.dictConfig(config)
except Exception as e:
print(f"Error loading logging configuration: {e}")
logging.basicConfig(level=logging.INFO)
Пример настройки логирования (YAML)
version: 1
formatters:
standard:
format: "%(asctime)s - %(name)s - %(levelname)s - %(message)s"
handlers:
console:
class: logging.StreamHandler
level: INFO
formatter: standard
file:
class: logging.handlers.RotatingFileHandler
level: DEBUG
formatter: standard
filename: app.log
maxBytes: 10485760
backupCount: 5
loggers:
"":
handlers: [console, file]
level: DEBUG
Сравнение стратегий логирования
Стратегия |
Преимущества |
Недостатки |
Лучше всего подходит для |
Логирование в консоль |
Простота, мгновенная обратная связь |
Ограниченная сохраняемость |
Разработка |
Логирование в файл |
Постоянные записи |
Затраты на производительность |
Малые и средние приложения |
Централизованное логирование |
Масштабируемость, агрегированные логи |
Сложная настройка |
Распределенные системы |
Декоратор контекстного логирования
import logging
import functools
import contextvars
## Create a context variable for tracking request ID
request_id = contextvars.ContextVar('request_id', default='unknown')
def log_with_context(logger=None):
"""
Decorator to add contextual information to logs
"""
if logger is None:
logger = logging.getLogger(__name__)
def decorator(func):
@functools.wraps(func)
def wrapper(*args, **kwargs):
extra = {
'request_id': request_id.get()
}
try:
logger.info(
f"Executing {func.__name__}",
extra=extra
)
result = func(*args, **kwargs)
logger.info(
f"{func.__name__} completed successfully",
extra=extra
)
return result
except Exception as e:
logger.exception(
f"Error in {func.__name__}",
extra=extra
)
raise
return wrapper
return decorator
Рабочий процесс логирования в распределенных системах
graph TD
A[Client Request] --> B[Generate Request ID]
B --> C[Log Request Start]
C --> D[Service Processing]
D --> E[Log Intermediate Steps]
E --> F{Process Successful?}
F -->|Yes| G[Log Success]
F -->|No| H[Log Error]
G --> I[Return Response]
H --> I
Продвинутые техники логирования
-
Структурированное логирование
- Используйте форматы JSON или ключ-значение
- Позволяет более легкий разбор и анализ логов
-
Выборочное логирование (Log Sampling)
- Уменьшает объем логирования в приложениях с высокой нагрузкой
- Захватывает репрезентативные записи логов
-
Динамическое изменение уровня логирования
- Изменяйте уровни логирования во время выполнения
- Приспосабливайтесь к разным окружениям
Практическая реализация логирования
import logging
from pythonjsonlogger import jsonlogger
class CustomJsonFormatter(jsonlogger.JsonFormatter):
def process_log_record(self, log_record):
## Add custom fields or transform existing ones
log_record['service'] = 'LabEx Application'
return log_record
def configure_json_logging():
logger = logging.getLogger()
json_handler = logging.StreamHandler()
formatter = CustomJsonFormatter(
'%(asctime)s %(levelname)s %(message)s %(request_id)s'
)
json_handler.setFormatter(formatter)
logger.addHandler(json_handler)
Лучшие практики
- Используйте структурированное логирование
- Реализуйте ротацию логов
- Включайте контекстную информацию
- Балансируйте между полнотой и производительностью
- Используйте соответствующие уровни логирования
- Защищайте конфиденциальную информацию
Реализуя эти практические решения для логирования, разработчики могут создавать более наблюдаемые и поддерживаемые приложения, используя рекомендованные LabEx подходы.