scaladogでScalaからDatadogにメトリクス・イベントを送信する
この記事は Scala Advent Calendar 2019 および Datadog Advent Calendar 2019 の21日目(遅刻)です。
scaladogとは?
scaladog は拙作のScala製 Datadog API のクライアントライブラリです。
HTTPでAPIを直接叩いているため、実行環境にDatadog Agentをインストールする必要はありません。
仕事でもプライベートでもScalaとDatadogにお世話になっているので、いっそのことクライアントライブラリを作ってみようと思ったのが開発を始めたきっかけです。 1
今回はDatadogの主要なユースケースであるメトリクスとイベントの送信を、scaladogで行う方法をお伝えしていきます。
準備
Datadog API を叩くには API Key
および、 Application Key
が必要になります。
これらのキーを取得する方法はこちらを参照してください。
キーを取得したら、これらを環境変数に設定します。
scaladogは DATADOG_API_KEY
, DATADOG_APP_KEY
環境変数に設定されたキーを読み込みます。
export DATADOG_API_KEY=<your-API-key> export DATADOG_APP_KEY=<your-Application-key>
また、今回のお見せするScalaコードの実行にはAmmoniteを使います。
以下コマンドで v1.8.22 をインストールします。
sudo sh -c '(echo "#!/usr/bin/env sh" && curl -L https://github.com/lihaoyi/Ammonite/releases/download/1.8.2/2.13-1.8.2) > /usr/local/bin/amm && chmod +x /usr/local/bin/amm' && amm
実行すると、Ammoniteの実行バイナリがダウンロードされたのち、REPLが起動します。
import $ivy
を使ってscaladogのライブラリをクラスパスに追加します。
import $ivy.`dev.nomadblacky::scaladog:0.4.2`
以下のようにライブラリ依存が追加されればOKです。
Loading... Welcome to the Ammonite Repl 1.8.2 (Scala 2.13.1 Java 1.8.0_231) If you like Ammonite, please support our development at www.patreon.com/lihaoyi @ import $ivy.`dev.nomadblacky::scaladog:0.4.2` https://repo1.maven.org/maven2/dev/nomadblacky/scaladog_2.13/0.4.2/scaladog_2.13-0.4.2.pom 100.0% [##########] 2.2 KiB (1.3 KiB / s) https://repo1.maven.org/maven2/dev/nomadblacky/scaladog_2.13/0.4.2/scaladog_2.13-0.4.2-sources.jar 100.0% [##########] 13.0 KiB (16.9 KiB / s) https://repo1.maven.org/maven2/dev/nomadblacky/scaladog_2.13/0.4.2/scaladog_2.13-0.4.2.jar 100.0% [##########] 264.9 KiB (273.4 KiB / s) import $ivy.$
続けてAPIクライアントとなるクラスのインスタンスを作成します。
@ val datadog = scaladog.Client()
datadog: scaladog.Client = scaladog.ClientImpl@5853495b
これで準備完了です!
カスタムメトリクスを送信する
まずはカスタムメトリクスを送信してみましょう。
以下のコードをREPLに入力します。
import scaladog.api.metrics._ import java.time.Instant import scala.util.Random while(true) { val series = Series( metric = "scaladog.example", points = Seq(Point(Instant.now(), Random.nextInt(1000))), tags = Seq("project:scaladog") ) datadog.metrics.postMetrics(Seq(series)) println(series) Thread.sleep(5000) }
5秒感覚でてきとうなメトリクスを送信するコードになっています。3
@ { // ←ブロックで複数行のコードを入力できます import scaladog.api.metrics._ import java.time.Instant import scala.util.Random while(true) { val series = Series( metric = "scaladog.example", points = Seq(Point(Instant.now(), Random.nextInt(1000))), tags = Seq("project:scaladog") ) datadog.metrics.postMetrics(Seq(series)) println(series) Thread.sleep(5000) } } Series(scaladog.example,List(Point(2019-12-21T14:59:56.537Z,689)),,List(project:scaladog),Gauge) Series(scaladog.example,List(Point(2019-12-21T15:00:02.277Z,484)),,List(project:scaladog),Gauge) Series(scaladog.example,List(Point(2019-12-21T15:00:08.033Z,550)),,List(project:scaladog),Gauge) Series(scaladog.example,List(Point(2019-12-21T15:00:13.749Z,470)),,List(project:scaladog),Gauge) Series(scaladog.example,List(Point(2019-12-21T15:00:19.425Z,682)),,List(project:scaladog),Gauge) Series(scaladog.example,List(Point(2019-12-21T15:00:25.129Z,219)),,List(project:scaladog),Gauge) Series(scaladog.example,List(Point(2019-12-21T15:00:30.858Z,440)),,List(project:scaladog),Gauge) Series(scaladog.example,List(Point(2019-12-21T15:00:36.576Z,269)),,List(project:scaladog),Gauge) Series(scaladog.example,List(Point(2019-12-21T15:00:42.258Z,213)),,List(project:scaladog),Gauge) Series(scaladog.example,List(Point(2019-12-21T15:00:47.951Z,180)),,List(project:scaladog),Gauge) Series(scaladog.example,List(Point(2019-12-21T15:00:53.677Z,615)),,List(project:scaladog),Gauge) Series(scaladog.example,List(Point(2019-12-21T15:00:59.412Z,377)),,List(project:scaladog),Gauge) Series(scaladog.example,List(Point(2019-12-21T15:01:05.119Z,303)),,List(project:scaladog),Gauge) Series(scaladog.example,List(Point(2019-12-21T15:01:11.103Z,40)),,List(project:scaladog),Gauge) Series(scaladog.example,List(Point(2019-12-21T15:01:16.821Z,147)),,List(project:scaladog),Gauge) Series(scaladog.example,List(Point(2019-12-21T15:01:22.506Z,899)),,List(project:scaladog),Gauge) Series(scaladog.example,List(Point(2019-12-21T15:01:28.289Z,347)),,List(project:scaladog),Gauge) Series(scaladog.example,List(Point(2019-12-21T15:01:33.990Z,241)),,List(project:scaladog),Gauge) Series(scaladog.example,List(Point(2019-12-21T15:01:39.657Z,716)),,List(project:scaladog),Gauge) Series(scaladog.example,List(Point(2019-12-21T15:01:45.680Z,706)),,List(project:scaladog),Gauge) Series(scaladog.example,List(Point(2019-12-21T15:01:51.393Z,191)),,List(project:scaladog),Gauge) Series(scaladog.example,List(Point(2019-12-21T15:01:57.118Z,696)),,List(project:scaladog),Gauge) ... // 飽きたら Ctrl+C で抜ける
Datadogの画面からメトリクスを送信できているか確認しましょう。
メトリクスを確認できました!
イベントを送信する
続けてイベントを送信してみましょう。
以下のコードをREPLに入力します。
scaladog.Client().events.postEvent( title = "TEST EVENT", text = "Hello, scaladog!" )
@ scaladog.Client().events.postEvent( title = "TEST EVENT", text = "Hello, scaladog!" ) res7: scaladog.api.events.PostEventResponse = PostEventResponse( "ok", 5245888207545475945L, "https://app.datadoghq.com/event/event?id=5245888207545475945" )
イベントのIDとURLが評価結果として返ってきていることがわかります。
Datadogの画面からイベントを確認してみましょう。
イベントが無事送信できていますね!
アラートの種類やタグの付与にも対応していますので、必要があれば以下のように追加できます。
scaladog.Client().events.postEvent( title = "TEST EVENT", text = "This is a test event.", dateHappened = Instant.now(), priority = Priority.Low, tags = Seq("project:scaladog"), alertType = AlertType.Warning )
活用例
これら以外のAPIも一部提供していますので、詳細はREADMEのコード例をご覧ください。
実際の利用例をご紹介しますと、社のブログ Scala Advent Calendar 6日目での、 esa.io の利用状況をDatadogに送信するScalaスクリプトにも scaladog が使われています。
また、お仕事でお世話になっているワークフローエンジンであるDigdagからDatadogを叩くための digdag-plugin-datadog を鋭意開発中です。
そのほか、sbtに組み込んでコンパイル時間やカバレッジを記録するのも面白いんじゃないかなぁと考えています。
あとがき
拙作のscaladogの紹介をしていきました。
まだまだサポートしているAPIは少ないのでこれから頑張って増やしていきたいです。
…とはいえ「このAPI使いたいな…じゃあ実装しよう!」というモチベーションから開発が始まるので、もし「このAPIをサポートしてほしい!」等あればIssueを投げてくれるときっと実装する気持ちになれると思います! 4
ぜひ、scaladogを使ってDatadogをカジュアルに使ってくれると嬉しいです!