Flutter インストゥルメンテーションのカスタマイズ

ネットワーク要求

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

DART
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);
}

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

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();
}

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

別の Splunk 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);
}

メソッド

RequestTracker.create(url)

RequestTracker.create(url)

RequestTracker url Instrumentation.start() を返します

パラメータ

Nameタイプ要件説明

url

文字列Null 以外。

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

setError(message, stackTrace)

setError(message, stackTrace)

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

パラメータ

Nameタイプ要件説明

message

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

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

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

setResponseStatusCode(statusCode)

setResponseStatusCode(statusCode)

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

パラメータ

Nameタイプ要件説明

statusCode

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

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

setRequestHeaders(requestHeaders)

setRequestHeaders(requestHeaders)

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

パラメータ

Nameタイプ要件説明

requestHeaders

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

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

setResponseHeaders(responseHeaders)

setResponseHeaders(responseHeaders)

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

パラメータ

Nameタイプ要件説明

responseHeaders

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

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

reportDone()

reportDone()

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

getServerCorrelationHeaders()

getServerCorrelationHeaders()

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

設定ユーザーデータ

setUserdata

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

  • setUserData(key, value)
  • setUserDataBool(key, value)
  • setUserDataDateTime(key, value)
  • setUserDataDouble(key, value)
  • setUserDataInt(key, value)

パラメータ

Nameタイプ要件説明

キー

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

対応する値のキー名。

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

クラッシュ

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

Flutter エージェントは、ネイティブクラッシュ情報を自動的にログに記録します。これは、Instrumentation.start() Get 人間が判読可能なクラッシュスナップショットを呼び出すときに、すでに有効になっています。

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

すべてのエラー(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);
});

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());
}

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

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

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

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

クラッシュコールバック

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

コールバック関数は、AgentConfiguration で設定できます。

void crashReportCallback(List<CrashReportSummary> summaries) async {
print(summaries);
}
AgentConfiguration config = AgentConfiguration(
appKey: <EUM_APP_KEY>,
crashReportCallback: crashReportCallback);
await Instrumentation.start(config);

Session Frames

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

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

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

メソッド

Instrumentation.startSessionFrame(sessionFrameName)

Instrumentation.startSessionFrame(sessionFrameName)

SessionFrame を開始して返します。

パラメータ

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

updateName(newName)

updateName(newName)

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

パラメータ

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

end()

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();
}

メトリクス

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

メソッド

Instrumentation.reportMetric(name, value)

Instrumentation.reportMetric(name, value)

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

パラメータ

Nameタイプ要件説明

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,
)
));
}

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

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

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


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

ユーザ データ

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

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

メソッド

setUserData(key, value)

setUserData(key, value)

次の文字列を追加するために使用

removeUserData(key)

removeUserData(key)

文字列 setUserData() を削除

パラメータ

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

関連付けられた文字列

setUserDataDouble(key, value)

setUserDataDouble(key, value)

double を追加するために使用

removeUserDataDouble(key)

removeUserDataDouble(key)

double setUserDataDouble() を削除

パラメータ

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

setUserDataInt(key, value)

setUserDataInt(key, value)

int を追加するために使用

removeUserDataInt(key)

removeUserDataInt(key)

int setUserDataInt() を削除

パラメータ

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

setUserDataBool(key, value)

setUserDataBool(key, value)

bool を追加するために使用

removeUserDataBool(key)

removeUserDataBool(key)

bool setUserDataBool() を削除

パラメータ

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

setUserDataDateTime(key, value)

setUserDataDateTime(key, value)

DateTime を追加するために使用

removeUserDataDateTime(key)

removeUserDataDateTime(key)

DateTime setUserDataDateTime() を削除

パラメータ

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

これは、DateTime を格納する方法の例です。

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

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

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

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

メソッド

leaveBreadcrumb(breadcrumb, mode)

leaveBreadcrumb(breadcrumb, mode)

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

パラメータ

Nameタイプ要件説明
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) {
...
}
}

タイマー

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

メソッド

startTimer(name)

startTimer(name)

タイマーを設定します。

パラメータ

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

stopTimer(name)

stopTimer(name)

タイマーを停止します。

パラメータ

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);
}
}

エラー

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

エラーのシビラティ(重大度)には以下の 3 つのレベルがあります。

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

メソッド

reportException(exception, severityLevel, stackTrace)

reportException(exception, severityLevel, stackTrace)

エラー例外と関連するシビラティ(重大度)レベルを設定します。

パラメータ

Nameタイプ要件説明
exception Exception -

Dart 例外

severityLevelErrorSeverityLevel(enum)デフォルト:warning

対応するシビラティ(重大度)レベル。

Future<void> _sendException() async {
try {
jsonDecode("invalid/exception/json");
} on FormatException catch (e, stackTrace) {
await Instrumentation.reportException(e,
severityLevel: ErrorSeverityLevel.warning, stackTrace: stackTrace);
}
}

reportError(error, severityLevel, stackTrace)

reportError(error, severityLevel, stackTrace)

関連するシビラティ(重大度)レベルでエラーレポートを作成します。

パラメータ

Nameタイプ要件説明
error Error -

Dart エラー

severityLevelErrorSeverityLevel(enum)デフォルトでは60000。 warning 対応するシビラティ(重大度)レベル。
Future<void> _sendError() async {
try {
const myMethod = null;
myMethod();
} on NoSuchMethodError catch (e) {
await Instrumentation.reportError(e,
severityLevel: ErrorSeverityLevel.critical);
}
}

reportMessage(message, severityLevel, stackTrace)

reportMessage(message, severityLevel, stackTrace)

メッセージレポートを作成します(reportError()、reportException() のいずれも使用できない場合)。

パラメータ

Nameタイプ要件説明
message文字列-

Dart 文字列

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

対応するシビラティ(重大度)レベル。

これは、NoSuchMethodError を報告する方法の例です。

Future<void> _sendMessage() async {
try {
jsonDecode("invalid/message/json");
} on FormatException catch (e, stackTrace) {
await Instrumentation.reportMessage(e.toString(),
severityLevel: ErrorSeverityLevel.info, stackTrace: stackTrace);
}
}

アプリケーションが応答しない(ANR)

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

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

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

情報ポイント

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

メソッド

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

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

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

パラメータ

Name タイプ 要件 説明
className String - メソッド呼び出しのクラスまたはオブジェクトの名前。
methodName String - メソッドの名前。
methodBody FutureOr<T> Function() - トラッキングされているメソッドの本文。
methodArgs dynamic - メソッドの引数。
uniqueCallId String? - この呼び出しをトラッキングするための一意のカスタム 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}),
);
}
);

セッション

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

メソッド

startNextSession()

startNextSession()

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

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

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

アプリケーションキー

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

メソッド

changeAppKey(newKey)

changeAppKey(newKey)

パラメータ

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

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

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

画面トラッキング

「ルート」という名前の 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()]);
}
}

WidgetTracker

WidgetTracker

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

メソッド

trackWidgetStart()

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

trackWidgetEnd()

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

パラメータ

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

次は、ウィジェット 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,
)
]));
}
}