JMXコマンドラインツール

# はじめに

* JMXを使うことでjava内部の情報を丸見えにできます。GUIではjconsoleを使えばよいのですがログ出力する方法について書いてみました。
* 思ったより簡単にできそうだったので勢いで[機能を追加した版](https://github.com/uzresk/jmx-cmdclient)を作ってみました。色々便利になっています。
* [ダウンロードはこちらからどうぞ](https://github.com/uzresk/jmx-cmdclient/releases)
* あ。ちなみにタイトルで誤解してほしくはないのですが、JMXはtomcatに限った話ではないです。

## 準備：JMXポートを開放する

* Linuxの場合
setenv.shをbinの下に作って、CATALINA_OPTSに設定します。

* Windowsの場合
tomcatXw.exeを起動し、Javaタブ、Java Optionに設定します。

* 設定内容

```
-Dcom.sun.management.jmxremote=true
-Dcom.sun.management.jmxremote.port=7085
-Dcom.sun.management.jmxremote.ssl=false
-Dcom.sun.management.jmxremote.authenticate=false
```

* （参考）JMXの接続で利用するID/PWなどは外部ファイル化などもできるようですね。
[Tomcat7 Monitoring and Managing Tomcat Enabling JMX Remote](https://tomcat.apache.org/tomcat-7.0-doc/monitoring.html#Enabling_JMX_Remote)
[Tomcat8 Monitoring and Managing Tomcat Enabling JMX Remote]
(https://tomcat.apache.org/tomcat-8.0-doc/monitoring.html#Enabling_JMX_Remote)

# ログ出力する①

* [Command-line JMX Client](http://crawler.archive.org/cmdline-jmxclient/)を使うと幸せになりそうですので早速ダウンロードします。

* コマンド

```
java -jar cmdline-jmxclient-0.10.3.jar - [接続先] [BEAN] [COMMAND]
```

* BEANとCOMMANDの部分にObjectNameとAttirbutesの名前を渡してあげれば取得できます。("は\でエスケープするのをお忘れなく）

```
java -jar cmdline-jmxclient-0.10.3.jar - localhost:7085 Catalina:clas
s=javax.sql.DataSource,context=/,host=localhost,name=\"jdbc/postgres\",type=DataSource numActive
```

* 出力結果

```
10/22/2015 11:53:10 +0900 org.archive.jmx.Client numActive: 0
```

* あとはawkして数値だけ抜けば閾値の監視などにも使えそうですね

# ログ出力する②

①でもいいんだけど、うーん。なんか物足りない！ということで①を改良した版のツールを作りました。
Java6以降であれば動くと思います。

## どこが進化してる？

* ヘッダが出力されます
* 定期的に実行できます
* 複数の項目をCSV形式で同時に出力できます
* 日付の形式を変更できます
* ファイル出力することができます

## 実行の仕方

シンプルに実行するには①と同じような感じで実行できます。

１．[まずはここからダウンロードしてください。](https://github.com/uzresk/jmx-cmdclient/releases)

２．さきほどとように、JNDI DataSourceのnumActiveを出力してみます。

```
java -jar jmx-cmdclient-0.1.0.jar localhost:7085 "Catalina:clas
s=javax.sql.DataSource,context=/,host=localhost,name=\"jdbc/postgres\",type=DataSource" "numActive"
```

## オブジェクト名の一覧を取得できます。

１．JMXのURLだけ指定してあげます。

```
java -jar jmx-cmdclient-0.1.0.jar localhost:7085
```

２．オブジェクト名の一覧が取得できました。

```
java.lang:type=ClassLoading
java.lang:type=Compilation
java.lang:type=GarbageCollector,name=PS MarkSweep
java.lang:type=GarbageCollector,name=PS Scavenge
java.lang:type=Memory
```

##　定期的に実行することができます。

* メモリの情報を定期的に出力してみます。引数の最後にInterval(sec)を指定します。

```
java -jar jmx-cmdclient-0.1.0.jar localhost:7085 "java.lang:type=Memory" "HeapMemoryUsage" 1
```

```
HeapMemoryUsage@committed,HeapMemoryUsage@init,HeapMemoryUsage@max,HeapMemoryUsage@used
2015-10-23 09:51:55.593,133955584,134217728,238616576,35819368
2015-10-23 09:51:56.596,133955584,134217728,238616576,35843488
2015-10-23 09:51:57.599,133955584,134217728,238616576,35843488
2015-10-23 09:51:58.601,133955584,134217728,238616576,35941744
2015-10-23 09:51:59.604,133955584,134217728,238616576,35941744
```

## 複数の項目をCSV形式で同時に出力できます

* JNDI DataSourceのnumActiveとnumIdleを同時に出力してみます。

１．まずはmetricsファイルを用意します。

```metrics.sample1
"Catalina:type=DataSource,context=/,host=localhost,class=javax.sql.DataSource,name="jdbc/postgres"" "numActive"
"Catalina:type=DataSource,context=/,host=localhost,class=javax.sql.DataSource,name="jdbc/postgres"" "numIdle"

２．引数にmetricsファイルを指定してあげます。

```
java -Dpath=./metrics -jar jmx-cmdclient-0.1.0.jar localhost:7085
```

３．複数の項目が定期的に出力されました。

```
numActive,numIdle
2015-10-23 09:57:59.228,0,0
2015-10-23 09:58:00.230,0,0
2015-10-23 09:58:01.232,0,0
2015-10-23 09:58:02.235,0,0
```

## 日付の形式を変更する

* 内部ではlogbackを利用していますので、logback.xmlを実行時に指定してあげます。

１．logback.xmlを用意する。日付を/区切りにしてミリ秒は出力しないようにしてみます。

```logback.xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE logback>
<configuration>

	<property name="DEFAULT_PATTERN" value="%d{yyyy/MM/dd HH:mm:ss},%m%n" />
	<property name="SIMPLE_PATTERN" value="%m%n" />

	<appender name="DEFAULT" class="ch.qos.logback.core.ConsoleAppender">
		<encoder>
			<pattern>${DEFAULT_PATTERN}</pattern>
			<charset>UTF8</charset>
		</encoder>
	</appender>

	<appender name="SIMPLE" class="ch.qos.logback.core.ConsoleAppender">
		<encoder>
			<pattern>${SIMPLE_PATTERN}</pattern>
			<charset>UTF8</charset>
		</encoder>
	</appender>

	<logger name="simple" level="INFO">
		<appender-ref ref="SIMPLE" />
	</logger>

	<logger name="default" level="INFO">
		<appender-ref ref="DEFAULT" />
	</logger>

	<logger name="ch.qos.logback" level="ERROR" />
	 
</configuration>
```

２．引数に１で変更したlogback.xmlを指定します。

```
java -Dlogback.configurationFile=./logback.xml -jar jmx-cmdclient-0.1
.0.jar localhost:7085 "java.lang:type=Memory" "HeapMemoryUsage" 1
```

３．日付が/区切りでミリ秒が出力されないようになりました。

```
HeapMemoryUsage@committed,HeapMemoryUsage@init,HeapMemoryUsage@max,HeapMemoryUsage@used
2015/10/23 10:01:37,133955584,134217728,238616576,29214400
2015/10/23 10:01:38,133955584,134217728,238616576,29214400
2015/10/23 10:01:39,133955584,134217728,238616576,29214400
```

* 同じようにlogback.xmlを変更することで日付でファイルをローリングるようにもできますね

## 色々なメトリクスを取得してみる

１． metricsファイルに色々指定してみます。

```metrics.sample2
"java.lang:type=Memory" "HeapMemoryUsage"
"java.lang:name=PS Perm Gen,type=MemoryPool" "Usage"
"java.lang:name=PS Eden Space,type=MemoryPool" "Usage"
"Catalina:type=DataSource,context=/,host=localhost,class=javax.sql.DataSource,name="jdbc/postgres"" "numActive"
"Catalina:type=DataSource,context=/,host=localhost,class=javax.sql.DataSource,name="jdbc/postgres"" "numIdle"
"Catalina:name="http-apr-8080",type=GlobalRequestProcessor" "bytesSent"
"Catalina:name="http-apr-8080",type=GlobalRequestProcessor" "bytesReceived"
"Catalina:name="http-apr-8080",type=GlobalRequestProcessor" "errorCount"
"Catalina:name="http-apr-8080",type=GlobalRequestProcessor" "maxTime"
"Catalina:name="http-apr-8080",type=GlobalRequestProcessor" "requestCount"
"Catalina:type=Manager,context=/,host=localhost" "activeSessions"
"Catalina:type=Manager,context=/,host=localhost" "sessionCounter"
"Catalina:type=Manager,context=/,host=localhost" "expiredSessions"
```

２．実行してみます

```
java -Dpath=./metrics.sample2 -jar jmx-cmdclient-0.1.0.jar localhost:7085 1
```

３．色々でましたね。性能測定するときの監視なんかにいいんじゃないでしょうか

```
HeapMemoryUsage@committed,HeapMemoryUsage@init,HeapMemoryUsage@max,HeapMemoryUsage@used,Usage@commit
ted,Usage@init,Usage@max,Usage@used,Usage@committed,Usage@init,Usage@max,Usage@used,numActive,numIdl
e,bytesSent,bytesReceived,errorCount,maxTime,requestCount,activeSessions,sessionCounter,expiredSessi
ons
2015-10-23 10:36:04.155,133955584,134217728,238616576,34799952,20971520,16777216,67108864,19881848,44171264,33554432,88932352,27702448,0,0,64697,0,2,1088,8,0,0,0
2015-10-23 10:36:05.167,133955584,134217728,238616576,35337304,20971520,16777216,67108864,19881848,44171264,33554432,88932352,28239800,0,0,64697,0,2,1088,8,0,0,0
2015-10-23 10:36:06.179,133955584,134217728,238616576,35463576,20971520,16777216,67108864,19881848,44171264,33554432,88932352,28366072,0,0,64697,0,2,1088,8,0,0,0
```