En nuestro software, utilizamos ampliamente MDC para rastrear cosas como ID de sesión y nombres de usuario para solicitudes web. Esto funciona bien mientras se ejecuta en el hilo original. Sin embargo, hay muchas cosas que deben procesarse en segundo plano. Para eso utilizamos las clases java.concurrent.ThreadPoolExecutor
y java.util.Timer
junto con algunos servicios de ejecución asíncrona auto-enrollados. Todos estos servicios administran su propio grupo de subprocesos.
Esto es lo que dice el manual de Logback sobre el uso de MDC en dicho entorno:
Los subprocesos de trabajo no siempre pueden heredar una copia del contexto de diagnóstico asignado del subproceso inicial. Este es el caso cuando se usa java.util.concurrent.Executors para la gestión de subprocesos. Por ejemplo, el método newCachedThreadPool crea un ThreadPoolExecutor y, al igual que otros códigos de agrupación de subprocesos, tiene una intrincada lógica de creación de subprocesos.
En tales casos, se recomienda invocar MDC.getCopyOfContextMap () en el subproceso original (maestro) antes de enviar una tarea al ejecutor. Cuando se ejecuta la tarea, como su primera acción, debe invocar MDC.setContextMapValues () para asociar la copia almacenada de los valores originales de MDC con el nuevo subproceso administrado por el Ejecutor.
Esto estaría bien, pero es muy fácil olvidar agregar esas llamadas, y no hay una manera fácil de reconocer el problema hasta que sea demasiado tarde. El único signo con Log4j es que te falta información de MDC en los registros, y con Logback obtienes información de MDC obsoleta (ya que el subproceso en la banda de rodadura hereda su MDC de la primera tarea que se ejecutó). Ambos son problemas serios en un sistema de producción.
No veo nuestra situación especial de ninguna manera, sin embargo, no pude encontrar mucho sobre este problema en la web. Aparentemente, esto no es algo con lo que muchas personas se topan, por lo que debe haber una forma de evitarlo. ¿Qué estamos haciendo mal aquí?