В какой то момент разработки приложения, каждый из нас приходит к тому, что нам нужно больше информации о том, что происходит внутри приложения или же в возможности мониторить приложение. В случае с 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
.
Автор: Timur_Kh