Download PDF
Download page iOS インストゥルメンテーションのカスタマイズ.
iOS インストゥルメンテーションのカスタマイズ
Related pages:
モバイル iOS SDK を使用して iOS アプリケーションをインストゥルメント化すると、SDK が公開する API を使用して、コントローラ UI に表示されるアプリケーションのデータをカスタマイズすることもできます。
以下のセクションでは、iOS SDK を使用してインストゥルメンテーションをカスタマイズする方法について説明します。
エージェントは情報を報告する前にローカルバッファにイベントに関するデータを保存するため、慎重に API を使用することをお勧めします。
データの追加タイプの収集
ADEUMInstrumentation クラスで使用可能なメソッドを使用して、6 つの追加タイプのデータを収集できます。
データのタイプ | 説明 | 仕様 | データが表示される場所 |
---|---|---|---|
情報ポイント | メソッドが呼び出される頻度と実行される時間。 |
| |
カスタムタイマー | コード内の任意のイベントシーケンスが、 複数のメソッドにまたがる場合でも、時間を計測。 |
| |
カスタムメトリック | 収集する整数ベースのデータ。 |
| |
ユーザデータ | 有用と思われる任意の文字列キーと値のペア |
| |
トピックパス(パンくずリスト) | クラッシュのコンテキスト。 |
| |
ユーザの操作 | ユーザがボタンを押したとき、リストをクリックしたとき、およびテキストを選択したときにキャプチャ。 |
|
追加のデータ型を設定した場合、モバイルエージェントはモバイルビーコンでそのデータをパッケージ化します。通常、ビーコンはインストゥルメント化されたアプリケーションが HTTP リクエストを送信したとき、またはクラッシュ後にアプリケーションが再起動されたときに送信されますが、カスタムデータが収集され、これらのイベントのいずれも 5 分以上発生していない場合は、カスタムデータはその時点で送信されます。
情報ポイント
情報ポイントを使用すると、独自のコードがどのように実行されているかを追跡できます。次のように beginCall
と endCall
を使用して、メソッドが呼び出される頻度と実行にかかる時間を確認できます。
- (void)myMethod
{
id tracker = [ADEumInstrumentation beginCall:self selector:_cmd];
// Implementation of method here ...
[ADEumInstrumentation endCall:tracker];
}
func myMethod() {
let tracker = ADEumInstrumentation.beginCall(self, selector: #function)
// Implementation of method here ...
ADEumInstrumentation.endCall(tracker)
}
例外がスローされた場合も報告されます。この情報は、コントローラ UI の [Custom Data] ビューに表示されます。
カスタムタイマー
カスタムタイマーでは、startTimer
と stopTimer
を使用して、複数のメソッドにまたがる場合でも、コード内の任意のイベントシーケンスの時間を測定できます。たとえば、ユーザが画面を表示する際にかかった時間を追跡する場合、インストゥルメンテーションは次のようになります。
- (void)viewDidAppear:(BOOL)animated {
[super viewDidAppear:animated];
[ADEumInstrumentation startTimerWithName:@"View Lifetime"];
}
- (void)viewDidDisappear:(BOOL)animated {
[super viewDidDisappear:animated];
[ADEumInstrumentation stopTimerWithName:@"View Lifetime"];
}
func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
ADEumInstrumentation.startTimer(withName: "View Lifetime")
}
func viewDidDisappear(_ animated: Bool) {
super.viewDidDisappear(animated)
ADEumInstrumentation.stopTimer(withName: "View Lifetime")
}
この情報は、コントローラ UI の [Custom Data] ビューに表示されます。
同じ名前値を使用して startTimerWithName
を再度呼び出すと、名前付きタイマーがリセットされます。
Custom Metrics
任意の整数ベースのデータをエージェントに渡すことができます。report.MetricWithName
コールの最初のパラメータは、メトリックをコントローラ UI に表示する場合の名前です。メトリック名には、英数字とスペースのみを使用します。不正な文字は、ASCII 16 進値に置き換えられます。
たとえば、「My custom metric」というメトリックを報告する場合は、次のようになります。
[ADEumInstrumentation reportMetricWithName:@"My custom metric" value:<#VALUE HERE#>];
この情報は、コントローラ UI の [Custom Data] ビューに表示されます。
ユーザ データ
有用と思われる任意の文字列キーと値のペアを設定できます。setUserData
コールの最初のパラメータは、使用するキーです。これはアプリケーション全体で一意である必要があります。2 番目パラメータは、キーに割り当てる値です。
例:
- (void) onUserLoggedIn:(NSString *)userid {
[ADEumInstrumentation setUserData:@"User ID" value:userid];
...
}
func onUserLogged(in userid: String?) {
ADEumInstrumentation.setUserData("User ID", value: userid)
}
この情報は、[Network Request Analyze] で確認でき、取得可能なクラッシュスナップショットに追加されます。キーと値はそれぞれ 2048 文字に制限されています。
また、次のメソッドを使用して、他のデータ型(Long、Boolean、Double、Date)の値を含むユーザデータを設定することもできます。
トピックパス(パンくずリスト)
トピックパスを使用すると、ユーザエクスペリエンスのコンテキストでクラッシュの場所を特定できます。問題が発生したときに、トピックパスを設定します。その後のある時点でアプリケーションがクラッシュした場合、トピックパスはクラッシュレポートとともに表示されます。
トピックパスを残すには、次の 2 つの方法があります。
次のメソッドを使用すると、トピックパスがクラッシュレポートのみで報告されます。
+ (void)leaveBreadcrumb:(NSString *)breadcrumb
次のメソッドを使用すると、トピックパスが報告される場所を微調整(クラッシュレポートのみ、またはクラッシュレポートとセッションを選択)できます。
+ (void)leaveBreadcrumb:(NSString *)breadcrumb mode:(ADEumBreadcrumbVisibility)mode
ここで、mode
は次のいずれかです。
ADEumBreadcrumbVisibilityCrashesOnly
ADEumBreadcrumbVisibilityCrashesAndSessions
breadcrumb
が 2048 文字を超えている場合は、切り捨てられます。空または nil
の場合、トピックパスは記録されません。各クラッシュレポートには、最近の 99 件のトピックパスが表示されます。
ユーザインタラクションのキャプチャ
iOS エージェントが、ユーザインタラクションによってトリガーされた特定の UI イベントを追跡するように設定できます。ユーザインタラクションがキャプチャされると、UI イベントでセッションをソートし、セッション ウォーターフォールのタイムラインで UI イベントを表示できます。
ユーザが次のいずれかまたはすべてを実行するときにキャプチャできます。
- ボタンのクリック
- テーブルセルの選択
- テキストフィールドの選択
- テキストビューの選択
セキュリティおよびプライバシー上の懸念点
インタラクション キャプチャ モードは、セキュリティとプライバシー上の理由でデフォルトでは無効になっています。これは、ユーザインタラクションに機密情報が含まれている可能性があるためです。さらに、UI インタラクションとスクリーンショットのキャプチャの両方を有効にすると、このような潜在的なセキュリティとプライバシー上の問題が複合化する場合があります。
ユーザ インタラクション キャプチャ モードの有効化
ユーザ インタラクション キャプチャ モードを有効にするには、ADEumAgentConfiguration
オブジェクトの interactionCaptureMode
プロパティにキャプチャモードを割り当てます。次のインストゥルメンテーション コードの例では、サポートされているすべてのタイプのユーザインタラクションをキャプチャするように iOS エージェントを構成します。
ADEumAgentConfiguration *config = [[ADEumAgentConfiguration alloc] initWithAppKey: <#EUM_APP_KEY#>];
config.interactionCaptureMode = ADEumInteractionCaptureModeAll;
[ADEumInstrumentation initWithConfiguration:config];
また、1 つのタイプのユーザインタラクションのみをキャプチャするように iOS エージェントを構成することもできます。
ADEumAgentConfiguration *config = [[ADEumAgentConfiguration alloc] initWithAppKey: <#EUM_APP_KEY#>];
config.interactionCaptureMode = ADEumInteractionCaptureModeButtonPressed;
[ADEumInstrumentation initWithConfiguration:config];
プログラムによるスクリーンショットの取得
デフォルトでは、モバイルスクリーンショットはエージェント側で有効になりますが、コントローラ側では無効になります。プログラムで手動でスクリーンショットを取得するには、コントローラ UI でスクリーンショットを有効にし、次の API を追加する必要があります。
[ADEumInstrumentation takeScreenshot];
ADEumInstrumentation.takeScreenshot()
スクリーンショットの無効化
スクリーンショットは、コントローラ UI または iOS SDK を使用して無効にできます。iOS SDK を使用してスクリーンショットを無効にするには、次に示すように ADEumAgentConfiguration
オブジェクトのプロパティ screenshotsEnabled
を NO
(Objective-C の場合)または false
(Swift の場合)に設定します。
ADEumAgentConfiguration *config = [[ADEumAgentConfiguration alloc] initWithAppKey: <#EUM_APP_KEY#>];
config.screenshotsEnabled = NO;
[ADEumInstrumentation initWithConfiguration:config];
let config = ADEumAgentConfiguration(appKey: <#EUM_APP_KEY#>);
config.screenshotsEnabled = false;
ADEumInstrumentation.initWith(config);
スクリーンショットのブロックとブロック解除
iOS SDK を使用して、コードブロックの実行中にスクリーンショットが実行されないようにすることもできます。これにより、スクリーンショットのブロックを解除するまで、スクリーンショットの作成が一時的にブロックされます。これにより、ユーザがログインやアカウント画面などで個人データを入力する状況でのスクリーンショットの作成を停止できます。
ADEumInstrumentation
クラスでは、スクリーンショットをブロックおよびブロック解除するためのメソッド、blockScreenshots
と unblockScreenshots
が使用できます。スクリーンショットが ADEumAgentConfiguration
オブジェクトの screenshotsEnabled
プロパティまたはコントローラ UI によって無効になっている場合、これらのメソッドは無効になります。スクリーンショットがブロックされているかどうかを確認するために screenshotsBlocked
を呼び出すこともできます。
次の例は、API を使用して、ユーザログインのスクリーンショットをブロックおよびブロック解除する方法を示しています。
#import "ADEumInstrumentation.h"
...
- (IBAction)loginUser:(id)sender {
if(![ADEumInstrumentation screenshotsBlocked]) {
[ADEumInstrumentation blockScreenshots];
}
LoginCredentials creds = [UserLogin getUserCreds];
if(creds.authorized) {
[LoginUser redirectToProfile:creds.user]
[ADEumInstrumentation unblockScreenshots];
}
}
...
import ADEumInstrumentation
...
@IBAction func loginUser(_ sender: UIButton) {
if(!ADEumInstrumentation.screenshotsBlocked()) {
ADEumInstrumentation.blockScreenshots()
}
let creds = UserLogin.getUserCreds()
if(creds.authorized) {
LoginUser.redirectToProfile(credits.user)
ADEumInstrumentation.unblockScreenshots()
}
}
...
コレクタへのユーザデータの送信を停止する場合のエージェントの無効化
エージェントの初期化中および実行中に、エージェントを無効にしてコレクタへのすべてのデータの送信を停止できます。たとえば、プライバシー上の理由でユーザがモニタリングをオプトアウトするオプションがアプリにある場合は、エージェントを無効にできます。
shutdownAgent
shutdownAgent
コールはコレクタへの発信データを停止し、デバイスにデータを保持しません。
[ADEumInstrumentation shutdownAgent];
ADEumInstrumentation.shutdownAgent()
- このコールは、エージェントからのトラフィックのみを停止します。
- エージェントが初期化されると、コールは削除できず、ライセンスが消費されます。
- この状態をデバイスで永続的にする場合は、UserDefaults にコードを追加して状態を保存し、そのフラグを使用してコード内のエージェントを条件付きで初期化します。
restartAgent
エージェントを再度有効にして shutdownAgent
を無効にする場合は、restartAgent
を使用します。
[ADEumInstrumentation restartAgent];
ADEumInstrumentation.restartAgent();
- このコールは、同様にリモートでエージェントをシャットダウンできるサーバ側のコールにも対応します。
- コールは、アプリケーションの実行中にのみ有効です。
- エージェントがリモートで無効になっている場合、コールは無視されます。
- コールがメモリから削除され、アプリケーションが再起動されるか、デバイスが再起動されると、エージェントは通常どおり初期化されます。
クラッシュ レポート コールバックの追加
モバイル RUM を使用している場合、コードの他の部分(Google Analytics など)がモバイル RUM が収集するクラッシュレポート情報を使用できるようにすることがあります。サマリークラッシュ情報を渡せるようにするには、クラッシュレポートのランタイムコールバックを設定します。iOS エージェントがクラッシュを検出して報告するときにコールバックを取得するには、コードに次のプロトコルを実装する必要があります。
@protocol ADEumCrashReportCallback <NSObject>
- (void)onCrashesReported:(NSArray<ADEumCrashReportSummary *> *)crashReportSummaries;
@end
このコールバックはアプリケーションの UI スレッドで呼び出されるため、重要な作業は別の作業スレッドで実行する必要があります。
渡される各 ADEumCrashReportSummary
には、次のプロパティがあります。
@interface ADEumCrashReportSummary : NSObject
/** Uniquely defines the crash, can be used as key to find full crash report. */
@property (nonatomic, readonly) NSString *crashId;
/** The exception name, may be `nil` if no `NSException` occured. */
@property (nonatomic, readonly) NSString * ADEUM_NULLABLE exceptionName;
/** The exception reason, may be `nil` if no `NSException` occured. */
@property (nonatomic, readonly) NSString * ADEUM_NULLABLE exceptionReason;
/** The Mach exception signal name */
@property (nonatomic, readonly) NSString *signalName;
/** The Mach exception signal code */
@property (nonatomic, readonly) NSString *signalCode;
@end
Google Analytics などの別の分析ツールに情報を送信する場合は、次の 5 つのプロパティすべてを含めることをお勧めします。
exceptionName
とexceptionReason
はオプションであり、クラッシュの原因をすばやく特定するのに役立ちます。これらは、例外レポートランタイム(Objective-C など)内でクラッシュ原因が発生した場合にのみ表示されます。signalName
とsignalCode
は、クラッシュをすばやく識別するのに役立ちます。これらはシステムから取得するものであり、ランタイムとは独立しています。その他の情報については、
crashId
を使用すると、AppDynamics コントローラ UI でクラッシュを検索できます。
たとえば、クラッシュ情報を iOS ロガーに出力するには、次のような ADEumCrashReportCallback
クラスを実装することもできます。
// assumes the containing object has "adopted" the protocol
- (void)onCrashesReported:(NSArray<ADEumCrashReportSummary *> *)summaries {
for (ADEumCrashReportSummary *summary in summaries) {
NSLog(@"Crash ID: %@", summary.crashId);
NSLog(@"Signal: %@ (%@)", summary.signalName, summary.signalCode);
NSLog(@"Exception Name:\n%@", summary.exceptionName);
NSLog(@"Exception Reason:\n%@", summary.exceptionReason);
}
}
エージェントの構成時に、ADEumCrashReportCallback
プロトコルを実装するオブジェクトを設定します。
ADEumAgentConfiguration *config = [ADEumAgentConfiguration new];
config.crashReportCallback = myCrashReportCallback;
前回の実行からクラッシュの検出と収集が行われた場合、メイン/UI スレッドでコールバックが呼び出されます。詳細については、最新の iOS SDK ドキュメントを参照してください。
クラッシュレポートの無効化
クラッシュレポートはデフォルトで有効になっていますが、インストゥルメンテーション構成を使用して手動でクラッシュレポートを無効にできます。他のクラッシュレポートツールを使用している場合、競合を最小限に抑え、クラッシュレポートの結果を最適化するために、クラッシュレポートを無効にする場合があります。
次のコード例に示すように、 crashReportingEnabled
プロパティを使用してインストゥルメンテーションを構成することにより、クラッシュレポートを無効にできます。
ADEumAgentConfiguration *config = [[ADEumAgentConfiguration alloc] initWithAppKey:appKey];
config.crashReportingEnabled = No
[ADEumInstrumentation initWithConfiguration:config];
let config = ADEumAgentConfiguration(appKey: <#EUM_APP_KEY#>);
config.crashReportingEnabled = false;
ADEumInstrumentation.initWith(config);
エラーと例外のレポート
ADEumInstrumentation
クラスの reportError
メソッドを使用して例外を報告できます。報告された例外は、セッション詳細に表示されます。
このメソッドには、次の 2 つの署名があります。
Objective-C 関数の署名 | 説明 |
---|---|
(void)reportError:(NSError *)error withSeverity (ADEumErrorSeverityLevel)severity; | この署名を使用してエラーを報告し、問題の重大度レベルを設定し、スタックトレースを送信します。 この関数の署名は、デフォルトでスタックトレースを送信します。スタックトレースを送信しない場合は、次の関数の署名を追加の引数 |
(void)reportError:(NSError *)error withSeverity:(ADEumErrorSeverityLevel)severity andStackTrace:(BOOL)stacktrace; | この署名を使用してエラーを報告し、問題の重大度レベルを設定し、スタックトレースを含めるかどうかを明示的に指定します。
スタックトレースなしでエラーを報告するには、 |
重要度レベル
問題に次の重大度レベルのいずれかを設定することもできます。重大度レベルを使用すると、[Code Issues Dashboard] または [Code Issues Analyze] でエラーをフィルタリングできます。
ADEumErrorSeverityLevelInfo
ADEumErrorSeverityLevelWarning
ADEumErrorSeverityLevelCritical
エラーレポートの例
次の例では、API を使用して考えられる例外を報告し、ファイル操作の実行に失敗した場合に重大度を ADEumErrorSeverityLevelCritical
に設定します。
NSError *err = nil;
[[NSFileManager defaultManager] contentsOfDirectoryAtPath:@"pathToFile" error:&err];
if (err) {
[ADEumInstrumentation reportError:err withSeverity:ADEumErrorSeverityLevelCritical, andStackTrace: NO];
} else {
...
}
var err: Error? = nil
try? FileManager.default.contentsOfDirectory(atPath: "pathToFile")
if err != nil {
ADEumInstrumentation.reportError(err, withSeverity: ADEumErrorSeverityLevelCritical, andStackTrace: false)
} else {
...
}
次のようにカスタムエラーを作成して報告することもできます。reportError
では引数 andStackTrace
が渡されないため、デフォルトではスタックトレースが自動的にエラーに含まれることに注意してください。
NSString *domain = @"com.YourCompany.AddUsers.ErrorDomain";
NSString *desc = NSLocalizedString(@"Unable to add user.", @"");
NSDictionary *userInfo = @{ NSLocalizedDescriptionKey : desc };
NSError *error = [NSError errorWithDomain:domain
code:-101
userInfo:userInfo];
[ADEumInstrumentation reportError:error withSeverity: ADEumErrorSeverityLevelWarning];
var domain = "com.YourCompany.AddUsers.ErrorDomain"
var desc = NSLocalizedString("Unable to add user.", comment: "")
var userInfo = [NSLocalizedDescriptionKey: desc]
var error = NSError(domain: domain, code: -101, userInfo: userInfo)
ADEumInstrumentation.reportError(error, withSeverity: ADEumErrorSeverityLevelWarning)
Application-Not-Responding(ANR)検出の構成
デフォルトでは、iOS エージェントは ANR 問題を検出しません。また、ANR 検出が有効になっている場合、ANR 問題はスタックトレースなしで報告されます。手動で ANR 検出を有効にし、iOS エージェント構成を使用してスタックトレースを含めるようにフラグを設定する必要があります。ANR モニタリングの詳細については、「コードの問題」を参照してください。ANR 問題のしきい値を指定する場合は、「アプリケーションが応答しないしきい値の設定」を参照してください。
ANR 検出の有効化
次に示すように、anrDetectionEnabled
プロパティを使用してインストゥルメンテーションを構成することによって、ANR 問題の検出を有効にします。
ADEumAgentConfiguration *adeumAgentConfig = [[ADEumAgentConfiguration alloc] initWithAppKey: <#EUM_APP_KEY#>];
// Enable ANR detection
adeumAgentConfig.anrDetectionEnabled = YES;
[ADEumInstrumentation initWithConfiguration:adeumAgentConfig];
let config = ADEumAgentConfiguration(appKey: <#EUM_APP_KEY#>);
// Enable ANR detection
config.anrDetectionEnabled = true;
ADEumInstrumentation.initWith(config);
ANR を使用したスタックトレースのレポート
ANR 検出を有効にすることに加えて、プロパティ anrStackTraceEnabled
を YES
(Objective-C)または true
(Swift)に設定して、ANR でスタックトレースを報告します。
ADEumAgentConfiguration *adeumAgentConfig = [[ADEumAgentConfiguration alloc] initWithAppKey: <#EUM_APP_KEY#>];
// Enable ANR detection
adeumAgentConfig.anrDetectionEnabled = YES;
// Set the flag to include stack traces with ANRs
adeumAgentConfig.anrStackTraceEnabled = YES;
[ADEumInstrumentation initWithConfiguration:adeumAgentConfig];
let config = ADEumAgentConfiguration(appKey: <#EUM_APP_KEY#>)
// Enable ANR detection
config.anrDetectionEnabled = true
// Set the flag to include stack traces with ANRs
config.anrStackTraceEnabled = true
ADEumInstrumentation.initWith(config)
ハイブリッド アプリケーション サポートの構成
デフォルトでは、iOS エージェントは iOS WKWebView をインストゥルメント化しますが、Ajax コールを収集して報告することはありません。この機能の概要と説明については、「ハイブリッド アプリケーションのサポート」を参照してください。
ハイブリッド アプリケーション サポートを無効にしたり、動作を変更したりするには、静的またはランタイム構成を設定します。次のセクションでは、ランタイム構成または静的構成のいずれかを使用して、ハイブリッドサポートのデフォルト設定を変更する方法を示します。
ハイブリッド アプリケーション サポートのランタイム構成
次のコード例では、JavaScript エージェントのインジェクションを無効にしています。インジェクションを無効にすると、アプリケーション内の WKWebView はインストゥルメント化されず、Ajax コールは報告されません。
ADEumAgentConfiguration *adeumAgentConfig = [[ADEumAgentConfiguration alloc] initWithAppKey: <#EUM_APP_KEY#>];
// Disable the JavaScript Agent Injection
adeumAgentConfig.jsAgentEnabled = NO;
[ADEumInstrumentation initWithConfiguration:adeumAgentConfig];
JavaScript エージェントのインジェクションはデフォルトで有効になっています。Ajax コールの収集とレポートも有効にするには、次のようにします。
ADEumAgentConfiguration *adeumAgentConfig = [[ADEumAgentConfiguration alloc] initWithAppKey: <#EUM_APP_KEY#>];
// Enable the collection and reporting of Ajax calls
adeumAgentConfig.jsAgentAjaxEnabled = YES;
[ADEumInstrumentation initWithConfiguration:adeumAgentConfig];
ハイブリッド アプリケーション サポートの静的構成
次の場合には、静的構成を使用する必要があります。
- 強制的に WKWebView や Ajax コールをインストゥルメント化する(ランタイム構成をオーバーライドする)
- ハイブリッドサポートを無効にし、ランタイム構成をオーバーライドする
- URL を自己ホストされた JavaScript 拡張ファイルに設定する
次の表は、info.plist
ファイルでサポートされているプロパティとデフォルト値を示しています。
プロパティ | デフォルト値 | 説明 |
---|---|---|
| true | クライアントがこのフラグに インジェクションは、新しい WKWebView の作成時に発生します。このため、このフラグが |
ForceWebviewInstrumentation | false | true に設定すると、iOS エージェントはランタイム構成に関係なく、JavaScript エージェントを WKWebView に挿入します。 |
ForceAjaxInstrumentation | true | true に設定すると、ランタイム構成に関係なく、Ajax オペレーションは常に収集および報告されます。 |
ADRUMExtUrlHttp | JavaScript エージェントは、基本 JavaScript エージェントと JavaScript エージェントの拡張という 2 つのコンポーネントで構成されています。基本 JavaScript エージェントは、モバイルエージェントのバイナリに組み込まれ、上記のルールに従って挿入されます。 初期化後、JavaScript エージェントは、これらのプロパティによって指定された URL から JavaScript エージェント拡張を取得します。 | |
ADRUMExtUrlHttps | https://cdn.appdynamics.com/ |
構成例
次の info.plist
の例では、強制的に WKWebView をインストゥルメント化(ランタイム構成をオーバーライド)しますが、Ajax リクエストの収集とレポートは強制されません。この構成では、JavaScript 拡張ファイルが取得される URL も設定されます。
<plist>
<dict>
...
<key>ADEUM_Settings</key>
<dict>
<key>ForceWebviewInstrumentation</key>
<true/>
<key>ForceAjaxInstrumentation</key>
<false/>
<key>ADRUMExtUrlHttp</key>
<string>http://<your-domain>/adrum.cdn</string>
<key>ADRUMExtUrlHttps</key>
<string>https://<your-domain>/adrum.cdn</string>
</dict>
...
</dict>
</plist>
プログラムによるセッションの制御
デフォルトでは、ユーザが非アクティブになってからモバイルセッションが終了します。たとえば、ユーザがアプリケーションを開くと、セッションは開始され、ユーザが設定した期間にアプリケーションを使用しなくなった後にのみ終了します。ユーザがアプリケーションの再使用を開始すると、新しいセッションが開始されます。
ただし、セッションの期間を定義するのに非アクティブな期間を設定する代わりに、次の API を使用して、セッションの開始と終了をプログラムで制御できます。
- (void)startNextSession
ADEumInstrumentation
クラスの startNextSession
メソッドを呼び出すと、現在のセッションが終了し、新しいセッションが開始されます。API を使用すると、セッションを定義してフレーム化することができます。これにより、ビジネス目標と予想されるユーザフローをより厳密に合わせることができます。たとえば、API を使用して、製品の購入を追跡するセッションを定義したり、新しいユーザを登録したりすることができます。
この API を過剰に使用すると、セッションが調整されます(過剰使用は iOS エージェントごとに 1 分あたり 10 コールを超えた場合になりますが、変更される可能性があります)。API を使用しない場合、セッションは、ユーザが非アクティブになった後、デフォルトの終了にフォールバックします。
プログラムによって制御されるセッションの例
次の例では、現在のセッションが終了し、チェックアウトが行われると新しいセッションが開始されます。
-(void) checkout {
AppDelegate *appDelegate = (AppDelegate *) [[UIApplication sharedApplication] delegate];
NSString *checkoutUrl = [appDelegate.url stringByAppendingString:@"rest/cart/co/"];
NSURL *url = [NSURL URLWithString:checkoutUrl];
NSMutableURLRequest *request = [[NSMutableURLRequest alloc] initWithURL:url cachePolicy:NSURLRequestUseProtocolCachePolicy timeoutInterval:60.0];
NSURLResponse *response = nil;
NSError *error = nil;
NSData *body = [NSURLConnection sendSynchronousRequest:request returningResponse:&response error:&error];
const char *responseBytes = [body bytes];
if (responseBytes == nil)
checkoutResponse = [NSString stringWithUTF8String:"Could not connect to the server"];
else {
checkoutResponse = [NSString stringWithUTF8String:responseBytes];
[ADEumInstrumentation startNextSession];
}
}
func checkout() {
let appDelegate = UIApplication.shared.delegate as? AppDelegate
let checkoutUrl = appDelegate?.url ?? "" + ("rest/cart/co/")
let url = URL(string: checkoutUrl)
var request: NSMutableURLRequest? = nil
if let url = url {
request = NSMutableURLRequest(url: url, cachePolicy: .useProtocolCachePolicy, timeoutInterval: 60.0)
}
var response: URLResponse? = nil
var error: Error? = nil
var body: Data? = nil
if let request = request {
body = try? NSURLConnection.sendSynchronousRequest(request, returning: &response)
}
let responseBytes = Int8(body?.bytes ?? 0)
if responseBytes == nil {
checkoutResponse = String(utf8String: "Could not connect to the server")
} else {
checkoutResponse = String(utf8String: &responseBytes)
ADEumInstrumentation.startNextSession()
}
}
セッションフレームの開始と終了
SessionFrame
API を使用して、セッションアクティビティに表示されるセッションフレームを作成できます。セッションフレームは、セッション中にユーザが実行している内容のコンテキストを提供します。この API を使用すると、ユーザ画面の命名方法が向上し、ビジネスコンテキスト内のユーザフローを記録できます。
使用例
次に、SessionFrame
API の一般的な使用例を示します。
- 1 つの
ViewController
では複数の関数が実行されていて、個々の関数をより詳細にトラッキングする必要があります。 - ユーザフローは、複数の ViewController またはユーザの操作におよびます。たとえば、API を使用してセッションフレーム「Login」、「Product Selection」、および「Purchase」を作成して、ユーザが購入のためにフローを記録することができます。
- ユーザの操作に基づいて動的情報をキャプチャし、オーダー ID などのセッションフレームに名前を付けることができます。
SessionFrame API
次の表に、セッションフレームで使用できる3つの方法を示します。つまり、startSessionFrame
を使用してセッションフレームを開始してから、返された ADeumSessionFrame
オブジェクトを使用してセッションフレームの名前を変更し、終了します。
クラス | メソッド | [説明(Description)] |
---|---|---|
|
| セッションフレームを開始して名前を付けるには、これを使用します。セッションフレームに名前を付けると、[Sessions Dialog] でフレームを簡単に識別して追跡できます。 |
|
| セッションフレームの名前を変更します。 |
ADEumSessionFrame |
| セッションフレームを終了します。 |
クラス | メソッド | [説明(Description)] |
---|---|---|
| startSessionFrame(_ name: String?) -> ADEumSessionFrame | セッションフレームを開始して名前を付けるには、これを使用します。セッションフレームをネーミングすると、のフレームを簡単に識別して追跡できます。Sessions Dialog. |
ADEumSessionFrame | updateName(_ name: String?) | セッションフレームの名前を変更します。startSessionFrame から返された ADEumSessionFrame オブジェクトからこのメソッドを呼び出すことができます。 |
ADEumSessionFrame | end() | セッションフレームを終了します。startSessionFrame から返された ADEumSessionFrame オブジェクトからこのメソッドを呼び出すことができます。 |
セッションフレームの例
次の例では、 SessionFrame
チェックアウトプロセス中にユーザアクティビティを追跡するために API が使用されます。
#import "ADEumSessionFrame.h"
...
@property (nonatomic, strong) ADEumSessionFrame *checkoutSessionFrame;
- (IBAction)checkoutCartButtonClicked:(id)sender {
// The user starting to check out starts when the user clicks the checkout button
// this may be after they have updated quantities of items in their cart, etc.
checkoutSessionFrame = [ADEumInstrumentation startSessionFrame:@"Checkout"];
}
- (IBAction)confirmOrderButtonClicked:(id)sender {
// 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.
NSString *newSessionName = [NSString stringWithFormat:@"Checkout: Order ID %@",orderId];
[checkoutSessionFrame updateName:newSessionName];
}
- (void)processOrderCompleted {
// Once the order is processed, the user is done "checking out" so we end
// the session frame
[checkoutSessionFrame end];
checkoutSessionFrame = nil;
}
- (void)checkoutCancelled {
// 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.
[checkoutSessionFrame end];
checkoutSessionFrame = nil;
}
import ADEumSessionFrame
...
var checkoutSessionFrame: ADEumSessionFrame?
@IBAction func checkoutCartButtonClicked(_ sender: UIButton) {
// The check out starts when the user clicks the checkout button.
// This may be after they have updated quantities of items in their cart, etc.
checkoutSessionFrame = ADEumInstrumentation.startSessionFrame("Checkout")
}
@IBAction func confirmOrderButtonClicked(_ sender: UIButton) {
// Once users 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.
let newSessionName = "Checkout: Order ID \(orderId)"
checkoutSessionFrame.updateName(newSessionName)
}
func processOrderCompleted() {
// Once the order is processed, the user is done "checking out", so we end the session frame.
checkoutSessionFrame.end()
checkoutSessionFrame = nil
}
func checkoutCancelled() {
// 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.
checkoutSessionFrame.end()
checkoutSessionFrame = nil
}
カスタムアプリケーション名のエージェントの構成
デフォルトでは、AppDynamics はアプリケーションの名前を自動的に検出します。アプリケーション名は、バンドル ID の文字列形式です。したがって、バンドル ID が com.example.appdynamics.HelloWorld
の場合、アプリケーション名は「com.example.appdynamics.HelloWorld」となります。
ただし、原則としてさまざまな地域のアプリケーションストアに異なるバンドル ID を付けたアプリケーションバイナリを展開することがあります。バンドル ID が異なる場合でも、1 つのアプリケーションに属するすべてのデータがまとめて収集され表示されるようにするには、アプリケーションにカスタム名を指定して共通名を設定します。これを行うには、ADEumInstrumentation
の設定に使用する ADEumAgentConfiguration
インスタンスでアプリケーション名プロパティを設定します。詳細については、最新の iOS SDK ドキュメントを参照してください。
@property (nonatomic, strong) NSString *applicationName;
一部の HTTP リクエストを無視するためのエージェントの構成
NSURL を使用した HTTP リクエストは、アプリケーションの内部で使用され、実際のネットワークリクエストを表すものではない場合があります。これらのリクエストに基づいて作成されたメトリックは、一般的に問題の追跡には役立たないため、そのデータが収集されないようにする場合があります。特定の NSURL リクエストを無視するには、ADEumInstrumentation
の設定に使用する ADEumAgentConfiguration
インスタンスに除外 URL パターンプロパティを設定します。できるだけ簡潔な正規表現を使用します。詳細については、最新の iOS SDK ドキュメントを参照してください。
@property (nonatomic, strong) NSSet * excludedUrlPatterns;
カスタム HTTP ライブラリでのエージェントの使用
iOS エージェントは、 NSURLConnection
または NSURLSession
クラスのいずれかによって基盤となる実装が処理されたときに、自動的にネットワークリクエストを検出します。これにより、ほとんどの iOS ネットワークリクエストが対象になります。ただし、モバイルアプリケーションでは、カスタム HTTP ライブラリが使用される場合があります。
- iOS エージェントがカスタムライブラリからのリクエストを検出するには、
ADEumHTTPRequestTracker
クラスを使用してアプリケーションに手動でリクエスト トラッキング コードを追加します。 - サーバ側の処理との相関を許可するようにヘッダーを設定するには、
ADEumServerCorrelationHeaders
クラスを使用します。 - カスタムライブラリを使用して、HTTP 経由でビーコンを送信するようにエージェントを構成するには、
ADEumCollectorChannel
プロトコルとADEumAgentConfiguration
クラスを使用します。
リクエストトラッキングの追加
リクエストトラッキングを手動で追加するには、リクエストの開始と終了のタイミングをエージェントに通知します。また、応答のステータスをエージェントに通知するようにプロパティを設定します。
リクエストのトラッキングを開始して完了する
HTTP リクエストのトラッキングを開始するには、リクエストを送信する直前に次のメソッドを呼び出します。
このメソッドを使用する前に、 ADEumInstrumentation
の initWithKey
メソッドのいずれかを使用してエージェントを初期化する必要があります。
@interface ADEumHTTPRequestTracker : NSObject
...
+ (ADEumHTTPRequestTracker *)requestTrackerWithURL:(NSURL *)url;
ここで、url
は要求されている URL です。このパラメータに nil
は使用できません。
HTTP リクエストのトラッキングを完了するには、応答またはエラーを受信した直後に、トラッカーオブジェクトに適切な properties を設定し、次のメソッドを呼び出してリクエストの結果をエージェントに返します。このメソッドを呼び出した後は、このオブジェクトを使用し続けることはできません。別のリクエストを追跡するには、requestTrackerWithURL
を再度呼び出します。
- (void)reportDone;
設定するプロパティ
エージェントにコールの結果を返すには、requestTrackerWithURL
オブジェクトに次のプロパティを設定する必要があります。
@property (copy, nonatomic) NSError *error;
応答の受信に失敗した場合を示します。リクエストが成功した場合は、nil
である必要があります。
@property (copy, nonatomic) NSNumber *statusCode;
応答の HTTP ステータスコード(受信した場合)を示します。
応答を受信した場合は、整数である必要があります。
エラーが発生し、応答が受信されなかった場合、これは
nil
にする必要があります。@property (copy, nonatomic) NSDictionary *allHeaderFields;
CODE
サーバの応答ヘッダーのキーと値を表すディクショナリを指定します。このディクショナリの形式は、NSURLRequest
の allHTTPHeadersFields
プロパティと同じである必要があります。ディクショナリエレメントは、キーと値のペアで構成されます。キーはヘッダーキー名で、値はヘッダー値です。
エラーが発生し、応答が受信されなかった場合、これは nil
にする必要があります。
例
次のようなリクエストスニペットがあるとします。
- (NSData *)sendRequest:(NSURL *) url error:(NSError **)error {
// implementation omitted
NSData *result = nil;
if (errorOccurred) {
*error = theError;
} else {
result = responseBody;
}
return result;
}
トラッカーを追加すると、次のようになります。
- (NSData *)sendRequest:(NSURL *)url error:(NSError **)error {
ADEumHTTPRequestTracker *tracker = [ADEumHTTPRequestTracker requestTrackerWithURL:url];
// implementation omitted
NSData *result = nil;
if (errorOccurred) {
*error = theError;
tracker.error = theError;
} else {
tracker.statusCode = theStatusCode;
tracker.allHeaderFields = theResponseHeaders;
result = responseBody;
}
[tracker reportDone];
return result;
}
Enable Server-Side Correlation
リクエストとサーバ側の処理の相関を有効にするには、サーバ側エージェントが検出できる発信リクエストに特定のヘッダーを追加し、応答でサーバ側エージェントから取得したヘッダーを返して、iOS エージェントが使用できるようにします。
これは、標準 HTTP ライブラリに対して自動的に実行されます。
@interface ADEumServerCorrelationHeaders : NSObject
+ (NSDictionary *)generate;
@end
次の作業が必要です。
バックエンドにリクエストを送信する前に、
generate
メソッドを呼び出し、生成されたヘッダーを設定します。上記の allHeaderFields プロパティを使用して、応答ヘッダーを返します。
Configure Agent to Use Custom HTTP Library
iOS エージェントは、ビーコンを送信するために HTTP を使用します。この目的で、エージェントがカスタム HTTP ライブラリを使用する構成を行うには、次の手順を実行します。
このプロトコルに準拠したクラスを実装します。
/** * Protocol for customizing the connection between the agent SDK and the collector. */ @protocol ADEumCollectorChannel <NSObject> /** * Sends a request synchronously and returns the response received, or an error. * * The semantics of this method are exactly equivalent to NSURLConnection's * sendSynchronousRequest:returningResponse:error: method. * * @param request The URL request to load. * @param response Out parameter for the URL response returned by the server. * @param error Out parameter used if an error occurs while processing the request. May be NULL. */ - (NSData *)sendSynchronousRequest:(NSURLRequest *)request returningResponse:(NSURLResponse **)response error:(NSError **)error; @end
OBJ-CADEumInstrumentation
を初期化する前にADEumAgentConfiguration
のcollectorChannel
プロパティを設定します。これはADEumCollectorChannel
を実装するクラスのインスタンスを渡します。詳細については、最新の iOS SDK ドキュメントを参照してください。@property (nonatomic, strong) id<ADEumCollectorChannel> collectorChannel;
OBJ-C
ネットワークリクエストへのカスタムデータの追加
次のメソッドを 1 つ(または複数)呼び出して属性を ADEumHTTPRequestTracker
に追加することで、カスタムデータをネットワークリクエストに追加できます。
Sample
- (NSData *)sendRequest:(NSURL *)url error:(NSError **)error {
ADEumHTTPRequestTracker *tracker = [ADEumHTTPRequestTracker requestTrackerWithURL:url];
// implementation omitted
NSData *result = nil;
if (errorOccurred) {
*error = theError;
tracker.error = theError;
} else {
tracker.statusCode = theStatusCode;
tracker.allHeaderFields = theResponseHeaders;
result = responseBody;
}
// Custom data can be added to this one request.
// Different types can be used.
// The data added will only appear for this network request and will not persist.
[tracker setUserData:@"trackerStringKey" value:@"Test String Value"];
[tracker setUserDataLong:@"trackerLongKey" value:66004024];
[tracker setUserDataBoolean:@"trackerBooleanKey" value:1];
[tracker setUserDataDouble:@"trackerDoubleKey" value:5905400.6];
[tracker setUserDataDate:@"trackerDateKey" value:[NSDate date]];
[tracker reportDone];
return result;
}
ネットワークリクエストの URL の変換
アプリケーションがネットワークリクエストを行う場合、機密情報が含まれている URL を EUM サーバに報告したくない場合があります。その場合は、ネットワークリクエスト URL を報告する前に変換するか、すべて無視します。
インポートを行うには以下を実行します。
- 特定の URL を変更または無視するネットワーク リクエスト コールバックを実装します。
- 初期化コードにネットワーク リクエスト コールバックを登録します。
ネットワーク要求のコールバックの実装
特定の URL を変更または無視するコールバックでは、次のようにプロトコルを実装します。コールバックメソッド networkRequestCallback
は同期されているため、関数からすばやく戻ることをお勧めします。
- (BOOL)networkRequestCallback:(ADEumHTTPRequestTracker *)networkRequest
URL の変換
通常 、networkRequestCallback
メソッドは次の手順に従って URL を変換する必要があります。
- 正規表現やパターンマッチングなどの手法を使用して、特定の URL を識別します。
ADEumHTTPRequestTracker
オブジェクトのurl
プロパティを変更します。(ADEumHTTPRequestTracker
オブジェクトのその他のプロパティの変更は無視されます。)url
プロパティに有効な URL を割り当てます。YES
(Objective-C)またはtrue
(Swift)を返します。
すべてのネットワークリクエストの URL を変換することもできるので、最初の手順はオプションです。
- (BOOL)networkRequestCallback:(ADEumHTTPRequestTracker *)networkRequest
{
NSString *maskURL = @"http://networkrequest-mask.com";
NSURL *url = [NSURL URLWithString:maskURL];
networkRequest.url = url;
return YES;
}
func networkRequestCallback(_ networkRequest: ADEumHTTPRequestTracker?) -> Bool {
let maskURL = "http://networkrequest-mask.com"
let url = URL(string: maskURL)
networkRequest?.url = url
return true
}
ただし、一般的には次の例に示すように、機密情報が含まれている URL を特定して変換する必要があります。
- (BOOL)networkRequestCallback:(ADEumHTTPRequestTracker *)networkRequest
{
NSString *urlString = networkRequest.url.absoluteString;
BOOL returnBeacon = YES;
NSString *maskURL = @"http://customer-account.com";
if (!([urlString rangeOfString:@"accountInfo"].location == NSNotFound)) {
networkRequest.url = [NSURL URLWithString:maskURL];
}
return returnBeacon;
}
func networkRequestCallback(_ networkRequest: ADEumHTTPRequestTracker?) -> Bool {
let urlString = networkRequest?.url.absoluteString
returnBeacon = true
let maskURL = "http://customer-account.com"
if !(Int((urlString as NSString?)?.range(of: "accountInfo").location ?? 0) == NSNotFound) {
networkRequest?.url = URL(string: maskURL)
}
return returnBeacon
}
URL の無視
networkRequestCallback
メソッドが false を返した場合、ビーコンはドロップされます。ビーコンを無視する一般的なプロセスは次のとおりです。
正規表現やパターンマッチングなどの手法を使用して、特定の URL を識別します。
false
を返します。
コールバック networkRequestCallback
が常に NO
(Objective-C)または false
(Swift)を返すようにすれば、理論的にはすべてのネットワークリクエストを無視できます。
- (BOOL)networkRequestCallback:(ADEumHTTPRequestTracker *)networkRequest
{
return NO;
}
func networkRequestCallback(_ networkRequest: ADEumHTTPRequestTracker?) -> Bool {
return false
}
ただし、一般的には次の例に示すように、モニタしないネットワークリクエストを識別し、NO
(Objective-C)または false
(Swift)を返して、ネットワークリクエストを無視します。
- (BOOL)networkRequestCallback:(ADEumHTTPRequestTracker *)networkRequest
{
NSString *urlString = networkRequest.url.absoluteString;
BOOL returnBeacon = YES;
if (!([urlString rangeOfString:@"avatar"].location == NSNotFound)) {
returnBeacon = NO;
}
return returnBeacon;
}
func networkRequestCallback(_ networkRequest: ADEumHTTPRequestTracker?) -> Bool {
let urlString = networkRequest?.url.absoluteString
var returnBeacon = true
if !(Int((urlString as NSString?)?.range(of: "avatar").location ?? 0) == NSNotFound) {
returnBeacon = false
}
return returnBeacon
}
コールバックの登録
コールバックを実装した後、次に示すようにプロトコルメソッドを実装するオブジェクトを初期化コードに登録します。iOS エージェントがネットワーク リクエスト ビーコンを作成する準備ができたら、最初に ADEumHTTPRequestTracker
オブジェクトを使用してコールバックを呼び出します。
ADEumAgentConfiguration *config = [[ADEumAgentConfiguration alloc] initWithAppKey: <#EUM_APP_KEY#>];
config.networkRequestCallback = self;
[ADEumInstrumentation initWithConfiguration:config];
let config = ADEumAgentConfiguration(appKey: <#EUM_APP_KEY#>)
config.networkRequestCallback = self
ADEumInstrumentation.initWith(config)
ロギングの有効化とロギングレベルの設定
ロギングレベルを有効にして設定するには、メソッド loggingLevel
を使用します。ロギングは、次のいずれかのレベルに設定できます。
ADEumLoggingLevelOff
ADEumLoggingLevelAll
ADEumLoggingLevelVerbose
ADEumLoggingLevelDebug
ADEumLoggingLevelInfo
ADEumLoggingLevelWarn
ADEumLoggingLevelError
Verbose、All、Debug レベルのロギングを使用するのは、トラブルシューティングのときだけであり、実稼働では必ずオフにしてください。
Examples:
-(BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
// appKey should be assigned your EUM app key
ADEumAgentConfiguration *config = [[ADEumAgentConfiguration alloc] initWithAppKey: <#EUM_APP_KEY#>];
config.loggingLevel = ADEumLoggingLevelAll;
[ADEumInstrumentation initWithConfiguration:config];
...
}
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
{
// appKey should be assigned your EUM app key
let config = ADEumAgentConfiguration(appKey: <#EUM_APP_KEY#>)
config.loggingLevel = .all
ADEumInstrumentation.initWithConfiguration(config)
...
return true
}
iOS SDK のドキュメント
最新の iOS SDK ドキュメント、または以下に記載されている以前のバージョンを参照してください。
- https://sdkdocs.appdynamics.com/ios-sdk/21.8/html/
- https://sdkdocs.appdynamics.com/ios-sdk/21.6/html/
- https://sdkdocs.appdynamics.com/ios-sdk/21.5/html/
- https://sdkdocs.appdynamics.com/ios-sdk/21.2/html/
- https://sdkdocs.appdynamics.com/ios-sdk/20.12/html/
- https://sdkdocs.appdynamics.com/ios-sdk/20.10/html/
- https://sdkdocs.appdynamics.com/ios-sdk/20.8/html
- https://sdkdocs.appdynamics.com/ios-sdk/20.7/html
- https://sdkdocs.appdynamics.com/ios-sdk/2020.3/html