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