Flutter アプリケーションをインストゥルメント化したら、インストゥルメンテーションをさらに手動でカスタマイズできます。

ネットワーク要求

ネットワーク要求のメトリックを収集するには、HTTP クライアントラッパーを使用します。

import 'package:http/http.dart' as http;

try {
  final client = TrackedHttpClient(http.Client());
  final response = await client.get(Uri.parse("https://www.appdynamics.com"));
  print(response);
} catch (e) {
  print(e);
}
JAVA

要求にユーザーデータを追加するなど、要求のトラッキングをより細かく制御する必要がある場合は、完了時に要求情報を登録するトラッカーオブジェクトを手動で作成できます。

try {
  final url = "www.appdynamics.com"
  final tracker = await RequestTracker.create(url);

  final response = await http.get(url);

  await tracker.setResponseStatusCode(response.statusCode)
    ..setRequestHeaders(response.request!.headers)
    ..setResponseHeaders(response.headers)
    ..setUserDataBool("shouldRespond", false);
} catch (e) {
  await tracker.setError(e.toString());
} finally {
  await tracker.reportDone();
}
JAVA

サーバー相関ヘッダーの追加

別の AppDynamics エージェント も、アプリケーションのバックエンドのインストゥルメント化に使用する場合、サーバー相関ヘッダーを追加して、ビジネストランザクションを特定できます。

import 'package:http/http.dart' as http;

try {
  final headers = await RequestTracker.getServerCorrelationHeaders();
  final url = Uri.parse("https://www.appdynamics.com");
  final client = HttpClient(http.Client());
  final response = await client.get(url, headers: headers);
  print(response);
} catch (e) {
  print(e);
}
JAVA

仕組み

RequestTracker.create(url) 

Null 以外の url を指定する(Instrumentation.start() を呼び出した後)ことにより、HTTP リクエストを手動でトラッキングするように設定された RequestTracker オブジェクトを返します。

パラメータ
名前タイプ要件説明

url

文字列Null 以外。

トラッキングされるリクエストのターゲット URL。

setError(message, stackTrace) 

応答を受信できなかったことを示すエラーメッセージを設定します(エラーが発生した場合)。リクエストが成功した場合は、このメソッドを呼び出さないでください。stackTrace 文字列を追加できます。

パラメータ
名前タイプ要件説明

message

文字列リクエストが正常に終了しませんでした。

エラーメッセージまたはエラーを説明する文字列。

stackTrace文字列リクエストが正常に終了しませんでした。エラー stackTrace プロパティ(ある場合)。

setResponseStatusCode(statusCode) 

応答のステータスコードを設定します(ある場合)。応答を受信した場合は、このメソッドは整数になります。エラーが発生し、応答が受信されなかった場合、このメソッドは呼び出しません。

パラメータ
名前タイプ要件説明

statusCode

整数リクエストが正常に終了しました。

応答のステータスコード。

setRequestHeaders(requestHeaders) 

トラッカーオブジェクトにリクエストヘッダーを追加します。エラーが発生し、応答が受信されなかった場合、このメソッドは呼び出しません。

パラメータ
名前タイプ要件説明

requestHeaders

Map<String, String>リクエストが正常に終了しました。

リクエストのヘッダー値を表すキーと値のペアのマップ。

setResponseHeaders(responseHeaders) 

トラッカーオブジェクトにリクエストの応答を追加します。エラーが発生し、応答が受信されなかった場合、これは呼び出しません。

パラメータ
名前タイプ要件説明

responseHeaders

Map<String, String>リクエストが正常に終了しました。

応答のヘッダー値を表すキーと値のペアのマップ。

reportDone() 

HTTP リクエストが完了し、適切な情報をログに記録したことを通知します。別のリクエストをトラッキングする必要がある場合は、新しい RequestTracker を作成する必要があります。

getServerCorrelationHeaders() 

AppDynamics エージェントもサーバー側で使用される場合に 使用する サーバー相関ヘッダーを返します。トラッキング対象のリクエストにヘッダーを追加する必要があります。

setUserdata

対応する各 API を使用してリクエスト トラッキング オブジェクトにカスタム値を 追加します。

  • setUserData(key, value)
  • setUserDataBool(key, value)
  • setUserDataDateTime(key, value)
  • setUserDataDouble(key, value)
  • setUserDataInt(key, value)
パラメータ
名前タイプ要件説明

key

String最大 2048 文字。一意(そうでない場合は上書きされます)。

対応する値のキー名。

valueString, bool, DateTime, double, int最大 2048 文字。リクエストに追加されたカスタム情報。

クラッシュ

ネイティブクラッシュの報告

Flutter エージェントは、ネイティブクラッシュ情報を自動的にログに記録します。これは、Instrumentation.start() の呼び出し時にすでに有効になっています。ネイティブクラッシュは、UI コントローラで対応する .dsym または ProGuard ファイルを渡すことでシンボル化できます。 詳細については、 人間が判読能なクラッシュスナップショットの取得 を参照してください。

すべてのクラッシュの報告

すべてのエラー(Flutter およびネイティブ)をキャプチャするには、ゾーンを使用します。

import 'dart:async';
import 'package:flutter/material.dart';
import 'package:appdynamics_mobilesdk/appdynamics_mobilesdk.dart';

void main() {
  runZonedGuarded(() {
    WidgetsFlutterBinding.ensureInitialized();
    FlutterError.onError = Instrumentation.errorHandler;
    runApp(MyApp());
  }, (Object error, StackTrace stack) async {
    final details = 
	  FlutterErrorDetails(exception: error.toString(), stack: stack);
    await Instrumentation.errorHandler(details);
});
CODE

Dart 例外の報告

Flutter エージェントが提供するエラーハンドラを使用して、Dart 例外をインターセプトし、コントローラに送信します。

import 'package:flutter/material.dart';
import 'package:appdynamics_mobilesdk/appdynamics_mobilesdk.dart';

void main() {
  WidgetsFlutterBinding.ensureInitialized();
  FlutterError.onError = Instrumentation.errorHandler;
  runApp(MyApp());
}
CODE

クラッシュレポートの無効化

クラッシュレポートは、デフォルトで有効になっています。ほとんどのアプリケーションでは、クラッシュレポートを有効にしておく必要がありますが、別のクラッシュレポートツールの使用によって問題が発生する場合にのみ無効にできます。

AgentConfiguration オブジェクトでネイティブ クラッシュ レポート機能を有効または無効にできます。

AgentConfiguration config = AgentConfiguration(
    appKey: <EUM_APP_KEY>,
    crashReportingEnabled: false);
await Instrumentation.start(config);
CODE

クラッシュコールバック

Flutter エージェントは、クラッシュレポートを受け取るコールバック関数の使用をサポートしています。このレポートには、ネイティブクラッシュ情報を表す Dart オブジェクトの配列が含まれています。

コールバック関数は、AgentConfiguration オブジェクトで設定できます。

void crashReportCallback(List<CrashReportSummary> summaries) async {
  print(summaries);
}

AgentConfiguration config = AgentConfiguration(
    appKey: <EUM_APP_KEY>,
    crashReportCallback: crashReportCallback);
await Instrumentation.start(config);
CODE

Session Frames

セッションフレームは、セッション中にユーザが実行している内容のコンテキストを提供します。次のいずれかで 作成済み カスタム ユーザー インタラクション フレームを作成できます: コントローラ UI またはエージェント インストゥルメンテーションの SessionFrame API 。

セッションフレームをカスタマイズする使用例には、次のようなものがあります。

  • 1 つのページで複数の関数を実行し、個々の関数をより詳細にトラッキングする必要があります。
  • ユーザーフローが複数のページまたはユーザーインタラクションにまたがっており、ユーザーフロー内のフレームを分類する必要があります。たとえば、購入のユーザーフローがある場合、次の名前のセッションフレームを作成できます。 「Login」、「Product Selection」、 「Purchase」。
  • ユーザの操作に基づいて動的情報をキャプチャし、オーダー ID などのセッションフレームに名前を付けることができます。

仕組み

Instrumentation.startSessionFrame(sessionFrameName) 

SessionFrame オブジェクトを開始して返します。

パラメータ
名前タイプ要件説明
sessionFrameName文字列Null 以外キャプチャされるセッションフレームのわかりやすい名前。

updateName(newName) 

セッションフレームを新しい名前で更新します。これは通常、適切なセッションフレーム名が作成時に不明な場合に使用されます。

パラメータ
名前タイプ要件説明
newName文字列Null 以外キャプチャされるセッションフレームのわかりやすい名前。

end()

セッションフレームの終了を報告します。この呼び出しの後、SessionFrame オブジェクトは使用できなくなります。

次は、ユーザーがチェックアウトボタンを押したときに現在のショッピングセッションの終了をマークする方法の例です。

class ShoppingCart {
  late SessionFrame _sessionFrame;
  late String _orderId;

void onCheckoutCartButtonClick() async {
  // The checkout starts when the user clicks the checkout button.
  // This may be after they have updated quantities of items in their
  // cart, etc.
  _sessionFrame = await Instrumentation.startSessionFrame("Checkout");
}

void onConfirmOrderButtonClick() {
  // Once they have confirmed payment info and shipping information,
  // and they are clicking the "Confirm" button to start the backend
  // process of checking out, we may know more information about the
  // order itself, such as an order ID.
  _sessionFrame.updateName("Checkout: Order ID {this.orderId}");
}

void onProcessOrderComplete() {
  // Once the order is processed, the user is done "checking out" so we end
  // the session frame.
  _sessionFrame.end();
}

void onCheckoutCancel() {
  // If they cancel or go back, you'll want to end the session frame also, or
  // else it will be left open and appear to have never ended.
  _sessionFrame.end();
}
CODE

メトリック

数値をメトリック名に関連付けて、Instrumentation.reportMetric を介して報告できます。

仕組み

Instrumentation.reportMetric(name, value)

カスタムメトリックを報告します。

パラメータ
名前タイプ要件説明

name

文字列

英数字とスペースのみ。メトリックを表す名前。
value整数数値、Null 以外。メトリック値。

次は、ユーザーがチェックアウトボタンをクリックした回数をトラッキングする方法の例です。

import 'package:appdynamics_mobilesdk/appdynamics_mobilesdk.dart';
import 'package:flutter/material.dart';

class App extends StatelessWidget {
  _finishCheckout() {
    Instrumentation.reportMetric(name: "Checkout Count", value: 1);
    // ...rest of the checkout logic
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: Text("Checkout screen")),
      body: Center(
        child:
            ElevatedButton(
              child: Text('Checkout'),
              onPressed: _finishCheckout,
            )
    ));
}
CODE

自動スクリーンショット(iOS のみ)

デフォルトでは、スクリーンショットのキャプチャは有効になっていますが、(プライバシー上の理由などで)無効にする必要がある場合は、AgentConfiguration オブジェクトで無効にできます。

次は、スクリーンショットを無効にする例です。

AgentConfiguration config = AgentConfiguration(
    appKey: <EUM_APP_KEY>,
	screenshotsEnabled: false);
await Instrumentation.start(config);
CODE

ユーザ データ

すべてのスナップショットに含まれるカスタムユーザーデータのキーと値のペアの識別子を設定できます。考慮事項:

  • キーは、アプリケーション全体で一意である必要があります。
  • キーと関連する値は 2048 文字に制限されています。 
  • null 値によってデータが消去され、同じキーを再使用すると前の値が上書きされます。
  • カスタムユーザーデータは、アプリケーションを実行しても保持されません。アプリケーションが破棄されると、ユーザーデータは消去されます。

仕組み

setUserData(key, value)

string 型を追加するために使用します。

removeUserData(key)

setUserData() で設定したキーに対応する string を削除します。

パラメータ
名前タイプ要件説明
key文字列最大 2048 文字(Null 以外)。ユーザーデータキーの名前。
value文字列最大 2048 文字。

キーに関連付けられた string 値。

setUserDataDouble(key, value)

double 型を追加するために使用します。

removeUserDataDouble(key)

setUserDataDouble() で設定されたキーに対応する double を削除します。

パラメータ
名前タイプ要件説明
key文字列最大 2048 文字(Null 以外)。ユーザーデータキーの名前。
value倍精度浮動小数点型最大 2048 文字。キーに関連付けられた double 値。

setUserDataInt(key, value)

int 型を追加するために使用します。

removeUserDataInt(key)

setUserDataInt() で設定したキーに対応する int を削除します。

パラメータ
名前タイプ要件説明
key文字列最大 2048 文字(Null 以外)。ユーザーデータキーの名前。
value整数最大 2048 文字。キーに関連付けられた int 値。

setUserDataBool(key, value)

bool 型を追加するために使用します。

removeUserDataBool(key)

bool を 削除します (setUserDataBool() で設定したキーに対応する)。

パラメータ
名前タイプ要件説明
key文字列最大 2048 文字(Null 以外)。ユーザーデータキーの名前。
valueブール型-キーに関連付けられた bool 値。

setUserDataDateTime(key, value)

DateTime 型を追加するために使用します。

removeUserDataDateTime(key)

setUserDataDateTime() で設定したキーに対応する DateTime を削除します。

パラメータ
名前タイプ要件説明
key文字列最大 2048 文字(Null 以外)。ユーザーデータキーの名前。
value日時(DateTime)-キーに関連付けられた DateTime 値。

次は、DateTime オブジェクトをユーザーデータとして保存する方法の例です。

await Instrumentation.setUserDataDateTime("currentTransactionYear", DateTime.utc(2021));
CODE

トピックパス(パンくずリスト)

トピックパス(パンくずリスト)を使用して、アプリケーション全体で関心のあるポイントを報告できます。トピックパスは、モードに応じてさまざまなレポートに含まれます。

  • トピックパスをクラッシュレポート(アプリケーションの再起動時にトリガーされる)にのみ表示する場合は、crashesOnly モード(デフォルト)を使用します。
  • セッションにもトピックパスを表示する場合は、crashesAndSessions モードを使用します。

各クラッシュレポートには、最近の 99 件のトピックパスのみが表示されます。

仕組み

leaveBreadcrumb(breadcrumb, mode)

トピックパスの名前と、モバイルセッションでの表示場所を設定します。

パラメータ
名前タイプ要件説明
breadcrumb文字列最大 2048 文字(余分な文字はすべて切り捨てられます)。トピックパスを説明するための文字列。
mode BreadcrumbVisibility (enum)-セッションでトピックパス情報を表示するかどうかを設定します。

次は、サインアップ画面に切り替える前後にトピックパスを配置する方法の例です。

Future<void> showSignUp() async {
  try {
    await Instrumentation.leaveBreadcrumb("Sign up button pressed.",
        BreadcrumbVisibility.crashesAndSessions);
    await pushSignUpScreen();


    await Instrumentation.leaveBreadcrumb("Sign Up screen pushed",
        BreadcrumbVisibility.crashesOnly);
  } catch (e) {
    ...
  }
}
CODE

タイマー

複数のメソッドにまたがるカスタムタイマーを使用して、イベントの時間を計測できます。

仕組み

startTimer(name)

タイマーを設定します。

パラメータ
名前タイプ要件説明
name文字列英数字とスペースのみ(Null 以外)。タイマーに関連付ける一意の識別子。

stopTimer(name)

タイマーを停止します。

パラメータ
名前タイプ要件説明
name文字列英数字とスペースのみ(Null 以外)。タイマーに関連付ける一意の識別子。

次は、チェックアウトにかかる時間をカウントするタイマーを開始する方法の例です。

Future<void> doCheckout() async {
 final checkoutTimerName = "Time spent on checkout";
 try {
   await Instrumentation.startTimer(checkoutTimerName);
   await someCheckoutService();
   await someOtherLongTask();
 } finally {
   await Instrumentation.stopTimer(checkoutTimerName);
 }
}
CODE

エラー

Dart エラー、例外、およびカスタムメッセージを報告できます。

エラーの重大度には以下の 3 つのレベルがあります。

  • info:エラーが発生しましたが、問題にはなりませんでした。
  • warning:エラーが発生しましたが、アプリケーションはグレースフルで回復しました。
  • critical:エラーが発生し、アプリケーションに問題が発生しました。

仕組み

reportException(exception, severityLevel)

エラー例外と関連する重大度レベルを設定します。

パラメータ
名前タイプ要件説明
exceptionException-

Dart Exception 型。

severityLevelErrorSeverityLevel (enum)デフォルトでは60000。 warning

対応する重大度レベル。


reportError(error, severityLevel)

関連する重大度レベルでエラーレポートを作成します。

パラメータ
名前タイプ要件説明
errorError-

Dart Error 型。

severityLevelErrorSeverityLevel (enum)デフォルトでは60000。 warning

対応する重大度レベル。

reportMessage(message, severityLevel)

メッセージレポートを作成します(reportError()reportException() がどちらも適切ではない場合に使用します)。

パラメータ
名前タイプ要件説明
message文字列-

Dart String 型。

severityLevelErrorSeverityLevel (enum)デフォルトでは60000。 warning

対応する重大度レベル。

次は、宣言されていないメソッドを呼び出したときに NoSuchMethodError を報告する方法の例です。

try {
  final myMethod = null;
  myMethod();
} on NoSuchMethodError catch (e) {
  await Instrumentation.reportError(e, severityLevel: ErrorSeverityLevel.CRITICAL);
}
CODE

Application Not Responding(ANR)

AgentConfiguration オブジェクトの作成時に、アプリケーションが応答しない場合(ANR)の自動検出とレポートを設定できます。 

次は、自動 ANR 検出機能を有効にする方法の例です。

AgentConfiguration config = AgentConfiguration(
    appKey: <EUM_APP_KEY>,
    anrDetectionEnabled: true
);
await Instrumentation.start(config);
CODE

情報ポイント

Instrumentation クラスを使用して、アプリケーション内の特定の関心ポイントをトラッキングできます。

方法

trackCall(className, methodName, methodBody, methodArgs, uniqueCallId)

呼び出しにトラッカーを設定します。

パラメータ
名前タイプ要件説明
classNameString-メソッド呼び出しのクラスまたはオブジェクトの名前。
methodName String-メソッドの名前。
methodBodyFutureOr<T> Function()-トラッキングされているメソッドの本文。
methodArgsdynamic-メソッドの引数。
uniqueCallIdString?-この呼び出しをトラッキングするための一意のカスタム ID。

次は、サーバー上のユーザーの姓名を更新する非同期メソッドをトラッキングする例です。

const firstName = "John";
const lastName = "Peters";

final result = await Instrumentation.trackCall(
    className: "MyAccountScreen",
    methodName: "updateUserName",
    methodArgs: [firstName, lastName],
    methodBody: () async {
      await http.post(
        Uri.parse('https://jsonplaceholder.typicode.com/albums'),
        body: jsonEncode(
            <String, String>{'firstName': firstName, 'lastName': lastName}),
      );
    }
);
CODE

セッション

新しいセッションを開始して、現在のセッションの終了をマークできます。

方法

startNextSession()

セッションの開始と終了を設定します。

次は、顧客の前のチェックアウトセッションが終了した後に、新しいチェックアウトセッションをマークする例です。

Future<void> checkout(dynamic data) async {
  try {
    final response = http.post("https://server.com/checkout", data);
    await Instrumentation.startNextSession();
  } catch (e) {
    print(e);
  }
}
CODE

アプリケーションキー

アプリケーションキーは初期化後に変更できます。新しいキーが適用されると、古いレポートは破棄されます。いずれかの開始メソッドを呼び出してエージェントがすでに初期化されていない限り、このメソッドを呼び出しても効果はありません。

メソッド

changeAppKey(newKey)

パラメータ
名前タイプ要件説明
newKeyStringアプリケーションキーの形式を尊重する必要があります(有効である必要があります)。古いキーに代わる新しいキー。

次は、アプリケーションキーを AA-BBB-CCC に更新する例です。

try {
  await Instrumentation.changeAppKey("AA-BBB-CCC");
} catch (e) {
  print(e);
}
CODE

画面トラッキング

NavigationObserver をアプリケーションに追加して、名前付きルートを使用してアプリケーション ウィジェットの遷移を自動的に検出できます。アプリケーションが名前付きルートを実装していない場合は、WidgetTracker クラスを介して画面を手動でトラッキングできます。

仕組み

NavigationObserver

import 'package:appdynamics_mobilesdk/appdynamics_mobilesdk.dart';
import 'package:flutter/material.dart';

void main() {
  runApp(const MyApp());
}

class MyApp extends StatelessWidget {
  const MyApp({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
        initialRoute: MyRoutes.mainScreen,
        onGenerateRoute: MyRouter.onGenerateRoute,
        navigatorObservers: [NavigationObserver()]);
  }
}
CODE

WidgetTracker

Flutter ウィジェットにトラッキングを追加して、特定の UI 要素をモニターできます。たとえば、Flutter アプリケーションが名前付きルートを自動的に実装していない場合、WidgetTracker クラスを介して画面を手動でトラッキングできます。

仕組み
trackWidgetStart()

ウィジェットのトラッキングを開始します。

trackWidgetEnd()

ウィジェットのトラッキングを停止します。

パラメータ
名前タイプ要件説明
widgetNameString一意である必要があります。メソッド呼び出しのクラスまたはオブジェクトの名前。

次は、CheckoutPage.screenName ウィジェットをトラッキングする例です。

import 'package:appdynamics_mobilesdk/appdynamics_mobilesdk.dart';
import 'package:flutter/material.dart';

class CheckoutPage extends StatefulWidget {
  const CheckoutPage({Key? key}) : super(key: key);

  static String screenName = "Checkout Page";

  @override
  _CheckoutPageState createState() => _CheckoutPageState();
}

class _CheckoutPageState extends State<CheckoutPage> {
  @override
  void initState() async {
    super.initState();
    await WidgetTracker.instance.trackWidgetStart(CheckoutPage.screenName);
  }

  _backToMainScreen() async {
    await WidgetTracker.instance.trackWidgetEnd(CheckoutPage.screenName);
    Navigator.pop(context);
  }

  @override
  Widget build(BuildContext context) {
    return Center(
        child:
        Column(crossAxisAlignment: CrossAxisAlignment.stretch, children: [
          ElevatedButton(
            child: const Text('Proceed'),
            onPressed: _backToMainScreen,
          )
        ]));
  }
}
CODE

デバイスメトリック

デバイスのステータスに関するさまざまなメトリックが自動的にトラッキングされます。詳細については、モバイル デバイス メトリック コレクションを参照してください。

Flutter エージェント API ドキュメント

以下の最新の Flutter エージェント API ドキュメントまたは前のバージョンを参照してください。