Posted at

kamon-mackerelでJVMで動くアプリケーションを監視しよう

Mackerel Advent Calendar 2018 の2日目の記事っす。よろしくお願いいたします。

Kamon は、JVM上で動作するアプリケーションの監視ツールキットです。

特定のベンダーに決められることなく、Metricsや、Tracing、Context Propagation APIs を提供してくれるツールキットです。

公式では、 StatsD, Prometheus, Kamino, Datadog, Zipkin, Jaeger などをサポートしておりますが、Mackerelがそこにありませんでしたので、ちょっと作ってみるかってことで、作りましたので、ご紹介させていただきます。

yoshiyoshifujii/kamon-mackerel


How to use

JVMで動くアプリケーションといっておりますが、基本、Scalaで書いたコードをJVMで実行するのを想定してlibraryを作っておりますので、ここでは、Scalaでどうやって組んでいけばメトリクスをMackerelで確認できるのか、手順を記載していきます。


sbt new

まずは、サンプルとして、プロジェクトを作成します。

今回は、簡単なWeb APIの雛形として、 akka/akka-http-quickstart-scala.g8 を作って、組んでみたいと思います。

なお、事前に、sbt、JVMがインストールされている前提となります。

私の環境では、


  • AdoptOpenJDK v1.8.0_192

  • sbt 1.2.6

がインストールされています。

それでは、以下のコマンドを実行します。

$ sbt new akka/akka-http-quickstart-scala.g8

すると、以下のようにだーっと出力されて、

Getting org.scala-sbt sbt 1.2.6  (this may take some time)...

downloading file:////Users/yoshiyoshifujii/.sbt/preloaded/org.scala-sbt/sbt/1.2.6/jars/sbt.jar ...
[SUCCESSFUL ] org.scala-sbt#sbt;1.2.6!sbt.jar (11ms)
...

で、以下の入力待ち状態になりますので、それぞれ、適切に入力したりEnterします。

This is a seed project which creates a basic build for an Akka HTTP

application using Scala.

name [My Akka HTTP Project]: example-akka-http
scala_version [2.12.7]:
akka_http_version [10.1.5]:
akka_version [2.5.18]:
organization [com.example]:
package [com.example]:

すると、直下に、 example-akka-http というディレクトリが出来ていますので、これでベースとなるプロジェクトができます。


IntelliJ IDEAで開く

作ったプロジェクトをIDEAで開きます。

Welcome_to_IntelliJ_IDEA.png

Import Project をクリックして、

Import_Project.png

sbtを選んで、Nextを押します。

Import_Project2.png

JDKは、1.8とか適切なのを選んで、Finishしますと、プロジェクトが開きます。

最初は、IntelliJ IDEAが色々と依存関係を成立させるためにダウンロードだなんだと時間がかかりますが、それを待ちます。


kamon-mackerelを依存関係に追加する

IntelliJ IDEAの初回ロードが終わりましたら、次に、build.sbtを開いて、kamon-mackerelを依存関係に追加します。

IDEAで、build.sbtを開きます。


build.sbt

lazy val akkaHttpVersion = "10.1.5"

lazy val akkaVersion = "2.5.18"

lazy val root = (project in file(".")).
settings(
inThisBuild(List(
organization := "com.example",
scalaVersion := "2.12.7"
)),
name := "example-akka-http",
libraryDependencies ++= Seq(
"com.typesafe.akka" %% "akka-http" % akkaHttpVersion,
"com.typesafe.akka" %% "akka-http-spray-json" % akkaHttpVersion,
"com.typesafe.akka" %% "akka-http-xml" % akkaHttpVersion,
"com.typesafe.akka" %% "akka-stream" % akkaVersion,

"com.typesafe.akka" %% "akka-http-testkit" % akkaHttpVersion % Test,
"com.typesafe.akka" %% "akka-testkit" % akkaVersion % Test,
"com.typesafe.akka" %% "akka-stream-testkit" % akkaVersion % Test,
"org.scalatest" %% "scalatest" % "3.0.5" % Test
)
)


このあたりに加えましょう。

    libraryDependencies ++= Seq(

"com.typesafe.akka" %% "akka-http" % akkaHttpVersion,
"com.typesafe.akka" %% "akka-http-spray-json" % akkaHttpVersion,
"com.typesafe.akka" %% "akka-http-xml" % akkaHttpVersion,
"com.typesafe.akka" %% "akka-stream" % akkaVersion,
"io.kamon" %% "kamon-core" % "1.1.0", // <= ここ!!
"io.kamon" %% "kamon-akka-http-2.5" % "1.0.1", // <= ここ!!
"com.github.yoshiyoshifujii" %% "kamon-mackerel" % "0.1.0", // <= ここ!!

"com.typesafe.akka" %% "akka-http-testkit" % akkaHttpVersion % Test,
"com.typesafe.akka" %% "akka-testkit" % akkaVersion % Test,
"com.typesafe.akka" %% "akka-stream-testkit" % akkaVersion % Test,
"org.scalatest" %% "scalatest" % "3.0.5" % Test
)

すると、 Import Changes って出てきますので、それを押します。

example-akka-http____workspace_git_yoshiyoshifujii_example-akka-http__-_____build_sbt__example-akka-http_.png


sbt-aspectj-runnerをpluginに追加

https://github.com/kamon-io/sbt-aspectj-runner のREADMEを参照し、 project/plugins.sbt に以下を追記する。


project/plugins.sbt

resolvers += Resolver.bintrayRepo("kamon-io", "sbt-plugins")

addSbtPlugin("io.kamon" % "sbt-aspectj-runner" % "1.1.0")


KamonにReporterを追加

Mainとなる com.example.QuickstartServer を開きます。

以下のようにimport文を追記して、Reporterを追加します。

...

import kamon.Kamon
import kamon.mackerel.MackerelAPIReporter

//#main-class
object QuickstartServer extends App with UserRoutes {
Kamon.addReporter(new MackerelAPIReporter())
...

さらに、 application.confsrc/main/resources 直下に作成します。


application.conf

kamon {

mackerel {

#
# Settings relevant to the MackerelAPIReporter
#
http {

# Mackerel API key to use to send metrics to mackerel directly over HTTPS.
api-key = ""
}

host {
id = ""
}

}
}


上記のように、api-keyとhostのidをconfigに設定しておく必要がありますので、Mackerelを開いて、それぞれ取得してきます。


Mackerelから設定値を取得

Mackerelを開いて、api-keyを取得します。

Kamon_·_Kamon.png


Hostを登録

Mackerelでは、エージェントをインストールすることでHostを登録するかと思いますが、今回は、APIを使ってHostを登録したいと思います。

ドキュメントは、こちら。 https://mackerel.io/ja/api-docs/entry/hosts#create

以下のcurlコマンドを実行します。

$ curl -i -X POST https://api.mackerelio.com/api/v0/hosts \

-H X-Api-Key:XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX \
-H Content-Type:application/json \
-d '{"name":"host_name_1","meta":{}}'

すると、 200 OK で返ってきたら登録OKです。

HTTP/1.1 200 OK

...
{"id":"YYYYYYYYYYY"}%

この表示されているIDが、HostIDですので、こちらも使います。

これで、 api-key と、 host-id を取得できました。


Akka HTTPを起動

sbtを起動して、 run を実行します。

$ cd example-akka-http/

$ sbt run
...
[info] Running com.example.QuickstartServer
23:37:29.340 [kamon.mackerel.MackerelAPIReporter] INFO kamon.mackerel.MackerelAPIReporter - Started the Mackerel API reporter.
Server online at http://127.0.0.1:8080/

以下のcurlを実行すると、いろいろとアクセスできます。

$ curl -i -X GET http://localhost:8080/users                                                                                                                                                      [~]

HTTP/1.1 200 OK
X-B3-TraceId: db805a66b23110ec
X-B3-Sampled: 0
X-B3-SpanId: 5388c20a0e8292b3
Server: akka-http/10.1.5
Date: Thu, 22 Nov 2018 14:42:14 GMT
Content-Type: application/json
Content-Length: 12

{"users":[]}%

$ curl -i -X POST http://localhost:8080/users -H Content-Type:application/json -d '{"name":"hoge","age":10,"countryOfResidence":"ooo"}' [~]
HTTP/1.1 201 Created
X-B3-TraceId: 4eb323d6196145e8
X-B3-Sampled: 0
X-B3-SpanId: dbfc829b7f2499b0
Server: akka-http/10.1.5
Date: Thu, 22 Nov 2018 14:45:45 GMT
Content-Type: application/json
Content-Length: 36

{"description":"User hoge created."}%


MackerelでMetricsを確認

Mackerelを開いて、HostのMetricsを確認してみます。

スクリーンショット_2018-11-22_23_47_44.png

うん。なんか出てます。


まとめ

各メトリクスの内容については、Actorの数とかが可視化されたりしてます。

他にも、JVMを可視化する kamon-jmx を入れたりすることも可能ですので、色々とKamonのMetrics収集を組み込んだうえで、Mackerelで可視化するライフが送れると思います。

当記事を作成するにあたり作ったサンプルのコードは、 https://github.com/yoshiyoshifujii/example-akka-http です。

以上です。