Статьи

Поиск временного интервала в логах

вступление

Этот пост косвенно связан с моим мини-сериалом об анализе логов. Было бы здорово прочитать две основные части, чтобы лучше понять, о чем я говорю. Часть 1 , Часть 2 .

Этот пост описывает одну важную проблему, с которой я столкнулся при реализации подхода IDE.

Описание задания

Когда кто-то работает с журналами, обычно ему нужно исследовать только один интервал времени. Доступные журналы обычно охватывают дни, но интервал времени, который должен быть исследован, составляет 1-2 часа. Задача состоит в том, чтобы выбрать все записи журнала за этот интервал времени.

Основная запись журнала Regex

Чтобы выбрать запись журнала, нам нужно регулярное выражение, соответствующее любой записи журнала. Для простого формата log4j вроде

1
2018-08-10 11:00:56,234 DEBUG [Thread-1] package1.pkg2.Class1 Text Message

Я нашел следующее регулярное выражение:

1
TIME_REGEX((?!(TIME_REGEX)).*\r?\n)*

Это регулярное выражение соответствует как однострочным, так и многострочным записям журнала. Время может быть регулярным выражением

1
\d\d\d\d-\d\d-\d\d \d\d:\d\d:\d\d,\d\d\d

Поэтому, если кто-то хочет загрузить все журналы в текстовое окно, он может открыть файлы журнала один за другим и использовать Matcher.find () с этим регулярным выражением для получения всех записей журнала.

Это регулярное выражение основано на том факте, что шаблон регулярного выражения никогда не повторяется в теле сообщения журнала, что верно в 99% всех случаев.

Дата и время записи журнала

Для поиска определенного временного интервала и использования других функций имеет смысл извлечь информацию dtaetime из записи журнала. К счастью, эта задача была решена JDK с DateTimeFormatter. Достаточно указать формат для типа журнала и дату можно извлечь. Например, для записи журнала выше формат

1
yyyy-MM-dd HH:mm:ss,SSS

Как только мы можем извлечь информацию о дате и времени, мы можем указать интервал как значения даты и времени, а не строки в каком-то определенном формате.

Время поиска

Теперь, когда мы нашли способ выбрать любую запись журнала и извлечь из нее информацию о дате, путь вперед кажется ясным:

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

У этого подхода есть одна большая проблема:
время С 50 файлами журналов по 50 МБ каждый потребуется несколько часов, чтобы просканировать все их, чтобы найти 10 МБ записей в интервале.

Решение

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

1
2
2018-08-10 11:00:56,234 DEBUG [Thread-1] package1.pkg2.Class1 Text Message
2018-08-10 11:00:56,234 DEBUG [Thread-1] package1.pkg2.Class1 Msg 2

Или же

1
2
2018-08-10 11:00:56,234 DEBUG [Thread-1] package1.pkg2.Class1 Text Message
2018-08-10 11:00:56,278 DEBUG [Thread-1] package1.pkg2.Class1 Msg 2

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

Это означает, что если ни первая, ни последняя запись в файле не находятся в интервале, то все записи в файле не находятся в интервале, и этот файл можно отфильтровать. Регулярные выражения Java имеют специальные конструкции для поиска первой и последней записей.

Первая запись:

1
<b>\A</b>TIME_REGEX((?!(TIME_REGEX)).*\r?\n)*

Последняя запись:

1
TIME_REGEX((?!(TIME_REGEX)).*\r?\n)*<b>\Z</b>

\ A означает начало текста, \ Z означает конец текста. Вы можете найти более подробную информацию в javadocs для java.util.regex.Pattern.

Решение заключается в использовании специальной техники предварительного сканирования. Перед сканированием всего текста файла журнала найдите первую и последнюю записи и, если их нет в интервале, пропустите файл. Возможно, из 50 файлов 1-2 необходимо отсканировать.

Вывод

REAL использует эту технику для ускорения поиска для интервала даты и времени. Я обнаружил, что требуется приблизительно 5-10 секунд, чтобы решить, должен ли файл быть пропущен. Большую часть времени выполняет Matcher.find () для последней записи. Первая запись найдена намного быстрее. Я думаю, что можно ускорить его, выбрав последние 5 МБ из 50 МБ файла для поиска последней записи. Но даже в текущем состоянии это достаточно быстро.

Опубликовано на Java Code Geeks с разрешения Вадима Коркина, партнера нашей программы JCG . Смотреть оригинальную статью здесь: Поиск временного интервала в журналах

Мнения, высказанные участниками Java Code Geeks, являются их собственными.