CloudWatchのカスタムメトリクスでJavaVMのGC関連情報を取得

この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。

JavaVMのGC情報を取得します

前回はLinuxOSのメモリー関連情報を取得して、CloudWatchに登録しました。今回は、JavaVMのガベージコレクション周りの情報をCloudWatchに登録したいと思います。

環境の構築

今回は、JavaVMのGCを見るためにTomcatをインストールします。また、JREではなくJDKを利用しますので必要なものをインストールします。CloudWatchコマンドラインツールは設定済みとします。詳しくは前回の記事をご覧ください。JREではなくJDKを入れる理由は、jpsコマンドとjstatコマンドを使うためです。これらのコマンドはプロセスIDなどを取得するためsudoで実行します。

$ sudo yum install java-1.6.0-openjdk-devel

$ sudo alternatives --install /usr/bin/java java /usr/lib/jvm/java-1.6.0/bin/java 200

$ sudo alternatives --config java
3 プログラムがあり 'java' を提供します。

  選択       コマンド
-----------------------------------------------
*+ 1           /usr/lib/jvm/jre-1.6.0-openjdk/bin/java
   2           /usr/lib/jvm/jre-1.5.0-gcj/bin/java
   3           /usr/lib/jvm/java-1.6.0/bin/java

Enter を押して現在の選択 [+] を保持するか、選択番号を入力します:3

$ sudo yum install tomcat6

$ sudo service tomcat6 start

jpsコマンド

TomcatのプロセスIDを取得するにはjpsコマンドを用います。

sudo jps -J-Djava.io.tmpdir=/usr/share/tomcat6/temp
19660 Jps
19246 Bootstrap

Bootstrapと出ている行がTomcatのプロセスIDです。これを前回と同じように成型してプロセスIDだけ取得します。

sudo jps -J-Djava.io.tmpdir=/usr/share/tomcat6/temp | grep 'Bootstrap' | tr -s ' ' | cut -d ' ' -f 1
19246

取れました!

jstatコマンド

TomcatのプロセスIDを用いてJavaVMの統計情報を取得します。

$ sudo jstat -J-Djava.io.tmpdir=/usr/share/tomcat6/temp -gcutil 19246  
  S0     S1     E      O      P     YGC     YGCT    FGC    FGCT     GCT   
  0.00   0.00   6.14  28.70  68.77      5    0.020     3    0.087    0.106

いつものように成型します。

$ sudo jstat -J-Djava.io.tmpdir=/usr/share/tomcat6/temp -gcutil 20191  | tail -1 | tr -s ' ' | cut -c2-100
0.00 0.00 6.14 28.70 68.77 5 0.020 3 0.087 0.1

さらにここから1つ目、2つ目と値を取得していきます。これで値の取得ができました。

bashでシェルを書く

一連の操作を行うシェルを書きます。jvm_gc_report.sh という名前で保存しました。

#!/bin/bash

export AWS_CLOUDWATCH_HOME=/home/ec2-user/CloudWatch-1.0.12.1
export AWS_CREDENTIAL_FILE=$AWS_CLOUDWATCH_HOME/credentials
export AWS_CLOUDWATCH_URL=https://monitoring.amazonaws.com
export PATH=$AWS_CLOUDWATCH_HOME/bin:$PATH
export JAVA_HOME=/usr/lib/jvm/java-1.6.0/
 
# get ec2 instance id
instanceid=`wget -q -O - http://169.254.169.254/latest/meta-data/instance-id`

bootstrappid=`jps -J-Djava.io.tmpdir=/usr/share/tomcat6/temp | grep 'Bootstrap' | tr -s ' ' | cut -d ' ' -f 1`

jstat=`jstat -J-Djava.io.tmpdir=/usr/share/tomcat6/temp -gcutil $bootstrappid  | tail -1 | tr -s ' ' | cut -c2-100`

survivor0=`echo $jstat|cut -d ' ' -f 1`
survivor1=`echo $jstat|cut -d ' ' -f 2`
eden=`echo $jstat|cut -d ' ' -f 3`
old=`echo $jstat|cut -d ' ' -f 4`
permanent=`echo $jstat|cut -d ' ' -f 5`
young=`echo $jstat|cut -d ' ' -f 6`
youngtime=`echo $jstat|cut -d ' ' -f 7`
fgc=`echo $jstat|cut -d ' ' -f 8`
fgctime=`echo $jstat|cut -d ' ' -f 9`
gct=`echo $jstat|cut -d ' ' -f 10`

mon-put-data --metric-name "Survivor0" --namespace "Java/Tomcat" --dimensions "InstanceId=$instanceid" --value "$survivor0" --unit "Percent" --region ap-northeast-1

mon-put-data --metric-name "Survivor1" --namespace "Java/Tomcat" --dimensions "InstanceId=$instanceid" --value "$survivor1" --unit "Percent" --region ap-northeast-1

mon-put-data --metric-name "Eden" --namespace "Java/Tomcat" --dimensions "InstanceId=$instanceid" --value "$eden" --unit "Percent" --region ap-northeast-1

mon-put-data --metric-name "Old" --namespace "Java/Tomcat" --dimensions "InstanceId=$instanceid" --value "$old" --unit "Percent" --region ap-northeast-1

mon-put-data --metric-name "Permanent" --namespace "Java/Tomcat" --dimensions "InstanceId=$instanceid" --value "$permanent" --unit "Percent" --region ap-northeast-1

mon-put-data --metric-name "YoungGC" --namespace "Java/Tomcat" --dimensions "InstanceId=$instanceid" --value "$young" --unit "Count" --region ap-northeast-1

mon-put-data --metric-name "YoungGCTime" --namespace "Java/Tomcat" --dimensions "InstanceId=$instanceid" --value "$youngtime" --unit "Seconds" --region ap-northeast-1

mon-put-data --metric-name "FullGC" --namespace "Java/Tomcat" --dimensions "InstanceId=$instanceid" --value "$fgc" --unit "Count" --region ap-northeast-1

mon-put-data --metric-name "FullGCTime" --namespace "Java/Tomcat" --dimensions "InstanceId=$instanceid" --value "$fgctime" --unit "Seconds" --region ap-northeast-1

mon-put-data --metric-name "TotalGCTime" --namespace "Java/Tomcat" --dimensions "InstanceId=$instanceid" --value "$gct" --unit "Seconds" --region ap-northeast-1

実行して何もエラーが表示されなければ成功です。

cronに登録する

今回のシェルはroot権限で実行する必要がありますので、rootユーザのcronに登録します。

$ sudo crontab -e

中身はこんな感じです。

*/5 * * * * /home/ec2-user/custom_metrics_report.shi
*/5 * * * * /home/ec2-user/jvm_gc_report.sh

AWS Management Consoleで動作結果を確認する

最後に実行結果を見てみます。

まとめ

jpsとjstatを用いてJavaVMのGC情報を取得することができ、これをCloudWatchに登録することで、EC2インスタンスの外側からTomcatがどのように動いているか知る事ができました。カスタムメトリクスで楽々運用生活を手に入れましょう!

参考資料

jps and jstat for tomcat on jdk-1.6.0_24

CloudWatchのカスタムメトリクスでFreeMemoryMBytes、UsedMemoryPercent、LoadAverage、Stealを取得

jstat - Java 仮想マシン統計データ監視ツール