Несколько недель назад мы с Рафаэлем обсуждали одну из основных проблем, с которыми мы столкнулись.

Проблема заключалась в том, что мы тратили ненужное количество времени на просмотр журналов приложений вручную, чтобы зафиксировать показатели производительности модели машинного обучения, которые включают оценку AUC, точность, точность, оценку F1 и многие другие показатели¹.

Что ж, вы все равно можете управлять и выполнять эту задачу вручную, просматривая эти журналы, если работает только одна модель, НО что, если работает более 50 моделей, и вы хотите проанализировать оценку AUC для всех моделей одновременно?
Это настоящий вызов!

Поскольку специалистам по обработке данных в команде было сложно получить обзор показателей производительности всех работающих моделей машинного обучения. Мы собрались как одна команда и сотрудничали (в том числе и с нашими деловыми партнерами). Мы поняли, что у нас уже есть LogDNA (служба ведения журналов), которая отображает журналы приложений, тогда почему бы нам просто не использовать ее и не реализовать структурированное ведение журнала.

Что такое структурированное ведение журнала?

Журналы, которые записываются в структурированном формате и могут быть легко проанализированы службой ведения журналов. Это может быть XML, JSON или другие форматы. ² Но, скорее всего, вы увидите JSON как стандартный формат для структурированного ведения журнала.

С JSON легко работать, и он стал стандартным форматом данных практически для всего, - Мэтт Уотсон3.

Почему структурированное ведение журнала?

Обычно журналы представляют собой неструктурированные текстовые данные, которые читаются человеком, но доступны ли они для чтения машиной?
Теперь вы можете подумать, почему они должны быть машиночитаемыми? Что, если машина выполняет для вас некоторую работу, например, выполняет некоторую аналитику или подсчитывает, сколько запросов было неудачно / выполнено успешно.
Разве это не полезно? Я знаю, это! : D

С обычными журналами трудно извлечь такую ​​полезную информацию.

Некоторые основные преимущества, которые дает структурированное ведение журнала:

  • Обеспечьте согласованность и стандартизацию благодаря структурированным данным
  • Аналитика или бизнес-аналитика
  • Лучше RCA, отладка, легко фильтровать журналы
  • Системный мониторинг, создание графиков или диаграмм для анализа поведения

Давайте посмотрим на небольшой пример. Как правило, вы регистрируете такие утверждения:

log.info("API request from {}".format(customerId))
OUTPUT:
INFO   2019-12-18 14:11:23   API request from customer 1234

Но если вы предоставите некоторую структуру (в данном случае формат JSON) для приведенного выше оператора, это будет выглядеть так:

{"level": "INFO", "time": "2019-12-18 14:11:23", "message": "API request from customer 1234"}

Теперь БОЛЬШОЙ вопрос - как этого добиться?

Самый простой способ - просто выгрузить журналы в паре "ключ-значение", но это не подходящее решение. Я бы порекомендовал использовать некоторые внешние библиотеки (потому что тогда вам не нужно писать дополнительную логику для сохранения контекста самостоятельно и с другими наборами конфигураций). Для этого существуют различные библиотеки и пакеты. Я выбрал structlog (потому что он прост в использовании, прост в настройке, очень хорошо документирован и снабжен различными примерами) для python, но вы можете найти похожие библиотеки или пакеты npm или драгоценные камни в соответствии с вашими потребностями.

Реализация

Я хочу дать вам краткий обзор реализации. Я также порекомендовал бы вам углубиться в structlog api docs для подробного объяснения.

Импортируйте пакет, создайте объект регистратора, а затем просто добавьте запись в журнал. Вот и все!

Structlog делает ведение журнала в Python менее болезненным и более мощным, добавляя структуру в записи журнала.

>>> import structlog
>>> log = structlog.get_logger()
>>> log.info("API request from {}".format(customerId))
This will give similar output as shown above in JSON format.

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

Например:
Ваше приложение получает запрос от клиента 12345, а затем обрабатывает его. Так что в этом случае было бы неплохо добавить эту информацию в качестве контекста.

log.bind(customer=customer_id, url=requested_url) # Binds data
log.info("Api request from XYZ customer")
# Some code...
log.info("Fetching some results...")

OUTPUT:
{"time": "2019-12-18 14:11:23", "level": "INFO", "message": "Api request from XYZ customer", "customer": 12345, "url": "/getSomeInfo" }
{"time": "2019-12-18 14:12:45", "level": "INFO", "message": "Fetching some results...", "customer": 12345, "url": "/getSomeInfo" }

Вы заметили, что вы связали данные только один раз, и они регистрируются в каждом операторе? Это контекст!

Что ДАЛЬШЕ?

Поскольку вы реализовали структурированное ведение журнала и преобразовали журналы в машиночитаемый формат (JSON).

Теперь вы можете использовать любую систему управления журналами, такую ​​как LogDNA, Loggly, Logentries и т. Д., И позволить ей выполнять свою работу.

На изображении выше вы можете видеть, что, добавив этот фильтр
response:(≥400 <500), становится проще фильтровать запросы с диапазоном кода ответа 400–500.

По сути, вы можете фильтровать, анализировать, генерировать некоторые графики и многое другое на основе пары key:value, которую вы передаете в записи журнала.

В этом сила структурированного ведения журнала!

Ссылки:
[1] Метрики для оценки вашего алгоритма машинного обучения
[2] Статья Мэтта Уотсона на stackify.com
[3] https://stackify.com / top-11-json-performance-usage-tips
[4] Документация по Structlog API