[Из песочницы] Сбор метрик из .NET приложений с помощью Telegraf
Одной из важнейших задач при проектировании систем является организация мониторинга состояния всех узлов, в том числе большого числа сервисов. В условиях, когда дополнительных сил и средств на это не выделяется, приходится максимально использовать готовые решения.
Думаю, у многих картина в проекте примерно такая:
Что-то куда-то пересылается, как-то обрабатывается и держится на одном гвозде. Задача была собрать со всех точек статистику обработки данных и сложить в одном месте, чтобы потом строить графики и писать отчеты.
Благодаря статье выбор пал на связку Telegraf-Elasticsearch-Grafana. Telegraf отлично вписался в проект для организации мониторинга состояния как железа, так и общедоступного стороннего софта, но я отдельно освещу вопрос измерения нагрузки на собственные сервисы. В данном случае речь идет о .NET сервисах, запущенных в docker контейнерах под Linux. Все сервисы образуют несколько этапов обработки входящей информации, и мне необходимо было измерять количество успешно обработанных и отбракованных пакетов с дополнительными метками этапа обработки, источника и др. для возможности последующей статистической обработки.
Опущу процесс установки и перейду сразу к настройке. Итак, Telegraf умеет принимать сообщения с метриками по каналам tcp, udp, а также через unixsocket:
[[inputs.socket_listener]]
#service_address = "unixgram:///tmp/telegraf.sock"
service_address = "udp4://:14230"
data_format = "json"
json_name_key = "name"
namepass = ["query_pass"]
tag_keys = ["appname","fromip"]
Сервисы будут отправлять сообщения каждый раз, когда обработается очередной пакет, поэтому дополнительно настроим агрегирование. Интервала в 10 секунд вполне достаточно, зависит от нагрузки конкретной системы.
[[aggregators.basicstats]]
period = "10s"
drop_original = true
stats = ["sum"]
namepass = ["query_pass"]
fieldpass = ["pass","fail"]
Пройдемся по параметрам: query_pass — название метрики, объединяющее будущие измерения, pass — успешная обработка, fail — нет. Дополнительно метрики будут помечаться тегами appname и fromip.
Теперь немного кода. Мне нравится отправлять метрики через udp и unixsocket, хотя вам могут подойти и другие варианты.
UdpClient udpClient = new UdpClient("127.0.0.1", 14230);
byte[] datagramBytes= Encoding.UTF8.GetBytes("{\"name\":\"query_pass\",\"pass\":1,\"fromip\":\"127.0.0.1\",\"appname\":\"application\"}");
udpClient.Send(datagramBytes, datagramBytes.Length);
datagramBytes= Encoding.UTF8.GetBytes("{\"name\":\"query_pass\",\"fail\":1,\"fromip\":\"127.0.0.1\",\"appname\":\"application\"}");
udpClient.Send(datagramBytes, datagramBytes.Length);
Все это отлично суммируется и складывается в базу, в моем случае это elasticsearch (скриншот).
[[outputs.elasticsearch]]
urls = [ "http://localhost:9200" ] # required.
timeout = "5s"
health_check_interval = "5s"
index_name = "telegraf-%Y.%m.%d" # required.
manage_template = true
template_name = "tp_telegraf"
overwrite_template = true
Всем котов.
P.S.: тут итоговый проект для отправки метрик под net.core