JProfiler用のカスタムプローブを開発するには、いくつかの基本的なコンセプトと用語を理解しておく必要があります。 JProfilerのすべてのプローブに共通する基盤は、特定のメソッドをインターセプトし、 インターセプトしたメソッドのパラメータやその他のデータソースを利用して、JProfiler UIで確認したい興味深い情報を含む文字列を構築することです。
プローブを定義する際の最初の課題は、どのようにインターセプトするメソッドを指定し、 そのメソッドのパラメータや関連するオブジェクトを使って文字列を構築できる環境を得るかという点です。 JProfilerでは、これを実現するために3つの異なる方法が用意されています。
- スクリプトプローブは、 JProfiler UI内ですべて定義できます。呼び出しツリーでメソッドを右クリックし、スクリプトプローブアクションを選択して、 組み込みのコードエディタで文字列用の式を入力できます。これはプローブの実験に最適ですが、 カスタムプローブの機能のごく一部しか利用できません。
- 埋め込みプローブAPIは、 自分のコードから呼び出すことができます。ライブラリやデータベースドライバ、サーバーなどを作成する場合、 プローブを製品に同梱できます。あなたの製品をJProfilerでプロファイルするユーザーは、 プローブが自動的にJProfiler UIに追加されます。
- インジェクションプローブAPIでは、 JProfilerのプローブシステムの全機能を使ってIDE上でサードパーティ製ソフトウェア向けのプローブを作成できます。 このAPIはアノテーションを利用してインターセプトを定義し、メソッドパラメータやその他の有用なオブジェクトをインジェクトします。
次の疑問は、「作成した文字列をJProfilerでどのように扱うか」です。利用可能な戦略は2つあり、 ペイロードの作成か呼び出しツリーの分割かを選択できます。
ペイロードの作成
プローブによって構築された文字列は、プローブイベントの作成に利用できます。 このイベントには、その文字列が説明として設定され、インターセプトしたメソッドの実行時間がイベントの継続時間となり、 関連する呼び出しスタックも記録されます。対応する呼び出しスタックごとに、プローブの説明とタイミングが集約され、 ペイロードとして呼び出しツリーに保存されます。イベントは一定数を超えると統合されますが、 呼び出しツリー内の集約されたペイロードは記録期間全体の合計値を示します。CPUデータとプローブの両方が記録されている場合、 プローブ呼び出しツリービューではペイロード文字列がリーフノードとして表示され、 CPU呼び出しツリービューにはプローブ呼び出しツリービューへの注釈付きリンクが含まれます。
CPUデータと同様に、ペイロードは呼び出しツリーやホットスポットビューで表示できます。 ホットスポットでは、どのペイロードが最も多くの時間を消費しているかを示し、 バックトレースではどのコードがこれらのペイロードを生成しているかを確認できます。 ホットスポットのリストを有効にするためには、ペイロード文字列に一意なIDやタイムスタンプを含めないようにしてください。 すべてのペイロード文字列が異なる場合、集約が行われず、ホットスポットの分布が明確になりません。 たとえば、JDBCのプリペアドステートメントの場合、パラメータはペイロード文字列に含めるべきではありません。
スクリプトプローブは、設定されたスクリプトの戻り値から自動的にペイロードを作成します。
インジェクションプローブも同様で、PayloadInterceptionでアノテートされたインターセプションハンドラメソッドから
文字列または高度な機能用のPayloadオブジェクトとしてペイロード説明を返します。
一方、埋め込みプローブはPayload.exitをペイロード説明を引数として呼び出すことでペイロードを作成し、
Payload.enterからPayload.exitまでの時間がプローブイベントの継続時間として記録されます。
ペイロードの作成は、異なる呼び出し元サイトで発生するサービス呼び出しを記録する場合に最も有用です。 典型的な例はデータベースドライバで、ペイロード文字列がクエリ文字列やコマンドとなります。 この場合、プローブは呼び出し元サイトの視点を取り、測定される作業は別のソフトウェアコンポーネントによって実行されます。
呼び出しツリーの分割
プローブは実行サイトの視点を取ることもできます。 この場合、インターセプトしたメソッドがどのように呼び出されたかではなく、 その後にどのメソッド呼び出しが実行されるかが重要です。 典型的な例は、抽出した文字列がURLとなるサーブレットコンテナ用のプローブです。
ペイロードの作成よりも重要なのは、プローブによって構築された各異なる文字列ごとに呼び出しツリーを分割できることです。 それぞれの文字列ごとに分割ノードが呼び出しツリーに挿入され、 対応するすべての呼び出しの集約された呼び出しツリーがそのノードに含まれます。 通常は1つの集約呼び出しツリーしかないところに、分割ノードのセットが呼び出しツリーを異なる部分に分割し、 個別に分析できるようになります。
複数のプローブでネストされた分割を生成することもできます。 1つのプローブはデフォルトで1つの分割レベルしか生成しませんが、 リエントラントとして設定されている場合は例外です(スクリプトプローブではサポートされていません)。
JProfiler UIでは、呼び出しツリーの分割はスクリプトプローブ機能とは別の
独立した機能(「メソッドの分割」)として提供されています。
これはペイロードを作成せずに呼び出しツリーのみを分割するため、名前や説明を持つプローブビューは不要です。
インジェクションプローブはSplitInterceptionでアノテートされたインターセプションハンドラメソッドから
分割文字列を返し、埋め込みプローブはSplit.enterで分割文字列を渡します。
テレメトリー
カスタムプローブにはデフォルトで2つのテレメトリー(イベント頻度と平均イベント継続時間)が用意されています。 インジェクションプローブおよび埋め込みプローブは、プローブ設定クラス内のアノテートされたメソッドで 追加のテレメトリーを作成できます。JProfiler UIでは、スクリプトテレメトリーはスクリプトプローブ機能とは独立しており、 「テレメトリー」セクションのツールバーにあるテレメトリーの設定ボタンから確認できます。
テレメトリーメソッドは1秒ごとにポーリングされます。
Telemetryアノテーションでは単位やスケールファクターを設定できます。
line属性を使うと、複数のテレメトリーを1つのテレメトリービューにまとめることができます。
TelemetryFormatのstacked属性を使うと、
ラインを加算して積み上げ線グラフとして表示できます。
テレメトリー関連のAPIは埋め込みプローブとインジェクションプローブで同等ですが、
それぞれのプローブタイプにのみ適用されます。
制御オブジェクト
場合によっては、プローブイベントを「制御オブジェクト」と呼ばれる長寿命の関連オブジェクトに紐付けることが有用です。 例えば、データベースプローブでは、クエリを実行する物理的なコネクションがその役割を担います。 このような制御オブジェクトは、埋め込みAPIやインジェクションプローブAPIでオープン・クローズでき、 プローブイベントビューに対応するイベントが生成されます。 プローブイベントを作成する際に制御オブジェクトを指定すると、 プローブの「制御オブジェクト」ビューで表示される統計情報に反映されます。
制御オブジェクトには、オープン時に指定する表示名があります。 新しい制御オブジェクトがプローブイベント作成時に使われる場合、 プローブの設定で名前解決用のリゾルバを提供する必要があります。
さらに、プローブはenumクラスを使ってカスタムイベントタイプを定義できます。 プローブイベント作成時にこれらのタイプのいずれかを指定でき、イベントビューで単一のイベントタイプでフィルタできます。 さらに重要なのは、制御オブジェクトを時間軸上のラインとして表示するプローブのタイムラインビューで、 イベントタイプごとに色分けされることです。 カスタムイベントタイプがない場合、カラー化はイベントが記録されていないアイドル状態と、 プローブイベントのデフォルト状態を示します。 カスタムタイプを使うことで、例えば「read」と「write」など、状態を区別できます。
記録
すべてのプローブと同様に、カスタムプローブもデフォルトではデータを記録しません。 必要に応じて記録を有効・無効にする必要があります。 プローブビューで手動の開始/停止アクションを使うこともできますが、 プローブ記録を最初から有効にする必要がある場合も多いです。 JProfilerはカスタムプローブを事前に認識できないため、 記録プロファイルにはすべてのカスタムプローブに適用されるカスタムプローブチェックボックスがあります。
同様に、プローブ記録の開始・停止トリガーアクションにはすべてのカスタムプローブを選択できます。
プログラムによる記録制御の場合、
Controller.startProbeRecording(Controller.PROBE_NAME_ALL_CUSTOM, ProbeRecordingOptions.EVENTS)
を呼び出すことで、すべてのカスタムプローブを記録できます。
または、特定のプローブのクラス名を渡してより詳細に制御することも可能です。











