RでDatadogのデータを取得するパッケージをCRANで公開しました

ドーモ、SREチームの湯谷(@yutannihilation)です。ニンジャスレイヤー7周年おめでとうございます。

Wantedlyの募集ページにも画面が映りこんでいますが、SREチームではDatadogも使っています。

Datadogはグラフ描画も高機能で便利ですが、やはり慣れ親しんだRでグラフが描きたい。誰しもそんな気持ちになることもありますよね。ということで、datadogrというパッケージをつくりました。

https://cran.r-project.org/package=datadogr

インストール

datadogrはCRANにリリースされているのでinstall.packages()でインストールできます。

install.packages("datadogr")

使い方

認証

datadogrパッケージを使うにはまず、DATADOG_API_KEYという環境変数にAPIキーを設定します。これは、.Renvironに書いておくか、k9_auth()でインタラクティブに設定するという方法があります。

library(datadogr)

k9_auth()

上のコードを実行するとポップアップが出てきます。ここにAPIキーを入力するとDATADOG_API_KEY環境変数に設定してくれます。

f:id:cybozuinsideout:20170725084905p:plain

ちなみに、datadogrパッケージの関数にはすべてk9_というプレフィックスがつきますが、K9というのはDoctor WhoというBBCのSFドラマに出てくる機械の犬です。「Datadog」という言葉から私はこれを連想しました。

実は、もともとパッケージ名もK9にしていたんですが、パッケージの審査で「分かりにくくね??」(意訳)というツッコミを受けたので無難なパッケージ名にフォールバックしました。うう…

メトリクス名の一覧を取得

k9_list_metrics()を使うと、メトリクス名の一覧を取得できます。デフォルトだと直近1時間に値のあるメトリクス名が返ってきます。例えば、IO関連のメトリクスは以下のようなものです。

library(tidyverse)

k9_list_metrics() %>%
  stringr::str_subset("^system.io")
#> This API is rate-limited and you have 98 requests left (reset after 2555 seconds)
#> 
#>  [1] "system.io.avg_q_sz"  "system.io.avg_rq_sz" "system.io.await"     
#>  [4] "system.io.r_await"   "system.io.r_s"       "system.io.rkb_s"
#>  [7] "system.io.rrqm_s"    "system.io.svctm"     "system.io.util"
#> [10] "system.io.w_await"   "system.io.w_s"       "system.io.wkb_s"
#> [13] "system.io.wrqm_s" 

メトリクスを取得

k9_get_metrics()を使うとメトリクスを取得できます。

Datadogからメトリクスを取り出すには独自のクエリの記法があります(参考:Graphing Primer using JSON)。基本的には、

メトリクス名{スコープ} by {グループ}

という形式になります。

メトリクス名は上で取得したsystem.io.r_sのようなものです。スコープは、メトリクスを絞り込むためのもので、role:dbのようなタグを指定します。グループはメトリクスをどのように分けるかを指定するもので、たとえばホストごとのメトリクスが見たい場合はhostを指定します。

例として、roleタグがdbかつgroupタグがtest1のホストのsystem.io.r_sを、各ホストのデバイス単位で見たい、という場合を考えてみます。クエリは以下のようになります。

system.io.r_s {role:db, group:test1} by {host, device}

これをk9_get_metrics()のクエリ引数に指定すると、欲しいメトリクスが取得できます。デフォルトだと直近1日分のメトリクスが取得できます。

d <- k9_get_metrics(
  query = "system.io.r_s {role:db, group:test1} by {host, device}"
)

結果はデータフレーム形式になっています。タイムスタンプと値、それにスコープやグループに指定した属性値が入っています。

glimpse(d)
Observations: 26,588
Variables: 11
$ timestamp    <dttm> 2017-07-23 22:30:00, 2017-07-23 22:35:00, 2017-07-23 22:40:00, 2017-07-23 22:45:00, 2017-07-23 ...
$ value        <dbl> 0.00000000, 0.00000000, 0.00000000, 0.00000000, 0.00000000, 0.00000000, 0.00000000, 0.00000000, ...
$ metric       <chr> "system.io.r_s", "system.io.r_s", "system.io.r_s", "system.io.r_s", "system.io.r_s", "system.io....
$ display_name <chr> "system.io.r_s", "system.io.r_s", "system.io.r_s", "system.io.r_s", "system.io.r_s", "system.io....
$ query_index  <int> 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ...
$ interval     <int> 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 3...
$ device       <chr> "sdb", "sdb", "sdb", "sdb", "sdb", "sdb", "sdb", "sdb", "sdb", "sdb", "sdb", "sdb", "sdb", "sdb"...
$ group        <chr> "test1", "test1", "test1", "test1", "test1", "test1", "test1", "test1", "test1", "test1", "test1...
$ host         <chr> "db-34", "db-34", "db-34", "db-34", "db-34", "db-34", "db-34", "db-34", "db-34", "db-34", "db-34...
$ role         <chr> "db", "db", "db", "db", "db", "db", "db", "db", "db", "db", "db", "db", "db", "db", "db", "db", ...
$ expression   <chr> "system.io.r_s{device:sdb,group:test1,host:db-34,role:db}", "system.io.r_s{device:sdb,group:test...

このクエリを文字列として組み立てるのは面倒なので、k9_get_metrics()にはquery引数の代わりにmetricscopeby引数を指定することもできます。以下のコードは上と同じリクエストを送ります。

k9_get_metrics(
  metric = "system.io.r_s",
  scope = list(role = "db", group = "test1"),
  by = c("host", "device")
)

他にも、fromto引数でメトリクス取得の期間を変えたり、.split_request引数でリクエストを日ごとに分割するかどうかを選べたりします。詳しくはドキュメント(?k9_get_metrics)をご参照ください。

グラフを描く

このデータを使って、最近はやりのjoyplot*1を描いてみましょう。ggjoyパッケージを使います。

library(ggjoy)

# ホスト名を並べ替え
x <- d %>%
  mutate(host = factor(host, levels = naturalsort::naturalsort(unique(.$host))))

ggplot(x, aes(value, host)) +
  geom_joy(fill = "tomato", colour = "white", alpha = 0.8) +
  facet_wrap(~ device) +
  scale_x_sqrt(limits = c(NA, 100)) +
  theme_minimal() +
  labs(title = "system.io.r_sの分布",
       subtitle = "role:db, group:test1")

f:id:cybozuinsideout:20170725084937p:plain

ちなみに、scale_x_log10()(対数スケール)ではなくscale_x_sqrt()になっているのは、メトリクスにゼロが多くてlogだとエラーになるからです。 ゼロが多いのは当然で、よく使われるデータが正しくメモリに載っていれば読み取りのIOは発生しません。 逆に言うと、メトリクスが横長に這いつくばっているホストがいくつかいますが、これは読み取りIOが発生しているのでチューニングの余地があるという兆候です。

Datadogも便利なんですけど、こんな感じで多数のホストのグラフをひたすら並べていく、みたいなときはやっぱりRがやりやすいですね。

最後に

何かあれば、GitHubレポジトリのIssuesTwitterでお知らせいただけると助かります。

SREチームではDatadogをバリバリ使い倒せる人、私ならRのグラフにも勝てる!という猛者を募集しています。募集要項はこちらです。

*1:Joy Divisionのアルバム「Unknown Pleasures」のジャケットに似ていることから名付けられたグラフ。確率密度曲線を所狭しと並べていく。