読者です 読者をやめる 読者になる 読者になる

vague memory

うろ覚えを無くしていこうともがき苦しむ人の備忘録

Datadog DogPushの使い方

Datadog の Help でも紹介されている、Monitor の管理ツールの DogPush に触れる機会があったので、使い方をまとめます。

f:id:htnosm:20170402235739j:plain


目次


前提・注意事項

基本的には全Monitorが対象

タグ等による絞り込み機能はありません。 出力や比較には全 Monitor の定義が使用されます。

同名 Monitor は未サポート

Datadog の Monitor は 同名の物を定義できますが、dogpush では未サポートとなります。
Monitor 名称で管理しているため重複エラーとなります。 dogpush に限らず、 Datadog のツール系はこの制約に引っ掛かる事が多い気がします。

$ dogpush init
Duplicate name: MonitorTest4
Traceback (most recent call last):
  File "/usr/bin/dogpush", line 5, in <module>
    dogpush.main()
  File "/usr/lib/python2.7/site-packages/dogpush/dogpush.py", line 397, in main
    args.command()
  File "/usr/lib/python2.7/site-packages/dogpush/dogpush.py", line 215, in command_init
    remote_monitors = [m['obj'] for m in get_datadog_monitors().values()]
  File "/usr/lib/python2.7/site-packages/dogpush/dogpush.py", line 139, in get_datadog_monitors
    'Duplicate names found in remote datadog monitors.')
dogpush.dogpush.DogPushException: Duplicate names found in remote datadog monitors.

Message が空の Monitor は未サポート

f:id:htnosm:20170402235740p:plain

実運用ではあまり無いかと思いますが、 現バージョンでは本文部分が空の場合に失敗します。Web UI 上では空での作成は不可ですが、APIだと作成できてしまいます。
message 部分に以下のようなメッセージが含まれてしまい、出力内容をそのまま利用することができません。

- message: !!python/unicode ''

一見上記部分を排除すれば利用できそうですが、重複エラーに引っ掛かります。

インストール

README を参考にインストールを行います。 今回は素に近い CentOS7 で試してます。必要パッケージは環境により変わると思います。

$ cat /etc/redhat-release
CentOS Linux release 7.3.1611 (Core)
$ python -V
Python 2.7.5
$ sudo yum install python2-pip openssl-devel python-devel libffi-devel
・・・
Complete!
$ pip -V
pip 8.1.2 from /usr/lib/python2.7/site-packages (python 2.7)
$ sudo pip install -U pip dogpush
・・・
Successfully installed PyYAML-3.12 datadog-0.15.0 decorator-4.0.11 dogpush-0.3.3 pip-9.0.1 pytz-2017.2 requests-2.13.0 simplejson-3.10.0
$ pip -V
pip 9.0.1 from /usr/lib/python2.7/site-packages (python 2.7)
$ dog -v
dog 0.15.0
$ dogpush -h
usage: dogpush [-h] [--config CONFIG] {init,push,diff,mute} ...

positional arguments:
  {init,push,diff,mute}
                        sub-command help
    init                init new alerts file
    push                push monitors to datadog
    diff                show diff between local monitors and datadog
    mute                Mute alerts based on their `mute_when` key

optional arguments:
  -h, --help            show this help message and exit
  --config CONFIG, -c CONFIG
                        configuration file to load (default: ./config.yaml)

datadog パッケージが依存関係として含まれるため、 dogshell(dogコマンド)もインストールされます。
尚、後述 delete_untracked オプションで記載していますが、バージョンが古いようでしたので再度 GitHub からインストールし直しています。

config.yaml ファイル

Datadog の Key 情報を定義する config.yaml が無いとエラーとなります。

$ dogpush init
Traceback (most recent call last):
  File "/usr/bin/dogpush", line 3, in <module>
    from dogpush import dogpush
  File "/usr/lib/python2.7/site-packages/dogpush/dogpush.py", line 391, in <module>
    CONFIG = _load_config(args.config)
  File "/usr/lib/python2.7/site-packages/dogpush/dogpush.py", line 29, in _load_config
    with open(config_file, 'r') as f:
IOError: [Errno 2] No such file or directory: './config.yaml'

config.yaml の作成

Datadog の API Key、App Key を記載します。

cat <<_EOF > config.yaml
datadog:
  api_key: XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
  app_key: xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
_EOF

デフォルトルール(default_rules)

パラメータ未指定時の既定値となる値を指定します。 README 上は multi,message とありますが、 実際は multi,type かと思います。

ルール 既定値 内容
multi False Multi アラートか否か {true, false}
type metric alert モニターのタイプ {metric alert, service check, event alert}

init,diff 時は config で指定した値は未出力となり、 push 時は既定値として設定されます。 そのため、本来 metric alert である設定項目に対し、service check をデフォルト値とした場合等はAPIエラーとなります。

$ dogpush push
Pushing 1 new monitors.
Traceback (most recent call last):
  File "/usr/bin/dogpush", line 5, in <module>
    pkg_resources.run_script('DogPush==0.3.3', 'dogpush')
  File "/usr/lib/python2.7/site-packages/pkg_resources.py", line 540, in run_script
    self.require(requires)[0].run_script(script_name, ns)
  File "/usr/lib/python2.7/site-packages/pkg_resources.py", line 1455, in run_script
    execfile(script_filename, namespace, namespace)
  File "/usr/lib/python2.7/site-packages/DogPush-0.3.3-py2.7.egg/EGG-INFO/scripts/dogpush", line 5, in <module>
    dogpush.main()
  File "/usr/lib/python2.7/site-packages/DogPush-0.3.3-py2.7.egg/dogpush/dogpush.py", line 407, in main
    args.command(args)
  File "/usr/lib/python2.7/site-packages/DogPush-0.3.3-py2.7.egg/dogpush/dogpush.py", line 230, in command_push
    datadog.api.Monitor.create(**_prepare_monitor(local_monitors[name]))
  File "/usr/lib/python2.7/site-packages/datadog/api/resources.py", line 40, in create
    attach_host_name=attach_host_name, **params)
  File "/usr/lib/python2.7/site-packages/datadog/api/api_client.py", line 150, in submit
    raise ApiError(response_obj)
datadog.api.exceptions.ApiError: {'errors': ["The value provided for parameter 'query' is invalid"]}

デフォルトルールオプション(default_rule_options)

使い方がわかりませんでした。 config.yaml へ記述すると AssertionError となってしまい、利用できませんでした。
ルールファイル(〜.yaml) へ記述して既定値を設定するのかと思いましたが、ルールファイルへの記述は無視されました。

チーム(teams)

通知設定を記述できます。 config.yaml へ通知先の指定を行い、各ルールファイルの先頭で定義したteamを指定します。
各 monitor 設定で severity を指定することで通知先の振分が行えます。

  • config.yamlへの記載例
    • シングルクォート囲み必須
    • servirity は CRITICAL がデフォルト、その他は任意文字列可
teams:
  team-A:
    notifications:
      CRITICAL: '@hoge@example.com @slack-XXXXX'
      WARNING: '@hoge@example.com'
      INFO: '通知無し'
      FATAL: 'Fatal @all'
  team-B:
    notifications:
      CRITICAL: '@hoge@example.com'
  • ルール yaml への記載例(team)
$ head -n 3 monitors.team*
==> monitors.team1.yaml <==
team: team-A

alerts:

==> monitors.team2.yaml <==
team: team-B

alerts:
  • ルール yaml への記載例(severity)
- message: 'Test Team Alert 1-1'
  name: TeamAlert1-1
  options: {new_host_delay: 300, require_full_window: true, thresholds: {critical: 50.0, warning: 30.0}}
  query: avg(last_5m):max:system.cpu.user{*} by {host} >= 50

- message: 'Test Team Alert 1-2'
  name: TeamAlert1-2
  options: {new_host_delay: 300, require_full_window: true, thresholds: {critical: 50.0, warning: 30.0}}
  query: avg(last_5m):max:system.cpu.user{*} by {host} >= 50
  severity: WARNING

- message: 'Test Team Alert 1-3'
  name: TeamAlert1-3
  options: {new_host_delay: 300, require_full_window: true, thresholds: {critical: 50.0, warning: 30.0}}
  query: avg(last_5m):max:system.cpu.user{*} by {host} >= 50
  severity: INFO

- message: 'Test Team Alert 1-4'
  name: TeamAlert1-4
  options: {new_host_delay: 300, require_full_window: true, thresholds: {critical: 50.0, warning: 30.0}}
  query: avg(last_5m):max:system.cpu.user{*} by {host} >= 50
  severity: FATAL

message 末尾に通知設定を追加することができます。

{"name":"TeamAlert1-1","message":"Test Team Alert 1-1\n@hoge@example.com @slack-XXXXX"}
{"name":"TeamAlert1-2","message":"Test Team Alert 1-2\n@hoge@example.com"}
{"name":"TeamAlert1-3","message":"Test Team Alert 1-3\n通知無し"}
{"name":"TeamAlert1-4","message":"Test Team Alert 1-4\nFatal @all"}

init コマンド

全 Monitor を対象とした YAML を出力します。
絞り込みのオプションはありません。

usage: dogpush init [-h]

実行例

そのまま実行すると標準出力となるため、リダイレクトなどでファイル出力とすることになると思います。

$ dogpush init
# team: TEAMNAME

alerts:

- message: 'Test2: alert message to @hoge@example.com'
  multi: true
  name: MonitorTest2
  options: {new_host_delay: 300, notify_no_data: false, require_full_window: true}
  overall_state_modified: 'yyyy-mm-ddThh:mm:ss.560069+00:00'
  query: avg(last_5m):max:system.cpu.user{*} by {host} >= 50

- message: 'Test3: alert message to @hoge@example.com'
  multi: true
・・・略
$ dogpush init > my_monitors.yaml
$

diff コマンド

Datadog 上の Monitor 登録内容とローカルのYAMLとの比較を行います。
対象とする monitor 定義(ここでは my_monitors.yaml) を config.yaml へ追加した上で利用します。

cat <<_EOF >> config.yaml
rule_files:
- my_monitors.yaml
_EOF

差分が無い場合は何も出力されません。

$ dogpush diff
$

差分がある場合は diff 結果が出力されます。

$ dogpush diff
---------------------------------------------------------
 TO BE UPDATED.  These monitors exist in datadog, but are
 different than the local version.  Use "dogpush push"
 to push them to datadog.
---------------------------------------------------------

--- datadog:MonitorTest2
+++ /home/vagrant/dogpush/my_monitors.yaml:MonitorTest2
@@ -1,4 +1,4 @@
-message: 'Test2: alert message to @hoge@example.com'
+message: 'Test2: alert message to @hoge@example.com Update'
 multi: true
 name: MonitorTest2
 options: {new_host_delay: 300, notify_no_data: false, require_full_window: true}
$

差分が name の場合は更新ではなく、新規追加として扱われます。

$ dogpush diff
---------------------------------------------------------
 NEW MONITORS.  These monitors are currently missing in
 datadog and can be pushed using "dogpush push"
---------------------------------------------------------

- message: MonitorTest1
  multi: true
  name: MonitorTest1 Update
  options:
    new_host_delay: 300
    no_data_timeframe: 2
    notify_no_data: false
    renotify_interval: 0
    require_full_window: true
    thresholds: {critical: 50.0}
    timeout_h: 0
  overall_state_modified: 'yyyy-mm-ddThh:mm:ss.560069+00:00'
  query: avg(last_5m):max:system.cpu.user{*} by {host} >= 50

------------------------------------------------------------
 UNTRACKED MONITORS.  These monitors are only in datadog
 and needed to be MANUALLY added to a local file or removed
 from datadog.
------------------------------------------------------------

- message: MonitorTest1
  multi: true
  name: MonitorTest1
  options:
    new_host_delay: 300
    no_data_timeframe: 2
    notify_no_data: false
    renotify_interval: 0
    require_full_window: true
    thresholds: {critical: 50.0}
    timeout_h: 0
  overall_state_modified: 'yyyy-mm-ddThh:mm:ss.560069+00:00'
  query: avg(last_5m):max:system.cpu.user{*} by {host} >= 50

*** FAILED *** Untracked monitors found.

push コマンド

Datadog 上の Monitor へローカルのYAMLの変更点を反映します。
対象とする monitor を config.yaml へ追加した上で利用します。

usage: dogpush push [-h]
$ dogpush push
Pushing 1 new monitors.
Updating 1 modified alerts

削除は行われません。 その為、 nameの変更を行った場合は別途削除が必要になります。

  • name を更新した場合、更新前の情報が残る
------------------------------------------------------------
 UNTRACKED MONITORS.  These monitors are only in datadog
 and needed to be MANUALLY added to a local file or removed
 from datadog.
------------------------------------------------------------

- message: MonitorTest1
  multi: true
  name: MonitorTest1
  options:
    new_host_delay: 300
    no_data_timeframe: 2
    notify_no_data: false
    renotify_interval: 0
    require_full_window: true
    thresholds: {critical: 50.0}
    timeout_h: 0
  overall_state_modified: 'yyyy-mm-ddThh:mm:ss.560069+00:00'
  query: avg(last_5m):max:system.cpu.user{*} by {host} >= 50

*** FAILED *** Untracked monitors found.

delete_untracked オプション

yaml に含まれていない monitor を削除するオプションです。
pip からインストールした物は少々バージョンが古いようで、使用できませんでした。

$ dogpush push --delete_untracked
usage: dogpush [-h] [--config CONFIG] {init,push,diff,mute} ...
dogpush: error: unrecognized arguments: --delete_untracked

GitHub 上では追加されているようでしたので、 git clone して再導入します。

# pip でインストールしたバージョンの削除
$ sudo pip uninstall dogpush
Uninstalling DogPush-0.3.3:
  /usr/bin/dogpush
  /usr/lib/python2.7/site-packages/DogPush-0.3.3-py2.7.egg
Proceed (y/n)? y
  Successfully uninstalled DogPush-0.3.3
# GitHub からインストール
$ git clone https://github.com/trueaccord/DogPush.git
$ cd DogPush
$ sudo python setup.py install
・・・
Finished processing dependencies for DogPush==0.3.3
# dlete_untracked オプションが追加されていることを確認
$ dogpush push -h
usage: dogpush push [-h] [-d]

optional arguments:
  -h, --help            show this help message and exit
  -d, --delete_untracked
                        Delete untracked monitors.

オプションを付けた状態で実行すると monitor の削除が行われます。

$ dogpush push --delete_untracked
Deleting 1 untracked monitors.
$ dogpush diff
$

mute コマンド

mute_tags を定義済みの Monitor へ Downtime を設定します。

usage: dogpush mute [-h]

mute_tags 定義

config.yaml へ mute 対象時間帯の定義を行い、各 monitor 設定で mute_when を指定することで mute 対象モニターとします。

  • config.yamlへの記載例
mute_tags:
  mute_a:
    timezone: Asia/Tokyo
    expr: now.hour < 10 or now.hour > 19
  • ルール yaml への記載例(mute_when)
- message: 'Test MuteAlert'
  name: MuteAlert
  options: {new_host_delay: 300, require_full_window: true, thresholds: {critical: 50.0, warning: 30.0}}
  query: avg(last_5m):max:system.cpu.user{*} by {host} >= 50
  mute_when: mute_a
  • 実行例
$ dogpush mute
Muting alert 'MuteAlert' until yyyy-mm-dd 10:00:00+09:00

対象モニターが mute 状態となります。

f:id:htnosm:20170402235741p:plain

Downtimes でも確認できます。

f:id:htnosm:20170402235742p:plain

まとめ

Datadog 公式の dogshell には monitor の pull/push がありません(ダッシュボード screenboard/timeboard 操作は用意されていますが、 monitor はありません。)ので、 その部分を補完できると思います。
注意事項に記載した通りいくつか制約はありますが、 YAML での記述となるので、JSONファイルよりは扱い易いかと思いました。