Lightbend Telemetryでakka httpクライアントのモニタリングをする

Lightbend TelemetryはakkaやLogomなどのプロダクトに対するインストルメントとモニタリングを提供します。 今回はこのLightbend Telemetryを手軽に試せるDeveloper sandboxを使ってローカルでakka httpアプリケーションのモニタリングをしてみました。
2021.08.23

はじめに

マイクロサービスを始めとする、RPCによって密結合された分散システムの運用においては、その複雑さ故に各コンポーネントのモニタリングや分散トレーシングの重要度が非常に高くなっています。Lightbend TelemetryはakkaやLogomなどのプロダクトに対するインストルメントとモニタリングを提供します。

今回はこのLightbend Telemetryを手軽に試せるDeveloper sandbox を使ってローカルでakka http アプリケーションのモニタリングをしてみました。

今回の目的

以前の記事でサイジングしたコネクションプールの設定が妥当かどうか確認するためakka httpのコネクションプールの使用状況をLightbend Telemetryでモニタリングします。

アーキテクチャ

今回のアーキテクチャです。

Akka HTTP ClientとPrometheus exporterを同一のJavaプロセス上で動作させ、Docker 上で動作するPrometheusサーバがメトリクスをPULLします。ちなみにLightbend TelemetryのIntroductionにもあるとおり、Lightbend Telemetryでは今回使うバックエンド以外にも様々な構成にできます。

やったこと

Developer sandboxは簡単にモニタリング構成を構築できるのですが、とは言ってもやることが結構あります。ざっと書き出すと以下の通りです。

  • Lightbend commercial credentialsの取得
  • ビルドツールにプラグインを設定する
  • Developer sandboxの入手とセットアップ
  • Prometheus developer sandboxの入手とセットアップ
  • Grafana ダッシュボードの有効化

以下概ねガイドの通りに設定すればいいのですが、各設定が正しいかどうかわからなくて躓いたので確認ポイントを含めて概要を説明していきます。

Lightbend commercial credentialsの取得

Lightbend Telemetryのバックエンドプラグインを含むMavenリポジトリにアクセスするためにクレデンシャルが必要です。クレデンシャルは以下のステップで取得できます。

  1. Lightbendアカウントを作成する
  2. Credentialsを取得する

2.のページに各種ビルドツール用の設定スニペットが表示されるので、設定ファイルなどに貼り付けます。

ビルドツールにプラグインを設定する

使用するビルドツールに合わせてプラグインを設定します(sbtの場合はこちら )。

今回は以下のようになりました。この例ではakka httpクライアントがリクエストを送信する先のWEBサーバも同じプロジェクト内で作成するためプロジェクトが複数になっています(プロジェクトを分けないとターゲットのHTTPサーバでもexporterが起動してポートが重複するため)

project/plugins.sbt

addSbtPlugin("com.lightbend.cinnamon" % "sbt-cinnamon" % "2.16.1")

build.sbt

lazy val akkaHttpVersion = "10.2.5"
lazy val akkaVersion = "2.6.15"
lazy val lightbendKey = "XXXXXXXXXXXXXXXXXXXXXXXXXXX"

lazy val common = (project in file("./common"))
  .settings(
    scalaVersion := "2.13.6",
    libraryDependencies ++= Seq(
      "com.typesafe.akka" %% "akka-http" % akkaHttpVersion,
      "com.typesafe.akka" %% "akka-http-spray-json" % akkaHttpVersion,
      "com.typesafe.akka" %% "akka-actor-typed" % akkaVersion,
      "com.typesafe.akka" %% "akka-stream" % akkaVersion,
      "org.typelevel" %% "cats-effect" % "3.2.0",
      "ch.qos.logback" % "logback-classic" % "1.2.3"
    )
  )

lazy val client = (project in file("./client"))
  .settings(
    scalaVersion := "2.13.6",
    cinnamonLogLevel := "DEBUG",
    run / cinnamon := true,
    test / cinnamon := true,
    resolvers ++= Seq(
      "lightbend-commercial-mvn" at s"https://repo.lightbend.com/pass/$lightbendKey/commercial-releases"
    ),
    libraryDependencies ++= Seq(
      Cinnamon.library.cinnamonAkkaHttp,
      Cinnamon.library.cinnamonAkka,
      Cinnamon.library.cinnamonPrometheus,
      Cinnamon.library.cinnamonPrometheusHttpServer
    )
  )
  .dependsOn(common)
  .enablePlugins(Cinnamon)

lazy val server = (project in file("./server"))
  .settings(
    scalaVersion := "2.13.6"
  )
  .dependsOn(common)

Developer sandboxの入手とセットアップ

Developer sandboxのアーカイブを取得します。今回はprometheus-sandboxを使用しました。コンテナ上で動作するprometheus server はprometheus/prometheus.yml に記述されているホストをポーリングします。実際にexporterがバインドしているホスト、ポート番号と一致しているか確認します。

# Scrape configuration for default Cinnamon Prometheus HTTP Server on localhost
scrape_configs:
  - job_name: 'cinnamon'
    scrape_interval: 10s
    static_configs:
      - targets: ['host.docker.internal:9001'] # <- ここをクロールする

インストルメント/バックエンドプラグインを依存ライブラリに追加

取得したいインストルメントあるいは選択したバックエンドに応じたプラグインを依存ライブラリに追加します。sbt例は先ほど掲載したので省略します。

今回使ったakka http clientプラグインはデフォルトではメトリクスを送信しないのでドキュメントに従ってメトリクスを送信する対象となるリクエストの条件をapplication.confに記述しておきます (この振る舞いはドキュメントには一言も書いてなくて、JARの中のreference.confを読んでわかった...)

ひとまず全てのリクエストのメトリクスを送信する設定は下記の通りです。

application.conf

cinnamon {
  akka.http = {
    clients {
      "*:*" {
        paths {
          "*" {
            metrics = on
          }
        }
      }
    }
  }
}

上記の設定をした後にakka httpを使うプログラムを起動します。prometheusプラグインを設定した場合 http://localhost:9001/metrics にアクセスすることでexporterが公開しているメトリクスを確認できます。

curl -s http://localhost:9001 | head
# HELP akka_dispatcher_running_threads Runnning thread count
# TYPE akka_dispatcher_running_threads gauge
akka_dispatcher_running_threads{dispatcher="akka.actor.internal-dispatcher",actor_system="client",application="example.Client",host="HL00732",} 0.0
akka_dispatcher_running_threads{dispatcher="akka.actor.default-dispatcher",actor_system="client",application="example.Client",host="HL00732",} 0.0
akka_dispatcher_running_threads{dispatcher="akka.io.pinned-dispatcher",actor_system="client",application="example.Client",host="HL00732",} 0.0
# HELP akka_dispatcher_processed_tasks Processed task count
# TYPE akka_dispatcher_processed_tasks gauge
akka_dispatcher_processed_tasks{dispatcher="akka.actor.default-blocking-io-dispatcher",actor_system="client",application="example.Client",host="HL00732",} 14.0
# HELP akka_dispatcher_active_threads Active thread count
# TYPE akka_dispatcher_active_threads gauge

Grafana ダッシュボードの有効化

http://localhost:3000/ にアクセスしてCinnamon Prometheus プラグインを有効化します。有効化後にはダッシュボードが表示されるので設定したインストルメントを表示してみます。

まとめ

Lightbend Telemetry Developer sandboxを使ってakka http クライアントのメトリクスを収集してみました。ドキュメントに書かれている通りやったつもりでもうまくいかなことが多くてかなり時間がかかりましたが、必要な測定ができそうなのでこれを使ってコネクションプールのテストをしてみたいと思います。続く・・・