JDK Flight RecorderファイルをJDK Mission Controlで分析して異常を見つけたら、レポートを作成するためにExcelに取り込みたいなぁと思うことがあります。その場合はjfr
コマンドとjq
コマンドを使って任意のイベントをCSVに変換しましょう。
イベントを探す
CSVファイルを作る前に、イベントが持つ要素名を取得しないといけません。そのためにはまず、そのイベントの名前を探して、次にそのイベントが持つ要素名を取得します。
ここで使用するのはjfr
コマンドのサブコマンドであるmetadata
です。これらを以下のように使います。
jfr metadata <JFR file> | grep @Name jfr metadata --events <Event Name> <JFR file>
まず最初に、イベントの名前を探しましょう。イベントの名前はメタデータの@Name
アノテーションに記載されています。そのため、JFRファイルが持っているイベントの@Name
アノテーションを全て表示しましょう。たくさん出力されるので、grep
を追加して引っかかりそうなキーワードでフィルタすることをお奨めします。
> jfr metadata <JFR file> | grep @Name @Name("jdk.TenuringDistribution") @Name("jdk.ThreadAllocationStatistics") @Name("jdk.ThreadCPULoad") @Name("jdk.ThreadContextSwitchRate") @Name("jdk.ThreadDump") @Name("jdk.ThreadEnd") @Name("jdk.ThreadPark") @Name("jdk.ThreadSleep") @Name("jdk.ThreadStart") @Name("jdk.UnsignedIntFlag") @Name("jdk.UnsignedIntFlagChanged") @Name("jdk.UnsignedLongFlag") @Name("jdk.UnsignedLongFlagChanged") @Name("jdk.YoungGarbageCollection")
次に、そのイベントが持つメタデータを取得しましょう。metadata
サブコマンドではJFRが持つ全てのイベントのメタデータを表示します。イベントの数は膨大にあるのでその出力結果からメタデータを探すのは大変です。そのため、先ほど取得したイベントの名前でフィルタを掛けて実行しましょう。今回はjdk.CPULoad
というCPUの負荷情報のメタデータを取得します。
> jfr metadata --events jdk.CPULoad <JFR file> @Name("jdk.CPULoad") @Category({"Operating System", "Processor"}) @Label("CPU Load") @Description("OS CPU Load") class CPULoad extends jdk.jfr.Event { @Label("Start Time") @Timestamp("TICKS") long startTime; @Percentage @Label("JVM User") float jvmUser; @Percentage @Label("JVM System") float jvmSystem; @Percentage @Label("Machine Total") float machineTotal; }
イベントをCSVへ出力
これでようやく本題であるイベントをCSVへ出力できます。以下のようなコマンドを使用してCSVへ出力します。
jfr print --json --events <イベント名> <JFR file> | jq -r ".recording.events[].values | [<出力したい要素を羅列>] | @csv"
出力したい要素は先ほど取得したイベントのメタデータからフィールド名に該当する部分の先頭に.
を付けて、各要素間はカンマ区切りで羅列します。CPULoad
のJVMのユーザ領域とシステム領域を出力する場合は.jvmUser, .jvmSystem
になります。
以下の例は、イベントの発生時間、JVMのユーザ領域の使用量、JVMのシステム領域の使用量、マシン全体の使用量を出力する例です。
jfr print --json --events jdk.CPULoad <JFR file> | jq -r ".recording.events[].values | [.startTime, .jvmUser, .jvmSystem, .machineTotal] | @csv" "2022-03-23T1:23:45.123456789+09:00",0.01234567890,0.01234567890,0.01234567 "2022-03-23T1:23:46.123456789+09:00",0.01234567890,0.01234567890,0.01234567 "2022-03-23T1:23:47.123456789+09:00",0.01234567890,0.01234567890,0.01234567
この結果をファイルにリダイレクトすることでCSVファイルが作成されます。
おまけ
JFRのイベントには期間(Duration)を持つイベントが多くあります。そのようなイベントの1つであるソケット読み込みの例も記載しておきます。メタデータの詳細が気になる場合は先述の手順で取得してください。
jfr print --json --events jdk.SocketRead <JFR file> | jq -r ".recording.events[].values | [.startTime, .duration, .host, .address] | @csv" "2022-03-23T1:23:45.123456789+09:00","PT0.012345678S","service-a","172.30.1.1" "2022-03-23T1:23:45.123456789+09:00","PT0.012345678S","service-b","172.30.1.2" "2022-03-23T1:23:45.123456789+09:00","PT0.012345678S","service-a","172.30.1.2"