12 июля 2018 года увидел свет первый коммит проекта :telemetry
. Автор коммита — Аркадий Гил, но README утверждает, что авторское право принадлежит © 2018 Chris McCord and Erlang Solutions, а последний коммит по состоянию на сегодня был сделан Жозе Валимом.
Библиотека представляется следующим образом:
Telemetry — это динамическая библиотека диспетчеризации метрик и инструментария. Она легковесная, небольшого размера, и может быть использована в любом проекте эрланга или эликсира.
Главным преимуществом библиотеки является то, что она действительно очень проста. Вы просто регистрируете событие, которое «состоит из числового значения и прикрепленных метаданных», и просто посылаете соответствующее сообщение всякий раз, когда это необходимо. Сообщение будет доставлено в обработчик, который может делать все, что вздумается потребителю; обычно это запись в журнал или что-то типа того. Разделение бизнес-логики и метрик в лучшем виде.
Главным недостатком :telemetry
же является то, что она требует огромного количества шаблонного кода, копируемого из проекта в проект, да еще и нуждающегося в сопровождении в нескольких мало связанных между собой кусках приложения. Рефакторинг проекта с интенсивным использованием телеметрии может стать катастрофой. Для изменения названия события необходимо изменить вызовы в трех разных местах: регистрация события, запуск события, обработка события. Если кто-то забывает зарегистрировать вновь созданный ивент, запуск его будет радостно отработан, но обработчик никогда не вызовется и оно просто отправится на кладбище недоставленных и непрочитанных сообщений.
Чувства мои были противоречивы. Я люблю, чтобы метрики были встроены везде, но я не могу согласиться, что grep -r telemetry\.execute ./{lib,test}/**/*.ex*
— это то, что я хочу добавить в свой конвейер сборки. Поэтому я придумал удобную обертку для :telemetry
, и назвал ее Telemetri?a
. Я преследовал следующие цели:
- простой способ добавления
:telemetry
к функциям и выражениям; - автоматическое создание имен событий на основе контекста;
- генерация конфигурации во время компиляции для регистрации всех активных событий;
- автоматическое включение метрик виртуальной машины и системы через
:telemetry_poller
; - настраиваемые обработчики для различных случаев, основанные не только на имени события;
- полная поддержка релизов;
- минимум (отсутствие) шаблонного кода для копипаста
В общем и целом
Проект сейчас только-только отправился в детский сад, но он уже полностью пригоден для использования. Все, что вам нужно, чтобы внедрить его в какой-нибудь проект (и, следовательно, запрыгнуть в наш поезд едущих в светлое будущее с ветерком и метриками), — это изменить mix.exs
, включив :telemetria
, и обеспечить минимальную конфигурацию.
# mix.exs
def project do
[
...
# needed for autogeneration of events
compilers: [:telemetria | Mix.compilers()]
]
end
def deps do
[
...
{:telemetria, "~> 0.5"}
]
end
Полный список поддерживаемых параметров всегда можно найти в документации, единственным обязательным является :otp_app
.
config :telemetria,
otp_app: :my_app,
polling: [enabled: true]
С этими настройками, метрики виртуальной машины и системы будут каждые пять секунд доставляться обработчику по умолчанию, который выплюнет их в журнал с уровнем :info
.
Интерфейс
Интерфейс у Telemetri?a
также очень прост. Он предоставляет три макрокоманды и одну аннотацию для обработки :telemetry
событий. Макросы deft/2
, defpt/2
, и t/2
— для обертки функции, приватных функций и любых пользовательских выражений, добавив к ним события :telemetry
. Проще говоря, все три — ничто иное, как аспекты, которые разворачиваются в получить метрики > выполнить обернутые инструкции > снова получить метрики и отослать ивент. Аннотация @telemetria true
по существу совпадает с изменением аннотированного вызова на deft/2
/ defp/2
. Давайте рассмотрим следующий пример.
Используя макрос
defmodule Geom do
import Telemetria
@spec circle_area(float()) :: float()
deft circle_area(radius),
do: 2 * 3.14 * radius
end
После компиляции этот код выплюнет событие с именем [:geom, :circle_area]
при каждом вызове Geom.circle_are/1
:
iex|1> Geom.circle_area 2.0
14:59:49.686 [info] [event: [:geom, :circle_area],
measurements: %{consumed: 3162, reference: "#Reference<0.12.34.56>",
system_time: [system: 1590843589680306588,
monotonic: -576460720784457,
utc: ~U[2020-05-30 12:59:49.681885Z]]},
metadata: %{context: [], env: #Macro.Env<aliases: [], context: nil, ...},
config: #PID<0.314.0>]
#? 12.56
Используя аннотацию
defmodule Geom do
use Telemetria
@telemetria true
@spec circle_area(float()) :: float()
def circle_area(radius),
do: 2 * 3.14 * radius
end
Этот код делает в точности то же самое, что и приведенный выше.
Компилятор
Это не обязательно, но работать с Telemetri?a
будет заметно проще, если добавить пользовательский компилятор в список компиляторов в вашем mix.exs
def project do
[
...
compilers: [:telemetria | Mix.compilers()]
]
end
Компилятор собирает добавленные / удаленные события, за кулисами поддерживает файл манифеста, чтобы всегда иметь актуальный список событий, и предоставляет диагностику основному компилятору Elixir.
Он также создает и предоставляет конфигурацию JSON, которая может быть найдена в папке config
локально и может использоваться в качестве конфигурации JSON в релизах. Telemetri?a
умеет читать конфиги в формате JSON.
Конфигурация
Конфигурация позволяет:
- глобальное включение / отключение телеметрии (очистка на уровне компилятора);
- включение опроса телеметрии виртуальной машины / системы с интервалом;
- испольщование обычного файла настройки дополнительных событий, непосредственно обрабатываемых с; помощью
:telemetry
; - конфигурацию JSON дополнительных событий (полезно для релизов);
- настройку собственного пользовательского обработчика для событий телеметрии.
Полный список настроек доступен в соответствуюшем разделе документации.
Потроха
Глубокое погружение в детали реализации, безусловно, выходит за рамки этой рекламной заметки, но несколько слов все-таки нужно сказать и о том, как оно устроено изнутри.
Если вы хотите легко перейти к добавлению метрик в свое приложение, пожалуйста, прекратите читать прямо сейчас и обратитесь к сниппетам из главки, озаглавленной «В общем и целом».
Если же, наоборот, вас интересуют какие-то хитрости и тонкости, то вот список того, что может оказаться интересным и даже познавательным.
- ??? всегда актуальные, автодокументируемые настройки с использованием
nimble_options
; - ??? реализация аннотаций с использованием
@on_definition
и@before_compile
хуков времени компиляции; - ??? запуск приложения поэтапно посредством
Application.start_phase/3
, чтобы обеспечить полную доступность:telemetry
в момент запуска основного приложения; - ??? реализация пользовательского компилятора эликсира для сбора событий и поддержка файла манифеста.
Удачных всем метрик!