Fluent Bit — особенности использования multiline в плагине tail

Input plugin tail имеет возможность обрабатывать многострочные лог файлы. Достаточно создать PARSER, при помощи которого можно определить первую строку такого сообщения. Все вроде бы работает, но мне захотелось не просто разобрать сообщение по тегам, но и в отдельном теге сохранить всё исходное сообщение.

По идее регулярное выражение, используемое в парсере для лога openfire

2018.04.16 10:48:15 ERROR [pool-2-thread-171]: org.jivesoftware.openfire.filetransfer.proxy.ProxyConnectionManager - Error processing file transfer proxy connection
java.io.IOException: Only SOCKS5 supported
        at org.jivesoftware.openfire.filetransfer.proxy.ProxyConnectionManager.processConnection(ProxyConnectionManager.java:156) ~[xmppserver-4.3.2.jar:4.3.2]
        at org.jivesoftware.openfire.filetransfer.proxy.ProxyConnectionManager.access$200(ProxyConnectionManager.java:53) ~[xmppserver-4.3.2.jar:4.3.2]
        at org.jivesoftware.openfire.filetransfer.proxy.ProxyConnectionManager$1$1.run(ProxyConnectionManager.java:125) [xmppserver-4.3.2.jar:4.3.2]
        at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511) [?:1.8.0_202]
        at java.util.concurrent.FutureTask.run(FutureTask.java:266) [?:1.8.0_202]
        at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149) [?:1.8.0_202]
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624) [?:1.8.0_202]
        at java.lang.Thread.run(Thread.java:748) [?:1.8.0_202]

должно выглядеть как то так:

^(?<message>(?<time>\d{4}\.\d{2}\.\d{2} \d{2}:\d{2}:\d{2}) (?<loglevel>\w+) {1,2}(?<process>\[[^ ]*\]): .*)

Оказалось, что всё не так просто. Fluent bit находит первую строку, разбирает её, формирует теги. Вроде всё нормально.

Но остальные строки он тупо дописывает к последнему тегу регулярного выражения. И вместо того, что бы поместить их (как я ожидал) в тег message, он добавляет их к тегу process.

Поэтому, после обработки приходится «терять» теги time, loglevel и process используя следующее выражение вместо первого:

^(?<time>\d{4}\.\d{2}\.\d{2} \d{2}:\d{2}:\d{2}) (?<loglevel>\w+) {1,2}(?<process>\[[^ ]*\]): (?<message>.*)

Остальные строки многострочного лога будут добавляться к тегу message, но он не будет содержать время, loglevel и процесс.

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

2 thoughts on “Fluent Bit — особенности использования multiline в плагине tail

  1. Добрый день, можно увидеть полный конфиг fluent bit?
    Пытаюсь применить парсинг multiline логов, которые идут из докера в kubernetes. Проблема в том что первую строку он «достаёт» из json, а следующие добавляет в json формате.

    2019-09-26T15:01:38.746271Z\u0009info\u0009Envoy proxy is NOT ready: 3 errors occurred:\n
    {«log»:»\u0009* failed checking application ports. listeners=\»0.0.0.0:15090\»,\»10.110.53.109:42422\»,\»10.99.145.243:8087\»,\»10.99.23.150:443\»,\»10.99.23.150:15020\»,\»10.99.23.150:15032\»,\»10.96.0.1:443\»,\»10.96.0.10:9153\»,\»10.99.23.150:15029\»,\»10.99.23.150:15443\»,\»10.107.243.171:80\»,\»10.96.0.10:53\»,\»10.102.115.169:9898\»,\»10.102.88.236:443\»,\»10.111.40.1:443\»,\»10.108.28.219:15011\»,\»10.97.60.158:443\»,\»10.97.46.154:80\»,\»10.99.23.150:15030\»,\»10.99.23.150:15031\»,\»10.99.23.150:31400\»,\»10.109.121.102:5558\»,\»10.102.88.236:15443\»,\»0.0.0.0:8080\»,\»0.0.0.0:15014\»,\»0.0.0.0:15004\»,\»0.0.0.0:80\»,\»0.0.0.0:5555\»,\»0.0.0.0:15010\»,\»0.0.0.0:9091\»,\»0.0.0.0:5000\»,\»0.0.0.0:443\»,\»0.0.0.0:8060\»,\»0.0.0.0:9090\»,\»0.0.0.0:9901\»,\»0.0.0.0:15001\»\n»,»stream»:»stdout»,»time»:»2019-09-26T15:01:38.747526596Z»}
    {«log»:»\u0009* envoy missing listener for inbound application port: 9998\n»,»stream»:»stdout»,»time»:»2019-09-26T15:01:38.747553699Z»}
    {«log»:»\u0009* envoy missing listener for inbound application port: 8085\n»,»stream»:»stdout»,»time»:»2019-09-26T15:01:38.747563325Z»}
    {«log»:»\n»,»stream»:»stdout»,»time»:»2019-09-26T15:01:38.747569303Z»}

    Мой конфиг:
    [INPUT]
    Name tail
    Tag kube.*
    Path /var/log/containers/nc-wf-*.log
    Multiline On
    Parser_Firstline audit-firstline-json
    DB /var/log/flb_kube.db
    Mem_Buf_Limit 5MB
    Skip_Long_Lines On
    Refresh_Interval 10
    [PARSER]
    Name audit-firstline-json
    Format regex
    Regex ^{«log»:»(?(?\d{4}-\d{2}-\d{2}( |\T)\d{2}:\d{2}:\d{2}(.|,)\d{3,})(?:(\\»)|[^»]){9}(?:(\\»)|[^»])*)»
    Time_Key time
    Time_Format %Y-%m-%dT%H:%M:%S.%L

    • Fluent Bit по определению не умеет парсить строки, кроме первой, у multiline логов.

      В Вашем случае, случае куберенетес я бы переписал приложение или настроил его или надавил бы на автора, что бы оно кидало лог одной Json строкой. И дальше использовал стандартный фильтр fluent bit — kubernetes с включенным параметром Merge_Log on. Это параметр заставляет fluent bit самостоятельно разбирать json log и формировать поля. Кроме того, этот фильтр вытащит всю необходимую информацию по контейнеру из api kubernetes. Ну и парсер можно использовать стандартный, его задача вытащить из лога поле time.

Добавить комментарий

Ваш e-mail не будет опубликован. Обязательные поля помечены *