2008-09-17 9 views
5

Tengo una aplicación estratificada en Java que tiene una capa de acceso a datos de múltiples hilos que se invoca desde diferentes puntos. Es probable que una sola llamada a esta capa genere varios hilos para paralelizar las solicitudes al DB.Actividades de registro en aplicaciones multiproceso

Lo que estoy buscando es una herramienta de registro que me permita definir "actividades" que están compuestas por varios hilos. Por lo tanto, el mismo método en la capa de acceso a datos debe registrar diferentes salidas dependiendo de quien llama. La capacidad de agrupar diferentes productos para resumir el costo total de una operación también es importante.

Aunque la aplicación está en Java, el idioma no es una restricción; lo que necesito son las pautas de diseño para implementarlo eventualmente. Actualmente estamos usando log4j, pero no podemos obtener este comportamiento.

Respuesta

4

También debería echar un vistazo a la función nested diagnostic context de log4j. Empujar diferentes contextos al registrador para diferentes personas que llaman puede ser el truco para usted.

+0

¡Muy bien, gracias! –

+0

Según la documentación, los NDC se conectan al hilo actual, por lo que no creo que eso lo ayude. Básicamente es solo una envoltura sobre el almacenamiento local de subprocesos. –

+1

Pero el NDC proporciona métodos para pasar el contexto actual a un subproceso secundario, que puede ser útil. –

0

En Java5 (y posterior) puede llamar

StackTraceElement[] stackTrace = Thread.currentThread().getStackTrace(); 

Inspeccionar el seguimiento de la pila a cualquier profundidad deseada y log en consecuencia.

En Java 1.4 se puede obtener la misma información con

StackTraceElement[] stackTrace = new Exception().getStackTrace(); 
+0

Quiero evitar las llamadas al seguimiento de la pila, ya que quiero que el registro sea lo menos invasivo posible, y he leído que acceder al seguimiento de la pila es muy caro. ¡Gracias por la respuesta! –

4

Debería poder pasar un registrador, por lo que crea un registrador basado en algunos datos "comunes" para la tarea, es decir, nombre de usuario, etc. Luego, pase este registrador como parámetro a todos los métodos que necesite. De esta forma, podrá establecer diferentes filtros y/o reglas en su archivo de configuración log4j. O para raspar el archivo de salida según el nombre del registrador.

EDITAR: También verifique las clases MDC y NDC en log4j. Puede agregar allí datos contextuales.

+0

Es bueno, pero no quiero modificar todas las interfaces. Estaba buscando algo que explotara más localidad de subprocesos. ¡Gracias! –

+0

¿Luego usa este enfoque en combinación con ThreadLocal? –

+0

Gracias por mencionar a MDC. Era justo lo que estaba buscando. – Knubo

0

Deberá pasar alguna estructura a la capa de acceso a datos que identifica la "actividad" actual. Es posible que ya tenga una clase de "Actividad" que tenga sentido, puede usar una instancia de registrador como Sunny suggested o puede utilizar una tercera estructura para realizar un seguimiento del contexto de actividad.

En cualquier caso, dado que su "actividad" se procesa a través de múltiples hilos, no puede usar thread-local-storage para realizar un seguimiento de la "actividad" actual, como sugieren la mayoría de las otras respuestas actuales. Necesitarás pasarlo explícitamente.

que sugeriría haciendo una pequeña fachada en la parte superior de log4j que se expande la interfaz con métodos como

void debug(Activity activity, String message); 

y pasando la actividad-contexto en esto desde la capa de acceso de datos.

Deberá modificar la capa de acceso a los datos para poder pasarle la actividad actual, pero la mejor manera de hacerlo depende en gran medida de la interfaz actual. Si usa el patrón de área de trabajo, puede que necesite agregar un método setActivity() en la clase Workspace-class, pero otro patrón de interfaz puede requerir que agregue un parámetro Activity a todos los métodos. Si por algún motivo no puede o no quiere cambiar la capa de acceso a datos, puede almacenar el contexto de actividad en el almacenamiento local de subprocesos antes de invocar la capa de acceso a datos y recuperarla justo antes de generar la subcapa hilos o enqueing los trabajos en la capa de acceso a datos. Esa es una solución factible, pero es un poco peligroso pasar información de esa manera.

2

En una de mis aplicaciones (web), utilizo un registrador ThreadLocal que captura información de registro en un StringBuilder. El objeto logger se inicializa en el método de servicio HttpServlet #, si se establece un parámetro de rastreo (si no está configurado, hay un registrador null muy rápido). El resultado resultante se descarga como un comentario HTML en la página solicitante o se escribe en un archivo de registro en un segmento.