これはなんですか
- Datadog Agent 設定でプロセス監視をするときにたまに使う
exact_match
キーについて調べたのでメモとして残しておく - これを読めば、どんなときに
exact_match: false
を設定すれば良いかが分かるようになるはず
先に結論
-
exact_match: true
のときはプロセス名を検索するが、何かしらのプログラム上でデーモンとして動いている場合に検索がうまく効かないことがある - ruby だったり java だったりのデーモンとして動いているプロセスについては、
exact_match: false
を設定した上でマッチング文字列にプロセス起動時のコマンドの一部を指定する- ex) td-agent は ruby のデーモンとして動作するので、コマンドを指定する必要がある
- プロセス起動時のコマンドは
ps -ef
で確認できる。また、各プロセスのプロセス名はps -ef c
で確認できる
背景
- Datadog で td-agent のプロセス監視をするとき、多くの場合は
exact_match: false
という項目が必要となる - なんでだろうと思って気になったので調べてみた。
前提: Datadog における Process Checks
Datadog Agent の Config に Process Check を設定することで、特定プロセスの死活状況やプロセス数、プロセスのリソース使用状況が取得できるようになる。
exact_match
を調べてみた
ドキュメントを読む
Process Check では、いわゆるプロセス名をプロセス一覧から検索してPIDを取得し、各種メトリクスを収集する。 exact_match
はプロセス一覧の検索に関わるオプションで、ドキュメント内では次のように説明されている:
By setting exact_match to False in your yaml file, the agent looks at the command used to launch your process and recognizes every process that contains your keywords.
つまり、exact_match: false
とすることで、検索対象をプロセス名ではなくプロセス起動時のコマンドに変えることができる。
Datadog Agent の コードを読む
実際にどんな処理が行われているかを知るため、Datadog Agent のコードを読んでみた。すると、次の様に psutil.Process()
を使ってプロセス名を検索していることがわかった。
for proc in psutil.process_iter():
# Skip access denied processes
if not refresh_ad_cache and proc.pid in self.ad_cache:
continue
found = False
for string in search_string:
try:
# FIXME 8.x: All has been deprecated
# from the doc, should be removed
if string == 'All':
found = True
if exact_match:
if os.name == 'nt':
if proc.name().lower() == string.lower():
found = True
else:
if proc.name() == string:
found = True
else:
cmdline = proc.cmdline()
if os.name == 'nt':
lstring = string.lower()
if re.search(lstring, ' '.join(cmdline).lower()):
found = True
else:
if re.search(string, ' '.join(cmdline)):
found = True
コードから、exact_match
が True の場合は psutil.Process().name()
の値が、False の場合は psutil.Process().cmdline()
の値が使われていることがわかる。
エージェントのプロセス名
当初の疑問に戻って、 td-agent のプロセス監視にはなぜ exact_match: false
が必要なのかを考える。
これまで調べたことから、td-agent のプロセス名 (psutil.Process.name()
の値) はおそらく td-agent
ではないことが推測される。詳しく調べたところ、td-agentはRuby製のプログラムで、Rubyのデーモンとして起動するらしい。実際、ps-ef
出力を見ると、rubyプログラムとして起動していた。(c
オプションを渡すとよりわかりやすい。)
$ ps -ef
UID PID PPID C STIME TTY TIME CMD
...
td-agent 15397 1 0 07:06 ? 00:00:00 /opt/td-agent/embedded/bin/ruby /usr/sbin/td-agent --log /var/log/td-agent/td-agent.log --use-v1-config --group td-agent --daemon /var/run/td-agent/td-agent.pid
td-agent 15402 15397 0 07:06 ? 00:00:01 /opt/td-agent/embedded/bin/ruby -Eascii-8bit:ascii-8bit /usr/sbin/td-agent --log /var/log/td-agent/td-agent.log --use-v1-config --group td-agent --daemon /var/run/td-agent/td-agent.pid --under-supervisor
...
$ ps -ef -c
UID PID PPID C STIME TTY STAT TIME CMD
...
td-agent 15397 1 0 07:06 ? Sl 0:00 ruby
td-agent 15402 15397 0 07:06 ? Sl 0:01 ruby
...
つまり、td-agentにおけるプロセス名は ruby
であるため exact_match: true
では検索がうまくできず、結果として exact_match: false
として起動時のコマンドから検索する必要があったということになる。
どんなときに exact_match: false
を指定するか
exact_match: false
指定は次の場合に必要となる:
- 検索対象のプロセスが ruby, java, python といったプログラムのデーモンとして動いていて、プロセス名からそのプロセスであることを特定できない場合
今回の td-agent が典型的な例である。他のパターンは知らないけど、自前でスクリプトをデーモン化した場合は気をつける必要がありそう。