Форматировать и красиво печатать лог через хвост

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

Логи в файле типа:

2019-07-04T09:53:04-07:00   some.package.placeholder.stderr {"log": "The content", "foo": "bar", "baz": "blah"}
2019-07-04T10:15:37-07:00   some.package.placeholder.stderr {"log": "I'm actually", "foo": "bar", "baz": "blah"}
2019-07-04T10:15:37-07:00   some.package.placeholder.stderr {"log": "Interested on", "foo": "bar", "baz": "blah"}

И я хочу сделать что-то похожее на

tail -f myLogFile | grep [...?...] | jq '.log'

Итак, при хвосте я получаю:

The content
I'm actually
Interested on

Или даже:

2019-07-04T09:53:04-07:00   The content
2019-07-04T10:15:37-07:00   I'm actually
2019-07-04T10:15:37-07:00   Interested on

Может ли some.package.placeholder.stder содержать пробелы?

Cyrus 04.07.2019 19:47

@Cyrus не для этого случая, но метка времени, package.placeholder и фактический json могут быть разделены табуляцией/пробелами

unmultimedio 04.07.2019 20:21
Как сделать HTTP-запрос в Javascript?
Как сделать HTTP-запрос в Javascript?
В JavaScript вы можете сделать HTTP-запрос, используя объект XMLHttpRequest или более новый API fetch. Вот пример для обоих методов:
4
2
4 444
3
Перейти к ответу Данный вопрос помечен как решенный

Ответы 3

Ответ принят как подходящий

С GNU grep для -o:

$ tail file | grep -o '{[^}]*}' | jq -r '.log'
The content
I'm actually
Interested on

С любым awk:

$ tail file | awk 'sub(/.*{/,"{")' | jq -r '.log'
The content
I'm actually
Interested on

$ tail file | awk '{d=$1} sub(/.*{/,""){$0 = "{\"date\": \""d"\", " $0} 1' | jq -r '.date + " " + .log'
2019-07-04T09:53:04-07:00 The content
2019-07-04T10:15:37-07:00 I'm actually
2019-07-04T10:15:37-07:00 Interested on

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

Предположительно, кто-то также захочет использовать параметр командной строки —unbuffered команды jq?

peak 05.07.2019 13:15

@peak idk, если честно, я только учусь jq, но вполне вероятно, что вы захотите использовать что-то, чтобы отключить буферизацию, поэтому, если эта опция для этого jq, тогда да, и вы также можете добавить fflush() к команды awk после печати каждой строки или вставьте stdbuf или аналогичный вызов.

Ed Morton 05.07.2019 16:57

Если строки журнала разделены табуляцией, вы можете прочитать строки в необработанном виде и разделить на табуляции. Который вы могли бы затем проанализировать json и отфильтровать по своему вкусу и рекомбинировать по мере необходимости.

$ tail -f myLogFile | jq -Rr 'split("\t") | [.[0], (.[2] | fromjson.log)] | join("\t")'
2019-07-04T09:53:04-07:00   The content
2019-07-04T10:15:37-07:00   I'm actually
2019-07-04T10:15:37-07:00   Interested on

Это выглядело потрясающе, но когда я попробовал это с jq версией 1.6 на cygwin, я просто получил assertion "cb == jq_util_input_next_input_cb" failed: file "/usr/src/ports/jq/jq-1.6-1.x86_64/src/jq-1.6/src/util.c", line 371, function: jq_util_input_get_position Aborted (core dumped)

Ed Morton 06.07.2019 19:32

Хм, я не в состоянии отладить и посмотреть, что вызывает это, но, судя по сообщению, я думаю, это проблема с тем, как хвост проходит по выходным данным. Я попробовал это сам в то время в git bash, и он не работает в режиме реального времени, что, как я полагаю, должно работать.

Jeff Mercado 06.07.2019 19:51

Я получаю то же сообщение об ошибке только от jq '...' file, что и от tail file | jq. Это может быть просто вещь cygwin, idk. Я только начинаю учиться jq поэтому не использовал его много. Быстрый гугл выдал github.com/stedolan/jq/issues/1588, но не знаю, та же ли это проблема или нет.

Ed Morton 06.07.2019 19:57

Вот вещь, которую я использую, которую можно использовать в канале и с файловыми аргументами:

cat /usr/local/bin/j2t
#!/bin/bash

function usage {
  cat <<EOF
Usage:
        $0 <json filename>
    or
        tail -F <json filename> | $0
EOF
}

if (($# == 0)); then
    {
        sed "s/@\(timestamp\)/\1/" | jq -r '[.timestamp, .pri.facility, .pri.severity, .message] | join("\t")'
    } < /dev/stdin

else
    if [ -r "$1" ] ; then
        sed "s/@\(timestamp\)/\1/" $1 | jq -r '[.timestamp, .pri.facility, .pri.severity, .message] | join("\t")'
    else
        help
    fi
fi

например: (если ваш daemon.log - это json)

j2t /var/log/daemon.log
level: 63, builder: awillia2)
2021-08-14T00:00:06.820642+00:00        daemon  INFO     Starting Run Clamscan...
2021-08-14T00:00:06.846405+00:00        daemon  INFO     Started Run Clamscan.

Наверное, стоит переформатировать время, оно длинновато.

Другие вопросы по теме