Выделение прерывателя строк регулярного выражения, объединяющего несколько строк ERROR [stderr] в одно событие - PullRequest
1 голос
/ 19 апреля 2019

Я работаю над отображением логов из json-файла Docker в Splunk. По большей части у меня это работает, за исключением случаев, когда печатается трассировка стека. Я знаю, что e.printStackTrace() не лучшая практика, но у наших сервисов есть кое-что, что я хочу поддержать в Splunk.

Я настраиваю файл props.conf, и у меня есть следующий LINE_BREAKER regex в props.conf. LINE_BREAKER=([\n\r]+)\s*{"log":"[0-9]+.*[0-9]\s+

Это будет соответствовать до конца отметки времени этой формы: {"log":"2019-04-18 15:18:18,796 ERROR [stderr] ...

Проблема в том, что напечатанная трассировка стека состоит из нескольких строк, например:

{"log":"2019-04-18 15:18:18,796 ERROR [stderr] (default-threads - 3) java.util.NoSuchElementException: No value present\n","stream":"stdout","time":"2019-04-18T19:18:18.800485539Z"}
{"log":"2019-04-18 15:18:18,804 ERROR [stderr] (default-threads - 3) at java.util.Optional.get(Optional.java:135)\n","stream":"stdout","time":"2019-04-18T19:18:18.806510971Z"}
{"log":"2019-04-18 15:18:19,259 ERROR [stderr] (default-threads - 3) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)\n","stream":"stdout","time":"2019-04-18T19:18:19.264689098Z"}
{"log":"2019-04-18 15:18:19,259 ERROR [stderr] (default-threads - 3) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)\n","stream":"stdout","time":"2019-04-18T19:18:19.281810119Z"}
{"log":"2019-04-18 15:18:19,274 ERROR [stderr] (default-threads - 3) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)\n","stream":"stdout","time":"2019-04-18T19:18:19.28185714Z"}
{"log":"2019-04-18 15:18:19,275 ERROR [stderr] (default-threads - 3) at java.lang.reflect.Method.invoke(Method.java:498)\n","stream":"stdout","time":"2019-04-18T19:18:19.281867696Z"}
{"log":"2019-04-18 15:18:19,275 ERROR [stderr] (default-threads - 3) at org.jboss.weld.interceptor.proxy.TerminalAroundInvokeInvocationContext.proceedInternal(TerminalAroundInvokeInvocationContext.java:49)\n","stream":"stdout","time":"2019-04-18T19:18:19.281875844Z"}
{"log":"2019-04-18 15:18:19,498 ERROR [org.apache.activemq.ActiveMQSession] (default-threads - 3) error dispatching message: : javax.ejb.EJBTransactionRolledbackException\n","stream":"stdout","time":"2019-04-18T19:18:19.523359025Z"}

... и так далее. до конца стека трассировки. Каждая строка заканчивается событием, основанным на моем регулярном выражении для LINE_BREAKER, что подходит для INFO сообщений и однострочных ERROR сообщений от нашего регистратора, но не для трассировки стека, как указано выше.

Я хочу объединить эту трассировку стека ОШИБКИ [stderr] в одно событие. Таким образом, мой разрыв строки должен соответствовать до следующего сообщения с меткой времени, которое не является [stderr].

из моего примера должно совпадать с первой строки с ERROR [stderr] до: {"log":"2019-04-18 15:18:19,498 (последняя строка журнала выше).

Я попытался добавить отрицательный прогноз, но теперь он будет совпадать только 1 раз. ([\n\r]+)\s*{"log":"[0-9]+.*[0-9]\s+[\s\S]+\[(?!stderr]) соответствует последней строке, но если под ней есть строки, ни одна из них больше не соответствует.

1 Ответ

1 голос
/ 27 апреля 2019

В этой части шаблона {"log":"[0-9]+.*[0-9]\s+ вы сопоставляете часть с отметкой времени, используя [0-9]+.*[0-9]\s+, что может привести к ненужному повторному отслеживанию из-за .*, который сначала будет соответствовать до конца строки.

Youвместо этого можно сделать шаблон типа метки времени более конкретным, например [0-9]{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2},\d+

. Чтобы получить совпадения, одним из вариантов может быть сопоставление строки, содержащей stderr.Затем повторите сопоставление следующих строк с этим шаблоном 0+ раз, начиная с новой строки, чтобы объединить их.

Чтобы продолжить сопоставление с другими строками, вы можете использовать отрицательный прогноз после ERROR и чередование .

^(?:{"log":"[0-9]{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2},\d+ ERROR \[stderr\].*(?:\n{"log":"[0-9]{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2},\d+ ERROR \[stderr\].*)*|{"log":"[0-9]{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2},\d+ ERROR (?!\[stderr\]).*)
  • ^ Начало строки
  • (?: Группа без захвата
    • {"log":"[0-9]{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2},\d+ ERROR \[stderr\].*
    • (?: Группа без захвата
      • \n{"log":"[0-9]{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2},\d+ ERROR \[stderr\].*
    • )* Закрыть группу без захвата и повторить 0+ раз
    • | Или
    • {"log":"[0-9]{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2},\d+ ERROR (?!\[stderr\]).*
  • ) Закрыть группу без захвата

Regex demo

...