Gymterview
middle

Что такое MDC (Mapped Diagnostic Context)?

MDC (Mapped Diagnostic Context) — механизм SLF4J/Logback для привязки контекстных данных к текущему потоку. Все лог-записи в рамках потока автоматически обогащаются данными из MDC.

Аналогия из жизни: MDC — это как бейдж посетителя в бизнес-центре. Пока бейдж надет, каждая камера на каждом этаже автоматически идентифицирует человека. Не нужно представляться у каждой двери.

Основное применение — correlation ID

Все лог-записи одного HTTP-запроса связываются единым идентификатором:

Фильтр для установки requestId в MDC
@Component
public class RequestFilter implements Filter {

    @Override
    public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain)
            throws IOException, ServletException {
        String requestId = ((HttpServletRequest) req).getHeader("X-Request-ID");
        if (requestId == null) {
            requestId = UUID.randomUUID().toString();
        }
        MDC.put("requestId", requestId);
        try {
            chain.doFilter(req, resp);
        } finally {
            MDC.clear(); // ОБЯЗАТЕЛЬНО очистить!
        }
    }
}

Конфигурация Logback для вывода MDC

Пример
<pattern>%d{ISO8601} [%thread] [%X{requestId}] %-5level %logger{36} - %msg%n</pattern>
<!-- %X{requestId} — подставляет значение из MDC -->

Результат в логах

Пример
2026-04-22 10:15:32.456 [http-nio-8080-exec-1] [a1b2c3d4] INFO  OrderService - Создание заказа
2026-04-22 10:15:32.789 [http-nio-8080-exec-1] [a1b2c3d4] INFO  PaymentService - Оплата обработана
2026-04-22 10:15:33.012 [http-nio-8080-exec-1] [a1b2c3d4] INFO  NotificationService - Уведомление отправлено

Все три записи связаны одним requestId — можно отследить весь путь запроса через систему.

Как работает MDC внутри

MDC основан на ThreadLocal — каждый поток хранит свою копию контекстных данных. Это означает:

Сценарий Поведение MDC Решение
Синхронный код Работает автоматически -
@Async методы Новый поток не наследует MDC TaskDecorator для копирования
Reactive (WebFlux) ThreadLocal не работает Reactor Context
Virtual Threads Работает, но при миллионах потоков расходует память Рассмотрите ScopedValue

Частые ошибки

  • Забыть MDC.clear() в finally — утечка контекста между запросами в пуле потоков (thread reuse)
  • MDC в @Async методах — новый поток не наследует MDC; нужен TaskDecorator для копирования
  • MDC с Virtual Threads — при миллионах потоков MDC (на основе ThreadLocal) потребляет значительную память

Как используется в 2026

  • MDC + correlation ID — стандартный паттерн для tracing в микросервисах
  • Micrometer Tracing (Spring Boot 3.x) автоматически пробрасывает traceId/spanId в MDC
  • В реактивном стеке (WebFlux) вместо MDC используется Reactor Context

На собеседовании: главное — объяснить связку MDC + ThreadLocal + обязательная очистка. Частая ошибка кандидатов — не упомянуть проблему с асинхронным кодом, где MDC не передаётся автоматически.