Преимущества структурированного ведения журнала по сравнению с базовым ведением журнала

110

Мы создаем новое приложение, и я хотел бы включить структурированное ведение журнала. Моя идеальная установка - что-то вроде Serilogнашего кода на C # и Bunyanнашего JS. Они подействуют, fluentdа затем могут выйти на любое количество вещей, я думал вначале elasticsearch + kibana. У нас уже есть база данных MySQL, так что в краткосрочной перспективе я больше заинтересован в том, чтобы настроить Serilog + Bunyan и разработчиков для ее использования, и мы можем войти в MySQL, в то время как мы потратим немного больше времени на привлечение свободного языка и всего остального.

Тем не менее, один из наших более опытных программистов предпочел бы сделать что-то вроде: log.debug("Disk quota {0} exceeded by user {1}", quota, user);использование, log4netа затем просто запустить операторы выбора для MySQL, например:SELECT text FROM logs WHERE text LIKE "Disk quota";

При этом, какой подход лучше и / или что мы должны учитывать при выборе типа системы ведения журналов?

DTI-Matt
источник
Я согласен с изменениями, которые были сделаны. Я не столько пытаюсь что-то кому-то доказать, сколько пытаюсь понять преимущества и различия в структурированной и базовой регистрации. На мой взгляд, структурированный дает нам гораздо большую гибкость, особенно в источниках журналов, и то, как мы затем можем отображать их данные. Насколько я понимаю, я не могу объяснить, почему базовая регистрация и поиск MySQL лучше / хуже, чем структурированная регистрация.
DTI-Matt
2
Структурированное ведение журнала @ DTI-Matt serilog - это просто базовое ведение журнала, только оно форматирует объекты, которые вы печатаете на нем, - то, что вы можете сделать самостоятельно, очень легко переопределяя ToString. Более важным аспектом является конфигурирование и управление файлами журналов, а не один способ форматирования строки поверх другого, другой - производительность. Если разработчик хочет использовать log4net (который является хорошей библиотекой для ведения журналов), тогда ваш выбор serilog (который выглядит круто) является одним из тех «решений в поисках проблемы».
gbjbaanb
@ DTI-Matt Глядя на serilog, он выглядит очень похоже на log4net. log4net обрабатывает создание структурированных журналов в конфигурации. Вам не нужно искать сообщения в журнале, поскольку вы можете настроить дополнительную информацию и записать ее в таблицу. Также настройте log4net для fluentd tipstuff.org/2014/05/…
RubberChickenLeader
Обратите внимание, что есть некоторые дураки, которые не понимают идею концептуальных вопросов здесь. Если вы спросите о направлениях приложений баз данных в попытке разобраться в их возможностях ETL v. code, вы получите несколько серьезных отрицательных отзывов. Я полагаю, ваш вопрос тоже будет на разделочной доске.
user3916597
2
@gbjbaanb Serilog работает так же, как log4net при рендеринге событий в виде текста, но если вы используете структурированный формат для хранения журналов, он будет связывать именованные свойства с аргументами, которые передаются (т. е. для поддержки поиска / фильтрации без регулярных выражений и т. д. ) HTH!
Николас Блюмхардт

Ответы:

140

Есть два фундаментальных преимущества структурированного подхода, которые нельзя эмулировать с помощью текстовых журналов без (иногда экстремальных уровней) дополнительных усилий.

Типы событий

Когда вы пишете два события с log4net, как:

log.Debug("Disk quota {0} exceeded by user {1}", 100, "DTI-Matt");
log.Debug("Disk quota {0} exceeded by user {1}", 150, "nblumhardt");

Это даст похожий текст:

Disk quota 100 exceeded by user DTI-Matt
Disk quota 150 exceeded by user nblumhardt

Но что касается машинной обработки, это всего лишь две строки разного текста.

Возможно, вы захотите найти все события «превышение дисковой квоты», но упрощенный случай поиска событий like 'Disk quota%'упадет, как только произойдет другое событие, похожее на:

Disk quota 100 set for user DTI-Matt

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

Напротив, когда вы пишете следующие два события Serilog :

log.Debug("Disk quota {Quota} exceeded by user {Username}", 100, "DTI-Matt");
log.Debug("Disk quota {Quota} exceeded by user {Username}", 150, "nblumhardt");

Они производят текстовый вывод, аналогичный версии log4net, но за кулисами "Disk quota {Quota} exceeded by user {Username}" шаблон сообщения переносится обоими событиями.

С помощью соответствующего приемника вы сможете позже писать запросы where MessageTemplate = 'Disk quota {Quota} exceeded by user {Username}'и получать именно те события, когда дисковая квота была превышена.

Не всегда удобно хранить весь шаблон сообщения с каждым событием журнала, поэтому некоторые приемники хэшируют шаблон сообщения в числовом EventTypeзначении (например 0x1234abcd), или вы можете добавить обогащение в конвейер ведения журнала, чтобы сделать это самостоятельно .

Это более тонкое, чем следующее различие ниже, но чрезвычайно мощное при работе с большими томами журналов.

Структурированные данные

Опять же, учитывая два события об использовании дискового пространства, может быть достаточно легко использовать текстовые журналы для запроса конкретного пользователя like 'Disk quota' and like 'DTI-Matt'.

Но производственная диагностика не всегда так проста. Представьте, что необходимо найти события, в которых превышена квота диска ниже 125 МБ?

С Serilog это возможно в большинстве стоков, используя вариант:

Quota < 125

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

Теперь добавьте к этому тип события:

Quota < 125 and EventType = 0x1234abcd

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

Еще одно преимущество, возможно, не такое простое, чтобы его можно было предотвратить заранее, но после того, как отладка производства вышла из сферы хакерства регулярных выражений, разработчики начинают гораздо больше ценить журналы и проявляют больше внимания и внимания при их написании. Лучшие журналы -> лучшее качество приложений -> больше счастья вокруг.

Николас Блумхардт
источник
4
я люблю этот ответ. очень хорошо написано и по какой-то причине я не могу объяснить, держит меня на краю своего места.
jokab
16

Когда вы собираете журналы для обработки, будь то для анализа в какой-либо базе данных и / или последующего поиска в обработанных журналах, использование структурированного ведения журнала делает некоторые операции более простыми / более эффективными. Анализатор может использовать преимущества известной структуры ( например, JSON, XML, ASN.1 и т. Д.) И использовать конечные автоматы для анализа, в отличие от регулярных выражений (которые могут быть вычислительно дорогими (относительно) для компиляции и выполнения). Синтаксический анализ текста в произвольной форме, такой как предложенный вашим коллегой, имеет тенденцию полагаться на регулярные выражения и полагаться на то, что этот текст не изменяется . Это может сделать синтаксический анализ текста произвольной формы довольно хрупким ( т.е. синтаксический анализ тесно связан с точным текстом в коде).

Рассмотрим также случай поиска / поиска, например :

SELECT text FROM logs WHERE text LIKE "Disk quota";

LIKEусловия требуют сравнения с каждым textзначением строки; опять же, это сравнительно дорого в вычислительном отношении, особенно когда используются подстановочные знаки:

SELECT text FROM logs WHERE text LIKE "Disk %";

При структурированном ведении журнала ваше сообщение, связанное с ошибкой диска, может выглядеть следующим образом в JSON:

{ "level": "DEBUG", "user": "username", "error_type": "disk", "text": "Disk quota ... exceeded by user ..." }

Поля такого типа структуры могут довольно легко сопоставляться, например, с именами столбцов таблицы SQL, что означает, что поиск может быть более конкретным / детальным:

SELECT user, text FROM logs WHERE error_type = "disk";

Вы можете размещать индексы в столбцах, значения которых вы ожидаете часто искать / искать, если вы не используете LIKEпредложения для этих значений столбцов . Чем больше вы можете разбить ваше сообщение журнала на конкретные категории, тем более целенаправленным вы можете сделать свой поиск. Например, в дополнение к error_typeполю / столбцу в приведенном выше примере, вы можете сделать даже be "error_category": "disk", "error_type": "quota"или somesuch.

Чем больше структура у вас в журнале сообщений, тем больше ваш разборе / поиск системы (такие как fluentd, elasticsearch, kibana) могут воспользоваться этой структуры, а также выполнять свои задачи с большей скоростью и меньшим количеством CPU / памяти.

Надеюсь это поможет!

Castaglia
источник
1
+1 Хочу добавить, что речь идет не только о скорости и эффективности. Релевантность результатов поиска будет намного выше при использовании структурированного ведения журнала и, следовательно, «структурированных запросов». Без этого поиск любых слов, которые встречаются в разных контекстах, даст вам массу неуместных хитов.
Марьян Венема
1
+1 от меня тоже, я думаю, что это прибивает это. Ниже добавлена ​​немного другая формулировка, чтобы расширить также случай типов событий.
Николас Блюмхардт
8

Вы не найдете большой выгоды от структурированного ведения журнала, когда ваше приложение создает несколько сотен сообщений журнала в день. Вы определенно будете это делать, когда у вас будет несколько сотен сообщений журнала в секунду, поступающих из разных развернутых приложений.

В связи с этим установка, в которой сообщения журнала попадают в стек ELK, также подходит для масштабирования, когда регистрация в SQL становится узким местом.

Я видел настройку «базового ведения журнала и поиска» с использованием SQL select .. likeи регулярных выражений, раздвинутых до предела, где он разваливается - есть ложные срабатывания, упущения, ужасный код фильтра с известными ошибками, которые трудно поддерживать, и никто не хочет их трогать, новые сообщения журнала, которые не соответствуют предположениям фильтра, нежелание прикасаться к операторам регистрации в коде, чтобы они не нарушали отчеты, и т. д.

Таким образом, несколько программных пакетов появляются для решения этой проблемы в лучшем виде. Есть Serilog, я слышал, что команда NLog смотрит на него , и мы написали StructuredLogging.Jsonдля Nlog , я также вижу, что новые абстракции журналирования ядра ASP.Net "позволяют провайдерам журналирования реализовывать ... структурированные журналы".

Пример с StructuredLogging. Вы входите в систему регистрации NLog следующим образом:

logger.ExtendedError("Order send failed", new { OrderId = 1234, RestaurantId = 4567 } );

Эти структурированные данные отправляются в кибану. Значение 1234сохраняется в OrderIdполе записи журнала. Затем вы можете искать, используя синтаксис запроса кибана, например, для всех записей журнала, где @LogType:nlog AND Level:Error AND OrderId:1234.

Messageи OrderIdтеперь это просто поля, в которых можно искать точные или неточные совпадения по мере необходимости или объединять их для подсчета. Это мощный и гибкий.

Из лучших практик StructuredLogging :

Зарегистрированное сообщение должно быть одинаковым каждый раз. Это должна быть постоянная строка, а не строка, отформатированная так, чтобы она содержала значения данных, такие как идентификаторы или количества. Тогда это легко найти.

Регистрируемое сообщение должно отличаться, т. Е. Не совпадать с сообщением, созданным несвязанным оператором журнала. Тогда его поиск тоже не подходит.

Энтони
источник