Делаем метрики и мониторинг для Akka при помощи Kamon
24 декабря 2014
Когда вы работаете с Akka, и вообще акторами, очень многое может пойти не так. Очереди сообщений могут переполняться, актор может начать перемножать матрички, заняв собой трэд, или, наконец, где-то могут просто начать сыпаться эксепшены. Пока у вас одна нода и мало пользователей, можно, конечно, просто быть на телефоне 24/7 и разбираться в проблемах по логам, отладочным ручкам, ну или remsh, если вы пишите на Erlang. Как только нод становится больше и проект выходит из альфы, такой подход становится совершенно нерабочим. На помощь приходит Kamon.
Примечание: Кстати, если вдруг вам доводилось слышать про Typesafe Console, знайте, что эта штука умерла. Нечто похожее осталось в Activator UI (который вскользь упоминался в заметке про Play), но оно не особо удобно и применимо только во время разработки, и то с натяжкой. Интересно, что сам Typesafe не особо трубил о смерти Typesafe Console и даже в списке рассылки разместил соответствующую информацию 1-го апреля, чтобы окончательно всех запутать.
Kamon — эта такая штука для сбора метрик в проектах, использующих Akka, Play Framework или Spray. Вам лишь нужно сказать «использовать Kamon» и указать ему, куда нужно складывать метрики. Все остальное — дело техники. Kamon умеет писать метрики в StatsD, Datadog и New Relic. При этом Kamon очень гибок. В частности, вы можете сказать «собирай информацию обо всех акторах, кроме» или наоборот, «собирай метрики только для таких-то акторов».
На самом деле, помощью Kamon можно не только репортить метрики, но и пробрасывать трейсы-контексты, а также более правильно определять причину ask timeout. Библиотека постоянно развивается, и в будущих версиях может появится еще какой-нибудь полезный функционал. Однако в рамках этой заметки мы сосредоточимся именно на метриках.
Для определенности скажем, что мы решили использовать Datadog. В принципе, если вы решите использовать, например, StatsD, то настройка будет мало чем отличаться.
Datadog — это очень могучий SaaS для хранения метрик и мониторинга системы. Помимо прочего, Datadog интересен своей способностью интегрироваться дофига с чем, а также вполне разумной ценовой политикой. Если в вашем проекте есть возможность воспользоваться SaaS для метрик и мониторинга, внимательно присмотритесь к Datadog. Получится намного быстрее, дешевле и удобнее, чем поднимать что-то свое.
Запись метрик в Datadog происходит не напрямую, а через Datadog Agent. Это такой демон, выполняющий несколько функций, и разделенный на компоненты, каждый из которых выполняет только одну функцию:
- Forwarder отвечает за отправку всех метрик в Datadog;
- Collector собирает информацию о машине (память, cpu, диск, трафик);
- Dogstatsd предоставляет StatsD API для записи метрик приложениями;
- Supervisord рулит предыдущими тремя компонентами;
По умолчанию включены все компоненты, но при необходимости, например, можно отключить collector.
Информацию по установке агента вы можете найти здесь или, если вы уже зарегистрированы в системе, в разделе Integrations → Agent. В последнем предлагаются более быстрые варианты в стиле curl ... | sh
.
В Ubuntu Linux после установки агента рулить им можно как-то так:
Конфиг агента (api key, какой интерфейс слушать и тд):
Логи агента с разбивкой по названным выше компонентам:
Описание протокола dogstatsd (который представляет собой расширенный протокол StatsD) вы можете найти здесь. Вот так, к примеру, можно записывать счетчики:
Хорошо, теперь нам есть, куда писать метрики. Осталось устроить все на стороне приложения. Пример того, как это делается, можно найти в этом репозитории. За основу мною был взять пример, который генерирует Typesafe Activator. Как оказалось, в этом примере многое нужно доводить до ума. Рассмотрим основные моменты.
Файл build.sbt:
libraryDependencies ++= Seq(
"com.typesafe.akka" %% "akka-actor" % "2.3.5",
"io.kamon" %% "kamon-core" % kamonVersion,
"io.kamon" %% "kamon-datadog" % kamonVersion,
"io.kamon" %% "kamon-log-reporter" % kamonVersion,
"io.kamon" %% "kamon-system-metrics" % kamonVersion,
"org.aspectj" % "aspectjweaver" % "1.8.2"
)
aspectjSettings
javaOptions <++= AspectjKeys.weaverOptions in Aspectj
fork in run := true
Здесь самое главное — это прикручивание AspectJ, через который Kamon и делает всю свою магию. Также обратите внимание на используемый здесь пакет kamon-system-metrics. Он позволяет собирать разные полезные метрики о самой JVM, в том числе время, потраченное на сборку мусора.
Файл project/plugins.sbt:
addSbtPlugin("com.typesafe.sbt" % "sbt-aspectj" % "0.10.0")
addSbtPlugin("com.eed3si9n" % "sbt-assembly" % "0.12.0")
Благодаря плагину sbt-aspectj Kamon будет работать при запуске приложения через sbt run
.
Файл src/main/resources/application.conf:
loglevel = INFO
extensions = ["kamon.metric.Metrics", "kamon.datadog.Datadog",
"kamon.system.SystemMetrics"]
}
kamon {
metrics {
filters = [
{
actor {
includes = [ "user/*", "user/worker-*" ]
excludes = [ "system/*" ]
}
},
{
trace {
includes = [ "*" ]
excludes = []
}
}
]
}
datadog {
hostname = "127.0.0.1"
port = 8125
flush-interval = 1 second
max-packet-size = 1024 bytes
report-system-metrics = true
includes {
actor = [ "*" ]
trace = [ "*" ]
dispatcher = [ "*" ]
}
application-name = "kamon_test"
}
}
Здесь мы прикручиваем компоненты Kamon’а в виде расширений для Akka и настраиваем их — по каким акторам собирать метрики, куда и как часто эти метрики отправлять, и так далее.
Еще интересен файл src/main/scala/sample/kamon/RandomNumberActor.scala:
import kamon.metric.UserMetrics
// ...
val counter = Kamon(UserMetrics).registerCounter("generate-number")
// ...
counter.increment()
Как видите, здесь приводится пример использования пользовательских метрик.
Если все было сделано правильно, то при запуске приложения в Datadog посыпятся метрики, при помощи которых вы без труда сможете строить графики вроде следующих.
Здесь мы следим за временем обработки сообщений заданным актором (максимум и 95-ый процентиль). Заметьте, что все метрики называются одинаково для всех акторов. Но при этом мы можем фильтровать метрики по имени актора или хосту, на котором крутится нода, поскольку метрики идут вместе с тэгами (см {actor:...
внизу графика). Кроме того, мы можем группировать метрики по множеству акторов, поскольку Kamon также снабжает метрики тэгами с префиксами, полученными из полного имени (пути) актора.
А этот график недвусмысленно намекает нам, что у актора копятся сообщения в очереди. Если вы недавно приступили к настройке Datadog, незамедлительно настройте алерты на эту ситуацию!
При использовании Kamon есть один важный нюанс. Допустим, вы собираете standalone jar. Тогда помимо этого jar вам придется включить в deb-пакет или чем вы там катите еще и aspectjweaver, а приложение запускать как-то так:
Но упаковка в deb-пакеты — это уже тема для отдельной заметки.
Вот, в общем-то, и все, о чем я хотел сегодня рассказать. Следует только добавить, что у Kamon есть официальный список рассылки.
Дополнение: Если вы вдруг используете Play, примите во внимание, что он инициализирует ActorSystem лениво, поэтому Kamon не будет слать никаких метрик до тех пор, пока кто-нибудь не пошлет первый HTTP-запрос. Для решения этой проблемы можно принудительно вычислить ActorSystem в onStart.
Дополнение: На момент написания этих строк Kamon репортил в качестве GC time суммарное время в миллисекундах, потраченное на сборку мусора с момента запуска приложения. Это поведение может измениться в будущем. А пока не пугайтесь, если увидите на графиках GC time в районе пятнадцати минут. Вообще, как оказалось, мониторинг GC time существенно усложняется, например, тем, что сборка мусора может происходить параллельно с работой кода самого приложения. Тем не менее, если вы полны решимости написать пользовательские метрики для наблюдения за GC, кое-какие примеры кода можно найти здесь и тут.
Дополнение: Вас также могут заинтересовать статьи Трассировка в Akka при помощи библиотеки Kamon и Устанавливаем связку из Prometheus и Grafana.
Метки: Akka, Scala, Функциональное программирование.
Вы можете прислать свой комментарий мне на почту, или воспользоваться комментариями в Telegram-группе.