Я ответил на аналогичный вопрос здесь , но я адаптирую этот ответ к вашему вопросу.
Мы используем requestID для этой цели - присваиваем идентификатор запроса каждому входящему (HTTP) запросу в самом начале обработки (в фильтре), а затем регистрируем его в каждой строке журнала, чтобы вы могли легко сгенерируйте эти журналы позже по этому идентификатору и найдите все соответствующие строки.
Если вы считаете, что добавлять этот идентификатор в каждый оператор журнала очень утомительно, значит, вы не одиноки - рамки ведения журналов Java сделали его прозрачным с помощью Mapped Diagnostic Context (MDC) (в по крайней мере log4j и logback имеют это).
RequestID может также работать как удобный ссылочный номер, чтобы выкладываться в случае ошибок (как вы уже предлагали). Однако, как прокомментировали другие, не стоит загружать эти данные в базу данных - лучше использовать файловую систему. Или самый простой подход - просто использовать requestID - тогда вам не нужно делать ничего особенного в момент возникновения ошибки. Это просто поможет вам найти правильный файл журнала и выполнить поиск внутри этого файла.
Как будет выглядеть один requestID?
Мы используем следующую схему:
:. 1022 *
In состоит из следующих переменных:
- instanceName уникально идентифицирует конкретную JVM в конкретной среде развертывания /.
- currentTimeInMillis не требует пояснений. Мы решили представить его в удобочитаемом формате «yyyyMMddHHmmssSSS», поэтому из него легко прочитать время начала запроса (будьте осторожны: SimpleDateFormat не является потокобезопасным, поэтому вам нужно либо синхронизировать его, либо создавать новый при каждом запросе). ).
- counter - это счетчик запросов в эту конкретную миллисекунду - в редких случаях вам может потребоваться сгенерировать более одного идентификатора запроса за одну миллисекунду
Как видите, формат идентификатора был настроен таким образом, что комбинация currentTimeInMillis.counter гарантированно уникальна в конкретной JVM, а весь идентификатор гарантированно будет глобально уникальным (хорошо не в истинном смысле «глобальный», но он достаточно глобален для наших целей), без необходимости задействовать базу данных или какой-либо другой центральный узел. Кроме того, использование переменной instanceName дает вам возможность ограничить количество файлов журналов, которые вам позже понадобятся для поиска этого запроса.
Тогда, последний вопрос: «это хорошо и просто в решении с одной JVM, но как вы масштабируете это для нескольких JVM, взаимодействующих по некоторому сетевому протоколу?»
Поскольку мы используем Spring Remoting для целей удаленного взаимодействия, мы реализовали пользовательскую RemoteInvocationFactory (которая берет идентификатор запроса из контекста и сохраняет его в Атрибуты RemoteInvocation ) и RemoteInvocationExecutor (который берет идентификатор запроса из атрибутов и добавляет его в контекст диагностики в другой JVM).
Не уверен, как бы вы реализовали это с обычным RMI или другими методами удаленного взаимодействия.