# 📋 Логирование ## Стек технологий | Компонент | Технология | |-----------|------------| | Фасад | SLF4J (`org.slf4j.Logger`) | | Реализация | Logback (поставляется с `spring-boot-starter-web`) | | Конфигурация | Стандартная Spring Boot (без кастомного `logback.xml`) | | Экспорт (прод) | OpenTelemetry Java Agent → OTLP → SigNoz | | Контекст тенанта | SLF4J MDC (`tenant.id`) | --- ## Архитектура ```mermaid graph LR Code["Java-код
log.info(...)"] --> SLF4J["SLF4J API"] SLF4J --> Logback["Logback"] Logback -->|"Локальная разработка"| Console["stdout / stderr"] Logback -->|"Продакшн"| OTelAgent["OTel Java Agent
(Logback Appender)"] OTelAgent -->|"OTLP HTTP"| SigNoz["SigNoz"] ``` ### Локальная разработка Логи выводятся в `stdout` контейнера в стандартном формате Spring Boot: ``` 2026-03-22 12:00:00.123 INFO 1 --- [main] c.m.app.config.DataInitializer : Initializing databases for 1 tenant(s)... ``` Просмотр логов: ```bash docker compose logs -f backend ``` ### Продакшн (Kubernetes) OpenTelemetry Java Agent подключается как `-javaagent` в [Dockerfile](file:///mnt/HDD/magistr/magistr/backend/Dockerfile) и автоматически перехватывает логи Logback, экспортируя их в SigNoz по OTLP. ```dockerfile ENTRYPOINT ["java", "-javaagent:opentelemetry-javaagent.jar", "-jar", "app.jar"] ``` Конфигурация агента задаётся через переменные окружения в [backend.yaml](file:///mnt/HDD/magistr/k8s/backend.yaml): | Переменная | Значение | Назначение | |------------|----------|------------| | `OTEL_EXPORTER_OTLP_ENDPOINT` | `http://192.168.1.100:4318` | Адрес SigNoz Collector | | `OTEL_SERVICE_NAME` | `magistr-backend` | Имя сервиса в SigNoz | | `OTEL_RESOURCE_ATTRIBUTES` | `deployment.environment=default` | Окружение | | `OTEL_LOGS_EXPORTER` | `otlp` | Экспорт логов через OTLP | | `OTEL_METRICS_EXPORTER` | `otlp` | Экспорт метрик через OTLP | | `OTEL_TRACES_EXPORTER` | `otlp` | Экспорт трейсов через OTLP | | `OTEL_INSTRUMENTATION_LOGBACK_APPENDER_EXPERIMENTAL_CAPTURE_MDC_ATTRIBUTES` | `tenant.id` | Захват MDC-атрибута в логи | > [!NOTE] > В локальной разработке OpenTelemetry Agent также встроен в Docker-образ, но без переменных `OTEL_*` он работает в режиме noop — логи идут только в stdout. --- ## Мультитенантный контекст (MDC) Каждый HTTP-запрос обогащается tenant ID через [TenantInterceptor](file:///mnt/HDD/magistr/magistr/backend/src/main/java/com/magistr/app/config/tenant/TenantInterceptor.java): ```java // preHandle — при входе запроса MDC.put("tenant.id", tenant); Span.current().setAttribute("tenant.id", tenant); // afterCompletion — после завершения MDC.remove("tenant.id"); ``` Это позволяет: - Фильтровать логи по тенанту в SigNoz - Коррелировать логи с трейсами через Span-атрибуты - Идентифицировать, к какому университету относится каждая запись --- ## Использование в коде ### Классы с логированием | Класс | Уровни | Что логируется | |-------|--------|----------------| | `TenantInterceptor` | DEBUG, WARN | Резолвинг тенанта, неизвестный тенант (404) | | `TenantDataSourceConfig` | INFO, WARN, ERROR | Загрузка тенантов, fallback на H2 | | `TenantRoutingDataSource` | INFO, WARN | Добавление/удаление тенантов, тест соединения | | `TenantConfigWatcher` | INFO, ERROR, WARN | Изменения ConfigMap, Flyway миграции | | `ConfigMapUpdater` | INFO, WARN, ERROR | Обновление ConfigMap в K8s | | `DataInitializer` | INFO | Инициализация БД при старте | | `LessonsController` | INFO, DEBUG, ERROR | CRUD-операции с занятиями, валидация | ### Паттерн использования ```java import org.slf4j.Logger; import org.slf4j.LoggerFactory; public class MyClass { private static final Logger log = LoggerFactory.getLogger(MyClass.class); public void doSomething() { log.info("Операция выполнена: param={}", value); log.error("Ошибка: {}", e.getMessage(), e); // со стектрейсом } } ``` ### Рекомендации по уровням | Уровень | Когда использовать | |---------|-------------------| | `ERROR` | Необработанные ошибки, сбои подключения к БД, провалы миграций | | `WARN` | Неизвестный тенант, нет конфигурации, fallback-сценарии | | `INFO` | Успешные операции, CRUD-действия, старт/стоп компонентов | | `DEBUG` | Детали резолвинга тенанта, ping-запросы | --- ## Настройка уровня логирования В [application.properties](file:///mnt/HDD/magistr/magistr/backend/src/main/resources/application.properties) (по умолчанию закомментировано): ```properties # Включить DEBUG для всего приложения #logging.level.root=DEBUG # Только для пакета приложения logging.level.com.magistr.app=DEBUG # Только для конкретного класса logging.level.com.magistr.app.config.tenant.TenantInterceptor=DEBUG ``` Также можно задавать через переменные окружения: ```bash LOGGING_LEVEL_ROOT=DEBUG LOGGING_LEVEL_COM_MAGISTR_APP=DEBUG ``` --- ## Просмотр логов ### Локально (Docker Compose) ```bash # Все логи backend docker compose logs -f backend # Фильтрация по ключевому слову docker compose logs -f backend | grep "tenant" ``` ### Продакшн (SigNoz) Логи доступны в веб-интерфейсе SigNoz → раздел **Logs**: - Фильтрация по `service.name = magistr-backend` - Фильтрация по `tenant.id` (из MDC) - Корреляция с трейсами через общий `trace_id`