Download PDF
Download page Java エージェント API ユーザガイド.
Java エージェント API ユーザガイド
このページの例では、エージェント API の一般的な使用例を実装する方法について説明します。https://sdkdocs.appdynamics.com/java-agent-api/v20.6/ の javadoc を参照してください。
一般的な使用例
次に、エージェント API の一般的な使用例を示します。
同期ビジネストランザクションの開始と終了
次に、メソッド checkout()
が呼び出されるたびに "Checkout" と呼ばれるビジネストランザクションが開始されるコード例を示します。ビジネストランザクションは、メソッドが戻ったときに終了します。try または finally ブロックでメソッド本体をカプセル化すると、メソッド自体が例外をスローした場合でも、ビジネストランザクションを終了します。それ以外の場合は、最後まで到達せずに終了します。
public String checkout(List<ItemOrders> orders) {
Transaction transaction = null;
try {
transaction = AppdynamicsAgent.startTransaction("Checkout", null, EntryTypes.POJO, false);
/*******************
* Method Body Here
*******************/
} finally {
if (transaction != null) {
transaction.end();
}
}
}
または、try-with-resources パターンを使用することができます。
public String checkout(List<ItemOrders> orders) {
try (Transaction transaction = AppdynamicsAgent.startTransaction("Checkout", null, EntryTypes.POJO, false)) {
/*******************
* Method Body Here
*******************/
}
}
この場合、try ブロックが終了すると、ビジネストランザクションが終了します。
非同期ビジネストランザクションの開始と終了
次に、メソッド checkoutAsync()
が呼び出されるたびに「CheckoutAsync」と呼ばれるビジネストランザクションが開始されるコード例を示します。ビジネストランザクションに作成された送信元セグメントは、ビジネストランザクションでメソッド endSegment()
が呼び出された場合、または try-with-resources 構成で使用されたときにクローズされた場合に終了します。try/finally ブロックでメソッド本体をカプセル化すると、メソッド自体が例外をスローした場合でも、セグメントを終了します。それ以外の場合は、最後まで到達せずに終了します。
//The thread where the Business Transaction starts
public String checkoutAsync(List<ItemOrders> orders) {
Transaction transaction = null;
try {
transaction = AppdynamicsAgent.startTransaction("CheckoutAsync", null, EntryTypes.POJO, true);
//mark handoff to link this segment with the end segment
transaction.markHandoff(commonPayload);
/*******************
* Method Body Here
*******************/
} finally {
if (transaction != null) {
transaction.endSegment();
}
}
}
または、try-with-resources パターンがサポートされています。
//The thread where the Business Transaction starts
public String checkoutAsync(List<ItemOrders> orders) {
try (Transaction transaction = AppdynamicsAgent.startTransaction("CheckoutAsync", null, EntryTypes.POJO, true)) {
//mark handoff to link this segment with the end segment
transaction.markHandoff(commonPayload);
/*******************
* Method Body Here
*******************/
}
}
これにより、try ブロックが終了した場合にビジネストランザクションが開始されるスレッドのセグメントが終了します。ビジネストランザクション自体は、非同期ビジネストランザクションが終了するときのメソッドで終了する必要があります。
//The thread where the Business Transaction ends
public String checkoutAsyncEnd(List<ItemOrders> orders, Transaction transaction, Object commonPayload) {
//link to the originating segment
Transaction transactionSegment = AppdynamicsAgent.startSegment(commonPayload);
/*******************
* Method Body Here
*******************/
if (transactionSegment != null) {
transactionSegment.endSegment();
}
if (transaction != null) {
transaction.end();
}
}
開始後のトランザクション名の設定
次に、開始後にトランザクション名を設定する例を示します。これは、アプリケーションで発生したイベントに基づいてトランザクションを分割する場合に役立ちます。
トランザクション名は、元のセグメントでの開始後に、非同期ハンドオフまたは終了が行われていない場合にのみ設定できます。
public String checkout(List<ItemOrders> orders) {
AppdynamicsAgent.startTransaction("Checkout", null, EntryTypes.POJO, false);
/*******************
* Method Body Here
*******************/
if (orders.isEmpty()) {
AppdynamicsAgent.setCurrentTransactionName("Empty Cart");
}
AppdynamicsAgent.getTransaction().end();
}
OOTB サーブレットの命名規則を使用したトランザクションの開始
次に、自動のサーブレットの命名規則を利用してトランザクションに名前を付ける例を示します。
public String checkout(List<ItemOrders> orders) {
Map<String, String> headers = new HashMap<String, String>();
headers.put("header1", "headerValue1");
Map<String, String[]> parameters = new HashMap<String, String[]>();
Map<String, Object> cookies = new HashMap<String, Object>();
cookies.put("chip", "ahoy");
ServletContext.ServletContextBuilder contextBuilder = new ServletContext.ServletContextBuilder()
.withURL(new URL("https://www.yourstore.com/endpoint/to/checkout"))
.withParameters(parameters)
.withHeaders(headers)
.withCookies(cookies)
.withSessionAttributes(new HashMap<String, Object>())
.withRequestMethod("GET")
.withHostValue("hostValue")
.withHostOriginatingAddress("hostOriginatingAddress");
Transaction t = AppdynamicsAgent.startServletTransaction(contextBuilder.build(), EntryTypes.HTTP, null, false);
/*******************
* Method Body Here
*******************/
t.end();
}
exit コールの定義
別のプロセスに対して要求を行う inventoryServer.verifyQuantities(orders)
では、その要求を exit コールとしてモニタできます。これにより、ダウンストリームサーバへのコールによるビジネストランザクションのモニタリングを継続し、リモートサービスで費やされた時間を特定することができます。このためには、次のようにメソッドを変更します。
public void verifyQuantities(List<ItemOrders> orders) {
ExitCall exitCall = null;
try {
exitCall = AppdynamicsAgent.getTransaction().startExitCall("Quantity Check", "Inventory Server", ExitTypes.HTTP, false);
/*******************
* Method Body
*******************/
} finally {
if (exitCall != null) {
exitCall.end();
}
}
}
または、HTTP バックエンド検出ルールを使用する場合、startHttpExitCall
メソッドを使用できます。
public void verifyQuantities(List<ItemOrders> orders) {
ExitCall exitCall = null;
try {
Map<String, String> identifyingProps = new HashMap<String, String>();
URL url = new URL("https://www.appdynamics.com/solutions/microservices/");
exitCall = AppdynamicsAgent.getTransaction().startExitCall(identifyingProps, url, false);
/*******************
* Method Body
*******************/
} finally {
if (exitCall != null) {
exitCall.end();
}
}
}
上記のコード変更では、コントローラのリモートサービスとしてマニフェストを定義する exit コールを定義します。インストゥルメント化されたダウンストリーム階層への要求にタグを付けて追跡するには、相関ヘッダーを追加します。
public void verifyQuantities(List<ItemOrders> orders) {
ExitCall exitCall = null;
try {
exitCall = AppdynamicsAgent.getTransaction().startExitCall("Quantity Check", "Inventory Server", ExitTypes.HTTP, false);
// Generate the appdynamics correlation header
String correlationHeader = exitCall.getCorrelationHeader();
// ... Method code including request creation
// Modify the request/payload to include the correlation header
inventoryRequest.addHeader(AppdynamicsAgent.TRANSACTION_CORRELATION_HEADER, correlationHeader);
} finally {
if (exitCall != null) {
exitCall.end();
}
}
}
次の例では、非同期 exit をインストゥルメント化する方法を示します。
public class StartEndAsyncExitCall {
private void makeAsyncExitTransaction() throws Exception {
System.out.println("Starting transaction");
try (Transaction transaction = AppdynamicsAgent.startTransaction("StartEndAsyncExitCall", null, EntryTypes.POJO, true)) {
Thread.sleep(1000);
new TransactionEndingThread(transaction).start();
System.out.println("Starting exitcall");
ExitCall exitCall = null;
exitCall = transaction.startExitCall("Custom", "Custom", ExitTypes.CUSTOM, true);
new ExitCallEndingThread(exitCall).start();
}
}
public class TransactionEndingThread extends Thread {
Transaction transaction = null;
TransactionEndingThread(Transaction transaction) {
this.transaction = transaction;
}
public void run() {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
transaction.end();
System.out.println("Ending transaction");
}
}
public class ExitCallEndingThread extends Thread {
ExitCall exitCall = null;
ExitCallEndingThread(ExitCall exitCall) {
this.exitCall = exitCall;
}
public void run() {
try {
Thread.sleep(50);
} catch (InterruptedException e) {
e.printStackTrace();
}
exitCall.end();
System.out.println("Ending exitcall");
}
}
}
非同期スレッドハンドオフの定義
チェックアウトメソッドでスレッドハンドオフが行われ、別のスレッドでモニタする一部のビジネスロジックが実行される場合も、ビジネストランザクションでワーカースレッドを登録します。
public String checkout(List<ItemOrders> orders) {
Transaction transaction = null;
try {
transaction = AppdynamicsAgent.startTransaction("Checkout", null, EntryTypes.POJO, false);
// ... Method code
// Custom thread handoff using custom queue
asyncTaskQueue.add(task);
} finally {
if (transaction != null) {
transaction.end();
}
}
}
これをインストゥルメント化するには、スレッドハンドオフをマークするように add メソッドを変更してから、スレッドの実行を開始する新しいセグメントを開始します。
public class AsyncTaskQueue {
public void add(Task task) {
AppdynamicsAgent.getTransaction().markHandoff(task);
/*******************
* Method Body
*******************/
}
public class Task {
public void run() {
Transaction transaction = null;
try {
transaction = AppdynamicsAgent.startSegment(this);
/*******************
* Method Body
*******************/
} finally {
if (transaction != null) {
transaction.endSegment();
}
}
}
public void cancel() {
AppdynamicsAgent.cancelHandoff(this);
/*******************
* Method Body
*******************/
}
}
タスクオブジェクトは、セグメントを関連付けするエージェントによって使用されます。エージェント API を使用してスレッドセグメントを関連付けるには、エージェントが Executor モードで実行されている必要があります。
スナップショットまたは分析へのデータの追加
多くの場合、コードには、スナップショットに追加するのに役立つ興味深い値があります。これは、問題の根本原因の診断に役立ち、Splunk AppDynamics ビジネストランザクション分析に送信して、アプリケーションに関するリアルタイムのビジネス指向の質問に回答するのに役立ちます。この API を使用して報告されたデータは、メソッド呼び出しデータコレクタで収集されたものと同じように表示されます。
ビジネストランザクション分析のチェックアウト合計を報告し、APM スナップショットに表示されるようにするには、次のコードを使用します。
private static final Set<DataScope> dataScopeSet = new HashSet(Arrays.asList(DataScope.ANALYTICS, DataScope.SNAPSHOTS));
public String checkout(List<ItemOrders> orders) {
Transaction transaction = null;
try {
transaction = AppdynamicsAgent.startTransaction("Checkout", null, EntryTypes.POJO, false);
// ... Method code
double shoppingCartTotal = total(orders);
transaction.collectData("cart total", Double.toString(shoppingCartTotal), dataScopeSet);
} finally {
if (transaction != null) {
transaction.end();
}
}
}
カスタム指標またはイベントの定義
カスタム指標として値を報告する場合にも役立ちます。
public String checkout(List<ItemOrders> orders) {
// ... Method code
double shoppingCartTotal = total(orders);
AppdynamicsAgent.getMetricPublisher().reportSumMetric("Cart Total", (long) shoppingCartTotal);
}
メトリックのパブリッシュ時に、コード内でメトリック名とともにメトリックパスを Server|Component:<TierName>|Custom Metrics|<MetricName>,
の形式で指定することをお勧めします。
カスタム指標とイベントの報告は、ビジネストランザクションのコンテキストに関係なく可能です。