Ведение журнала действий в многопоточных приложениях

StackOverflow https://stackoverflow.com/questions/83117

  •  01-07-2019
  •  | 
  •  

Вопрос

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

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

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

Это было полезно?

Решение

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

Другие советы

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

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

В log4j вы можете записать имя потока с помощью шаблона "%t".Видишь макет шаблона log4j.

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

В Java5 (и более поздних версиях) вы можете вызвать

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

Проверьте трассировку стека на любую желаемую глубину и внесите ее в журнал соответствующим образом.

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

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

Я думаю, вы хотите связать объекты logger с потоками.Может помочь переменная ThreadLocal, содержащая экземпляр log4j logger для каждого потока:

http://java.sun.com/javase/6/docs/api/java/lang/ThreadLocal.html

Вам нужно будет передать некоторую структуру на уровень доступа к данным, которая идентифицирует текущую "активность".Возможно, у вас уже есть класс "Activity", который имеет смысл, вы могли бы использовать экземпляр Logger как Предложила Солнышко или вы могли бы использовать третью структуру для отслеживания контекста действия.

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

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

void debug(Activity activity, String message);

и передача контекста действия в это из уровня доступа к данным.

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

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

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top