Разбор многострочных журналов с использованием pyspark с регулярным выражением - PullRequest
0 голосов
/ 16 апреля 2020

Я борюсь с pyspark, чтобы разделить лог-файл на фрейм данных, который может содержать многострочные события. С этими событиями мне нужна помощь.

Файл журнала имеет формат

2020-04-03T14:12:24,368 DEBUG [main] blabla bla bla bla
2020-04-03T14:12:24,371 DEBUG [main] bla bla bla bla 
2020-04-03T14:12:24,348 DEBUG [Thread-2] multiline log line bla bla 
bla bla bla
bla bla
    blablabla
2020-04-03T14:12:24,377 DEBUG [main] blabla bla bla bla

Чтобы разделить одну строку на группы, я могу просто использовать

log_pattern = r'(\d*-\d*-\d*)T(\d*:\d*:\d*,\d*)[ ]{1,}(DEBUG|INFO|WARN|FATAL|ERROR|TRACE)[ ]{1,}(\[.*\])[ ]{1,}(.*)'
logs_df = base_df.select(regexp_extract('value', log_pattern, 1).alias('date'),
                         regexp_extract('value', log_pattern, 2).alias('timestamp'),
                         regexp_extract('value', log_pattern, 3).alias('log_level'),
                         regexp_extract('value', log_pattern, 4).alias('application'),
                         regexp_extract('value', log_pattern, 5).alias('log_content'))
logs_df.show(10, truncate=True)

Вывод:

+----------+------------+---------+-----------+--------------------+
|      date|   timestamp|log_level|application|         log_content|
+----------+------------+---------+-----------+--------------------+
|2020-04-08|00:35:12,014|     INFO|     [main]|Log4J2Helper:68 -...|
|2020-04-08|00:35:12,014|     INFO|     [main]|Log4J2Helper:69 -...|
....

Я хочу, чтобы log_content содержал многострочное событие журнала. Тем не менее, я не понимаю, как я должен быть в состоянии разделить строки в отношении многострочных комментариев. Я попытался разделить, regexp lookahead, но, похоже, не понял это правильно.

Кажется, у spark.read.tex есть опция пользовательского разделителя новой строки, но он не может принимать регулярное выражение.

Сначала я подумал о парсинге с использованием модуля re, но, поскольку файлы журнала имеют размер в гигабайт, я, вероятно, столкнулся с проблемами памяти и обработки.

Может кто-нибудь подсказать мне, как мне обращаться с этими большими многострочными лог-файлами?

1 Ответ

1 голос
/ 16 апреля 2020

Вы можете захватить все следующие строки, которые не начинаются, например, с 1 или более цифр и дефиса, используя отрицательный прогноз в последней группе (.*(?:\r?\n(?!\d+-).*)*)

Обратите внимание, что если вы используете \d*-\d*-\d*, вы можете также возможно совпадение --, так как квантификатор * соответствует 0 или более раз.

Эта часть \[.*\] может быть записана с использованием отрицательного класса символов \[[^][]*\], чтобы предотвратить совпадение и сделать его немного более производительным .

(\d+-\d+-\d+)T(\d+:\d+:\d+,\d+)[ ]+(DEBUG|INFO|WARN|FATAL|ERROR|TRACE)[ ]+(\[[^][]*\])[ ]+(.*(?:\r?\n(?!\d+-).*)*)

Regex demo

...