技術書典4でmackerel本を買った ことだし、今年度も性能検証仕事が増えそうだし、今のうちに欲しかったmetricをmackerelでとれるようにしようと。
欲しかったもの
Munin にはある tomcat request count と tomcat trafficです。特殊なものじゃないのだけど、これがなぜか、 mackerel になくて。
mackerel-plugin-jvm でとれるのは、GC関係、Heap関係なのです。
自力実装の判断
第3者公開版ならどこかにありそうな気もするけれど、ちょっと探しても見つからないので、作ったほうが早そうだと。
すぐに見つからない=メジャーどころじゃない plugin だと見つかったあとの、動作検証・ライセンス確認・安全性確認まで時間とられちゃいますから。
Munin で取れているので、munin plugin を移植すればできるはず。
そこだけMuninで見ればいい?
mackerel の「グラフをチャネル(Slackなど)に投稿」「グラフを共有」機能を一度使っちゃうと、それなしには耐えられない体にされてしまうのです。
Munin tomcat plugin
/usr/share/munin/plugins/
を見渡せば jmx_tomcat_request_
がいました。
シェルスクリプトだったのでこのまま移植しちゃいましょう。
autoconf, config 用のパートもありますが、中核部分だけ
...
cat <<@EOF > ${tmpfile}
open ${PidNum}
get -s -d Catalina -b name="${objname}",type=GlobalRequestProcessor requestCount
close
@EOF
${JAVA_HOME}/bin/java -jar ${jmxterm} -i ${tmpfile} 2>/dev/null | awk \
'BEGIN {
FS="\n"
RS=""
}
{
print "requests.value " $1;
}'
...
概要
- Tomcat起動時に記録している pidファイルを参照
- それを引数に、Jmxterm で対象JVMから情報取得
ちょろい。
※この記事書くときに Munin の GitHub を探したのですが、この plugin ソースは現役じゃなさそうです。古い版を引き継ぎ引き継ぎ使っているみたい。
コマンドラインで動作確認
$ cat /service/tomcat/pid
xxx
$ java -jar /usr/share/munin/plugins/jmxterm.jar
Welcome to JMX terminal. Type "help" for available commands.
$>open xxx
# Connection to xxx is opened
$>get -s -d Catalina -b name="jk_8009",type=GlobalRequestProcessor requestCount
# mbean = Catalina:name="jk_8009",type=GlobalRequestProcessor:
requestCount = 16;
$>get -s -d Catalina -b name="jk_8009",type=GlobalRequestProcessor *
# mbean = Catalina:name="jk_8009",type=GlobalRequestProcessor:
requestCount = 16;
maxTime = 1408;
bytesReceived = 81;
modelerType = org.apache.coyote.RequestGroupInfo;
bytesSent = 57435;
processingTime = 3235;
errorCount = 0;
$>close
# disconnected
$>quit
# bye
ちょろい。traffic用の bytesSent, bytesReceivedもとれそう。
トラブルシュート
jmxtermでopenできない
Tomcat起動時のjmxremoteオプションを確認します。port番号は一例。
-Dcom.sun.management.jmxremote.port=10080
-Dcom.sun.management.jmxremote.ssl=false
-Dcom.sun.management.jmxremote.authenticate=false
InstanceNotFoundException
getしても #InstanceNotFoundException: Catalina:name="jk_8009",type=GlobalRequestProcessor
でとれなかったら、そのTomcatでのBean名が違うのでしょう。
jmxterm で help
して beans -d Catalina
して type=GlobalRequestProcessor
を探してください。
http-8080
だったり "ajp-nio-8009"
だったりかもしれません。
pidファイル・コマンドtmpfileはトロい
古式蒼然としてますよね。 jmxtermのマニュアル見てたら、対話形式だけでなく自動実行用のオプションもいろいろあるじゃないですか。
- tmpfile にjmxtermのコマンドをつくるのはやめて、--noninteract を使おう
- 動的に取得するtomcat pidではなく、固定の com.sun.management.jmxremote.port=10080 を使おう
初版
# !/bin/bash
DefaultJmxterm="/usr/share/munin/plugins/jmxterm.jar"
jmxterm=${jmxterm:-${DefaultJmxterm}}
EPOCH=$(date +'%s')
requestCount=`echo "get -d Catalina -b name=jk_8009,type=GlobalRequestProcessor requestCount" | \
java -jar ${jmxterm} -l localhost:10080 -v silent -n | \
sed -e 's/[^0-9]//g'`
echo -e "tomcat.requestCount\t${requestCount}\t${EPOCH}"
短っ!
これを実行許可した tomcat.access.sh
にして、mackerel-agent.conf に指定します。
# tail -n 2 /etc/mackerel-agent/mackerel-agent.conf
[plugin.metrics.tomcat]
command = "/home/work/tomcat.access.sh"
agentを再起動すれば、1-2分で新metricのグラフが出てくるはずです
/etc/init.d/mackerel-agent restart
これでとれる requestCount はTomcat起動で0リセットのあとは、単調増加の累積値です。
mackerel は metric が累積値の場合に、グラフを per minute にしてくれる「差分値」グラフの設定があるので、グラフが出てきたら設定変更してください。
やったね。My first mackerel plugin 成功。
plugin改
改造プラン
- bean名の"jk_8009", jmxportの10080 は環境次第なので環境変数対応する
- requestCount のついでに他の関連metricも取る
jmxterm で get *
で見えた、errorCount, bytesSent, bytesReceived もmetric として取りましょう。
pluginを4つでグラフを4つにするのはイケてない。
pluginが4行違うmetricを返せば、mackerel は '.'(dot)で区切ったnamespaceに合わせてグラフを統合してくれます。
(requestCount, errorCount) と (bytesSent, byetesreceived) は単位が違うので、namespace を2分割して2枚のグラフにします。
plugin改の出力ゴールイメージ
tomcat.access.requestCount 5434 1526870547
tomcat.traffic.bytesReceived 81 1526870547
tomcat.traffic.bytesSent 2105 1526870547
tomcat.access.errorCount 416 1526870547
4つの値をとるのに、javaを4回起動するのも、昭和の第5世代脳には耐えがたいので、1回でget *
して、結果を sed
で加工調整します。
ほい。
# !/bin/bash
DefaultJmxterm="/usr/share/munin/plugins/jmxterm.jar"
jmxterm=${jmxterm:-${DefaultJmxterm}}
DefaultJmxport="localhost:10080"
jmxport=${jmxport:-${DefaultJmxport}}
DefaultBeanName='"ajp-nio-8009"'
beanName=${beanName:-${DefaultBeanName}}
EPOCH=$(date +'%s')
echo "get -d Catalina -b name=${beanName},type=GlobalRequestProcessor *" | \
java -jar ${jmxterm} -l ${jmxport} -v silent -n | \
# requestCount = 5434;
# bytesReceived = 81;
# bytesSent = 2105;
# errorCount = 416;
sed -r -n "
s/^(requestCount|errorCount)/tomcat.access.\1/
s/^(bytesReceived|bytesSent)/tomcat.traffic.\1/
s/ = /\t/
s/;/\t${EPOCH}/
/(requestCount|bytesReceived|bytesSent|errorCount)/p
"
# tomcat.access.requestCount 5434 1526870547
# tomcat.traffic.bytesReceived 81 1526870547
# tomcat.traffic.bytesSent 2105 1526870547
# tomcat.access.errorCount 416 1526870547
環境変数は、mackerel-agent.conf に env 行を追加してください。
[plugin.metrics.tomcat]
command = "/home/work/tomcat.access.sh"
env = { beanName="jk-8009" }
公開場所