В какой то момент разработки приложения, каждый из нас приходит к тому, что нам нужно больше информации о том, что происходит внутри приложения или же в возможности мониторить приложение. В случае с Play Framework уже существует готовое решение в виде отличной библиотеки с открытым исходным кодом Kamon в паре с модулем kamon-play.
Но сегодня мы собираемся взглянуть на альтернативное решение, интеграцию и использование Drowizard Metrics ранее известное как Codahale Metrics с Play Framework.
Интеграция
Так я начал искать готовые решения которые могли бы мне помочь в интеграции этих двух инструментов.
Я нашел несколько не полных решений:
- metrics-scala — Отличная библиотека, изящный API c хорошей поддержкой Scala, но в случае с Play Framework не достаточно поддрежки.
- metrics-play — Одно из первых решений которыми Google пытается удовлетворить ваш запрос, но эта библиотека уже не поддерживается и не совместима с последними версиями Play Framework и Dropwizard Metrics. Но имеется форк, который обновлен до последних версий, так что я решил попробовать его.
К сожалению модуль metrics-play предоставляет только базовый функционал из всего что имеется в среде Dropwizard Metrics. Это может быть достаточно, если вам нужны простые метрик�� которые доступны через REST api, но у меня были более высокие требования и я решил дополнить функционал этого модуля написав следующие модули:
- metrics-reporter-play — Поддержка Metrics репортеров в Play Framework.
- metrics-annotation-play — Поддержка аннотаций Metrics для Play Framework через Guice AOP.
Собственно об этом мы будем говорить далее.
Поддержка Metrics репортеров в Play Framework
Metrics предоставляет мощный инструментарий для мониторинга поведения критических компонентов в продакшн среде. Так же, предоставляет средства отправки измеренных данных через репортеров. Metrics репортеры — это отличный способ отправки данных из самого приложения в предпочитаемую систему хранения и визуализации метрик.
На момент написания статьи поддерживаемые репортеры следующие:
- console — Периодически отправляет данные в стандартный поток выхода приложения
- graphite — Периодически отправляет данные в Graphite.
Dropwizard Metrics и комьюнити также предосталяют другие репортеры, на пример Ganglia Reporter, CSV Reporter, InfluxDB Reporter, ElasticSearch Reporter и другие.
Добавление фэктори для поддержки репортеров в библиотеку является легкой задачей.
Поддержка аннотаций Metrics для Play Framework через Guice AOP
По умолчанию, для того что бы использовать метрики нужно вызвать Metric Registry для создания метрик, создать контекст и в ручную управлять им. На пример:
def doSomethingImportant() = {
val timer = registry.timer(name(classOf[WebProxy], "get-requests"))
val context = timer.time()
try // critical business logic
finally context.stop()
}Что бы держать все DRY есть аннотации, модуль metrics-annotation-play будет создавать и надлежащим образом вызвать Timer для @Timed, Meter для @Metered, Counter для @Counted и Gauge для @Gauge. @ExceptionMetered тоже поддерживается, он создает Meter, который измеряет частоту выбрасывания исключений.
Предыдущий пример можно переписать следующим образом:
@Timed
def doSomethingImportant = {
// critical business logic
}или же можно сдекарировать весь класс, что создаст метрики для всех явных методов:
@Timed
class SuperCriticalFunctionality {
def doSomethingImportant = {
// critical business logic
}
}Данный функционал поддерживается только для классов созданных через Guice, так же имеются некоторые ограничения AOP.
Пример использования
Давайте попробуем использовать библиотеку в реальном приложении и рассмотрим, как все работает. Исходный код приложения можно найти тут.
Я использую шаблон activator play-scala с sbt plugin. Мы должны добавить JCenter в список resolvers и зависимости:
name := """play_metrics_example"""
version := "1.0-SNAPSHOT"
lazy val root = (project in file(".")).enablePlugins(PlayScala)
scalaVersion := "2.11.8"
resolvers += Resolver.jcenterRepo
libraryDependencies ++= Seq(
"de.khamrakulov.metrics-reporter-play" %% "reporter-core" % "1.0.0",
"de.khamrakulov" %% "metrics-annotation-play" % "1.0.2",
"org.scalatestplus.play" %% "scalatestplus-play" % "1.5.1" % Test
)Для примера я использую сonsole репортер, давайте добавим конфигурацию в application.conf.
metrics {
jvm = false
logback = false
reporters = [
{
type: "console"
frequency: "10 seconds"
}
]
}Как вы видите я деактивировал метрики jvm и logback, что бы не потерять наши метрики и добавил репортер, который будет выводить метрики в stdout c периодичностью 10 секунд.
Теперь мы можем начать использовать аннотации, я сдекорирую метод index контроллера HomeController:
@Singleton
class HomeController @Inject() extends Controller {
@Counted(monotonic = true)
@Timed
@Metered
def index = Action {
Ok(views.html.index("Your new application is ready."))
}
}На самом деле вы не должны использовать все аннотации разом, т.к. @Timed комбинирует в себе Counter и Meter, но я это сделал для демонстрации возможностей.
После старта приложения и запроса Главной Страницы, репортер должен вывести метрики в stdout:
-- Counters --------------------------------------------------------------------
controllers.HomeController.index.current
count = 1
-- Meters ----------------------------------------------------------------------
controllers.HomeController.index.meter
count = 1
mean rate = 0.25 events/second
1-minute rate = 0.00 events/second
5-minute rate = 0.00 events/second
15-minute rate = 0.00 events/second
-- Timers ----------------------------------------------------------------------
controllers.HomeController.index.timer
count = 1
mean rate = 0.25 calls/second
1-minute rate = 0.00 calls/second
5-minute rate = 0.00 calls/second
15-minute rate = 0.00 calls/second
min = 14.59 milliseconds
max = 14.59 milliseconds
mean = 14.59 milliseconds
stddev = 0.00 milliseconds
median = 14.59 milliseconds
75% <= 14.59 milliseconds
95% <= 14.59 milliseconds
98% <= 14.59 milliseconds
99% <= 14.59 milliseconds
99.9% <= 14.59 millisecondsКонечно же вы все еще можете просмотреть метрики через REST api, для этого надо добавить конфигурацию в routes файл:
GET /admin/metrics com.kenshoo.play.metrics.MetricsController.metricsЧто дальше?
Автоматическая проверка работоспособности приложения (Health Checks)
Metrics так же поддерживает возможность использования автоматических проверок работоспособности приложения(health checks). Больше информации можно найти в официальной документации.
Больше репортеров
Для создания надлежащей среды использования метрик нужна поддержка большего количества репортеров. Это должно быть еще одним направлением развития библиотеки.
Надлежащая по��держка Future
На данный момент, что бы измерить время выполнения Future нужно в ручную выполнять все действия. Надлежащая поддержка Future может помочь в асинхронной среде Play Framework и может быть хорошим дополнением.
Поддержка HdrHistogram
Hdrhistogram предоставляет альтернативную реализацию коллектора (reservoir) высокого качества, который может быть использован для Histogram и Timer.