Playでいい感じにZipkinするライブラリを公開しました

PlayでZipkinでトレースするライブラリには以下のようなものがあるのですが、どれも用途が限られていたり、Playとのインテグレーションが不十分だったりします。

そんな背景もあり、同僚がPlayでいい感じにZipkinを利用できるようにするためのライブラリを社内向けに作成していたので、これをエンハンスしてOSSとして公開してみました。

github.com

まずはbuild.sbtに以下の依存関係を追加します。

libraryDependencies ++= Seq(
  "jp.co.bizreach" %% "play-zipkin-tracing-play25" % "1.0.0"
)

さらにapplication.confに以下のような設定を追加します。

play.http.filters=filters.Filters

trace {
  service-name = "zipkin-api-sample"

  zipkin {
    host = "localhost"
    port = 9410
    sample-rate = 0.1
  }
}

zipkin-trace-context {
  fork-join-executor {
    parallelism-factor = 20.0
    parallelism-max = 200
  }
}

play.modules.enabled  += "jp.co.bizreach.trace.play25.module.ZipkinModule"

filter.FiltersZipkinTraceFilterを追加します。

package filters

import javax.inject.Inject
import jp.co.bizreach.trace.play25.filter.ZipkinTraceFilter
import play.api.http.DefaultHttpFilters

class Filters @Inject() (
  zipkinTraceFilter: ZipkinTraceFilter
) extends DefaultHttpFilters(zipkinTraceFilter)

ここまでで準備完了です。コントローラーでは以下のようにWSClientの代わりにTraceWSClientをDIして使用することでAPI呼び出しのトレースを行うことができます。

package controllers

import play.api.mvc.{Action, Controller}
import play.api.libs.json.Json
import jp.co.bizreach.trace.play25.{TraceWSClient, ZipkinTraceService}
import jp.co.bizreach.trace.play25.implicits.ZipkinTraceImplicits
import scala.concurrent.ExecutionContext
import javax.inject.Inject

class ApiController @Inject() (ws: TraceWSClient)
  (implicit val tracer: ZipkinTraceServiceLike, val ec: ExecutionContext)
    extends Controller with ZipkinTraceImplicits {

  def test = Action.async { implicit request =>
    ws.url("hello-api-call", "http://localhost:9992/api/hello")
      .get().map { res => Ok(res.json) }
  }

}

また、ZipkinTraceServiceLikeのメソッドを使用してAPI呼び出し以外の処理のトレース情報を取得することも可能です。

// 同期処理のトレース
def test1 = Action { implicit request =>
  tracer.trace("sync"){
    println("Hello World!")
    Ok(Json.obj("result" -> "ok"))
  }
}

// Futureによる非同期処理のトレース
def test2 = Action.async { implicit request =>
  tracer.traceFuture("async"){
    Future {
      println("Hello World!")
      Ok(Json.obj("result" -> "ok"))
    }
  }
}

なお、このライブラリは諸事情によりPlay 2.3〜2.5に対応しています。バージョンのよって利用方法が少々異なりますので詳細については各バージョン向けのREADMEを参照してください。

このライブラリはBrave 4(Java向けのZipkinクライアントライブラリ)を使用して実装されています。Brave 4はBrave 3からAPIが大幅に変更されているので、このライブラリはBrave 4の使い方の参考のもなるのではないかと思います。