2008-09-17 2 views
5

У меня есть многоуровневое приложение на Java, которое имеет многопользовательский уровень доступа к данным, который вызывается из разных точек. Один вызов этого слоя может вызвать несколько потоков для параллелизации запросов к БД.Ведение журнала в многопоточных приложениях

Что я ищу - это инструмент ведения журнала, который позволит мне определить «действия», которые состоят из разных потоков. Следовательно, тот же метод на уровне доступа к данным должен регистрировать разные выходы в зависимости от вызывающего. Важное значение имеет также возможность группировки различных выходов для суммирования общей стоимости операции.

Хотя приложение находится на Java, язык не является ограничением; мне нужны руководящие принципы проектирования, чтобы в конечном итоге реализовать его. В настоящее время мы используем log4j, но не можем получить от этого поведение.

ответ

4

Вы также должны взглянуть на nested diagnostic context особенности log4j. Нажатие разных контекстов в журнал для разных абонентов может сделать трюк для вас.

+0

Очень хороший, спасибо! – 2008-09-17 13:56:33

+0

Согласно документации, NDC присоединяются к текущему потоку, поэтому я не думаю, что это вам поможет. В основном это оболочка поверх поточно-локального хранилища. – 2008-09-17 14:00:11

0

В Java5 (и позже), вы можете позвонить

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

Проверьте трассировки стека на любой глубине вы хотите, и войти соответственно.

В Java 1.4 вы можете получить ту же информацию с

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

Я хочу избежать вызовов в трассировку стека, так как я хочу, чтобы регистрация была как можно менее инвазивной, и я прочитал, что доступ к трассировке стека очень дорог. Спасибо за ответ! – 2008-09-17 13:35:29

4

Вы должны иметь возможность передавать регистратор, поэтому вы создаете регистратор на основе некоторого «общего» для данных задачи - то есть имени пользователя и т. Д. Затем передайте этот регистратор в качестве параметра ко всем методам, которые вам нужны. Таким образом, вы сможете устанавливать различные фильтры и/или правила в файле конфигурации log4j. Или очистить выходной файл на основе имени регистратора.

EDIT: Также проверьте классы MDC и NDC в log4j. Вы можете добавить туда контекстные данные.

0

Вам нужно будет передать некоторую структуру на уровень доступа к данным, который идентифицирует текущую «активность». Возможно, у вас уже есть класс «Activity», который имеет смысл, вы можете использовать экземпляр Logger как Sunny suggested, или вы можете использовать третью структуру для отслеживания контекста активности.

В любом случае, поскольку ваше «действие» обрабатывается несколькими потоками, вы не можете использовать поточно-локальное хранилище для отслеживания текущей «активности», как и большинство других текущих ответов. Вам нужно будет передать его явно.

Я хотел бы предложить сделать небольшой фасад на вершине log4j, который расширяет интерфейс с методами, как

void debug(Activity activity, String message); 

и прохождение активности-контекста в этом от уровня доступа к данным.

Вам нужно будет внести некоторые изменения в уровень доступа к данным, чтобы вы могли передать ему текущую активность, но как лучше всего это сделать сильно зависит от текущего интерфейса. Если вы используете шаблон Workspace, вам просто нужно добавить метод setActivity() в классе Workspace, но для другого шаблона интерфейса вам может потребоваться добавить параметр Activity ко всем методам.

Если вы по какой-либо причине не можете или не захотите изменить уровень доступа к данным, вы можете, естественно, сохранить контекст активности в потоковом локальном хранилище перед вызовом уровня доступа к данным и получить его непосредственно перед тем, потоки или включение заданий на уровне доступа к данным. Это приемлемое решение, но немного опасно передавать информацию таким образом.

2

В одном из моих (сетевых) приложений я использую журнал регистрации ThreadLocal, который фиксирует информацию о регистрации в StringBuilder. Объект регистратора инициализируется в методе службы HttpServlet #, если установлен параметр трассировки (если он не установлен, существует очень быстрый нулевой регистратор). Полученный результат либо выгружается как комментарий HTML на запрашивающую страницу, либо записывается в файл журнала в одном сегменте.

Смежные вопросы