モバイル iOS SDK を使用して iOS アプリケーションをインストゥルメント化すると、SDK が公開する API を使用して、コントローラ UI に表示されるアプリケーションのデータをカスタマイズすることもできます。

エージェントは情報を報告する前にローカルバッファにイベントに関するデータを保存するため、慎重に API を使用することをお勧めします。

データの追加タイプの収集

ADEUMInstrumentation クラスで使用可能なメソッドを使用して、6 つの追加タイプのデータを収集できます。

データのタイプ説明仕様データが表示される場所
情報ポイントメソッドが呼び出される頻度と実行される時間。
  • データは数値
  • 名前には、英数字
    とスペースを使用
カスタムタイマーコード内の任意のイベントシーケンスが、
複数のメソッドにまたがる場合でも、時間を計測。
  • データは数値
  • メトリック名には、英数字
    とスペースを使用
カスタムメトリック収集する整数ベースのデータ。
  • データは数値
  • メトリック名には、
    英数字とスペースを使用
ユーザデータ有用と思われる任意の文字列キーと値のペア
  • データは任意のタイプ
  • メトリック名には制限なし
トピックパス(パンくずリスト)クラッシュのコンテキスト。
  • データは任意のデータ型
  • メトリック名には制限なし
ユーザの操作ユーザがボタンを押したとき、リストをクリックしたとき、およびテキストを選択したときにキャプチャ。
  • データは任意のデータ型
  • メトリック名には制限なし

追加のデータ型を設定した場合、モバイルエージェントはモバイルビーコンでそのデータをパッケージ化します。通常、ビーコンはインストゥルメント化されたアプリケーションが HTTP リクエストを送信したとき、またはクラッシュ後にアプリケーションが再起動されたときに送信されますが、カスタムデータが収集され、これらのイベントのいずれも 5 分以上発生していない場合は、カスタムデータはその時点で送信されます。

情報ポイント

情報ポイントを使用すると、独自のコードがどのように実行されているかを追跡できます。次のように beginCallendCall を使用して、メソッドが呼び出される頻度と実行にかかる時間を確認できます。

- (void)myMethod
    {
        id tracker = [ADEumInstrumentation beginCall:self selector:_cmd];

        // Implementation of method here ...

        [ADEumInstrumentation endCall:tracker];
    }
CODE
func myMethod() {
    let tracker = ADEumInstrumentation.beginCall(self, selector: #function)
    // Implementation of method here ...
    ADEumInstrumentation.endCall(tracker)
}
RUBY

例外がスローされた場合も報告されます。この情報は、コントローラ UI の [Custom Data] ビューに表示されます。  

カスタムタイマー

カスタムタイマーでは、startTimerstopTimer を使用して、複数のメソッドにまたがる場合でも、コード内の任意のイベントシーケンスの時間を測定できます。たとえば、ユーザが画面を表示する際にかかった時間を追跡する場合、インストゥルメンテーションは次のようになります。

- (void)viewDidAppear:(BOOL)animated {
      [super viewDidAppear:animated];
      [ADEumInstrumentation startTimerWithName:@"View Lifetime"];
  }
- (void)viewDidDisappear:(BOOL)animated {
      [super viewDidDisappear:animated];
      [ADEumInstrumentation stopTimerWithName:@"View Lifetime"];
  }
CODE
func viewDidAppear(_ animated: Bool) {
    super.viewDidAppear(animated)
    ADEumInstrumentation.startTimer(withName: "View Lifetime")
}
func viewDidDisappear(_ animated: Bool) {
    super.viewDidDisappear(animated)
    ADEumInstrumentation.stopTimer(withName: "View Lifetime")
}
RUBY


この情報は、コントローラ UI の [Custom Data] ビューに表示されます。

同じ名前値を使用して startTimerWithName を再度呼び出すと、名前付きタイマーがリセットされます。

Custom Metrics

任意の整数ベースのデータをエージェントに渡すことができます。report.MetricWithName コールの最初のパラメータは、メトリックをコントローラ UI に表示する場合の名前です。メトリック名には、英数字とスペースのみを使用します。不正な文字は、ASCII 16 進値に置き換えられます。

たとえば、「My custom metric」というメトリックを報告する場合は、次のようになります。

[ADEumInstrumentation reportMetricWithName:@"My custom metric" value:<#VALUE HERE#>];
CODE

この情報は、コントローラ UI の [Custom Data] ビューに表示されます。

ユーザ データ

有用と思われる任意の文字列キーと値のペアを設定できます。setUserData コールの最初のパラメータは、使用するキーです。これはアプリケーション全体で一意である必要があります。2 番目パラメータは、キーに割り当てる値です。

例: 

- (void) onUserLoggedIn:(NSString *)userid { 
    [ADEumInstrumentation setUserData:@"User ID" value:userid];
    ...
  }
CODE
func onUserLogged(in userid: String?) {
    ADEumInstrumentation.setUserData("User ID", value: userid)
}
RUBY

この情報は、[Network Request Analyze] で確認でき、取得可能なクラッシュスナップショットに追加されます。キーと値はそれぞれ 2048 文字に制限されています。 

また、次のメソッドを使用して、他のデータ型(Long、Boolean、Double、Date)の値を含むユーザデータを設定することもできます。

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

トピックパスを使用すると、ユーザエクスペリエンスのコンテキストでクラッシュの場所を特定できます。問題が発生したときに、トピックパスを設定します。その後のある時点でアプリケーションがクラッシュした場合、トピックパスはクラッシュレポートとともに表示されます。

トピックパスを残すには、次の 2 つの方法があります。

次のメソッドを使用すると、トピックパスがクラッシュレポートのみで報告されます。

+ (void)leaveBreadcrumb:(NSString *)breadcrumb
CODE
次のメソッドを使用すると、トピックパスが報告される場所を微調整(クラッシュレポートのみ、またはクラッシュレポートとセッションを選択)できます。
+ (void)leaveBreadcrumb:(NSString *)breadcrumb mode:(ADEumBreadcrumbVisibility)mode
CODE

ここで、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];
CPP

また、1 つのタイプのユーザインタラクションのみをキャプチャするように iOS エージェントを構成することもできます。

ADEumAgentConfiguration 
*config = [[ADEumAgentConfiguration alloc] initWithAppKey: <#EUM_APP_KEY#>];
config.interactionCaptureMode = ADEumInteractionCaptureModeButtonPressed;
[ADEumInstrumentation initWithConfiguration:config];
CPP

スクリーンショットの設定および作成

モバイルスクリーンショットはデフォルトで有効になっています。スクリーンショットを自動的に取得するようにコントローラ UI を構成するか、次に示すように、iOS SDK を使用して手動でスクリーンショットを取得できます。

[ADEumInstrumentation takeScreenshot];
CPP
ADEumInstrumentation.takeScreenshot()
RUBY

スクリーンショットの無効化

スクリーンショットは、コントローラ UI または iOS SDK を使用して無効にできます。iOS SDK を使用してスクリーンショットを無効にするには、次に示すように ADEumAgentConfiguration オブジェクトのプロパティ screenshotsEnabledNO(Objective-C の場合)または false(Swift の場合)に設定します。

ADEumAgentConfiguration 
*config = [[ADEumAgentConfiguration alloc] initWithAppKey: <#EUM_APP_KEY#>];
config.screenshotsEnabled = NO;
[ADEumInstrumentation initWithConfiguration:config];
CPP
let config = ADEumAgentConfiguration(appKey: <#EUM_APP_KEY#>);
config.screenshotsEnabled = false;
ADEumInstrumentation.initWith(config);
RUBY

スクリーンショットのブロックとブロック解除

iOS SDK を使用して、コードブロックの実行中にスクリーンショットが実行されないようにすることもできます。これにより、スクリーンショットのブロックを解除するまで、スクリーンショットの作成が一時的にブロックされます。これにより、ユーザがログインやアカウント画面などで個人データを入力する状況でのスクリーンショットの作成を停止できます。

ADEumInstrumentation クラスでは、スクリーンショットをブロックおよびブロック解除するためのメソッド、blockScreenshotsunblockScreenshots が使用できます。スクリーンショットが 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];
    }
}
...
CPP
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()
    }
}
...
CPP

コレクタへのユーザーデータの送信を停止する場合のエージェントの無効化

エージェントの初期化中および実行中に、エージェントを無効にしてコレクタへのすべてのデータの送信を停止できます。たとえば、プライバシー上の理由でユーザがモニタリングをオプトアウトするオプションがアプリにある場合は、エージェントを無効にできます。

shutdownAgent

shutdownAgent のコールは、コレクタへの発信データがすべてのデータをコレクタに送信することを停止します。 

[ADEumInstrumentation shutdownAgent];
CPP
ADEumInstrumentation.shutdownAgent()
RUBY
  • このコールは、エージェントからのトラフィックのみを停止します。
  • エージェントが初期化されると、コールは削除できず、ライセンスが消費されます。
  • この状態をデバイスで永続的にする場合は、UserDefaults にコードを追加して状態を保存し、そのフラグを使用してコード内のエージェントを条件付きで初期化します。

restartAgent

エージェントを再度有効にして shutdownAgent を無効にする場合は、restartAgent. を使用します。このコールは、同様にリモートでエージェントをシャットダウンできるサーバー側のコールにも対応します。 

[ADEumInstrumentation restartAgent];
CPP
ADEumInstrumentation.restartAgent();
RUBY
  • コールは、アプリケーションの実行中にのみ有効です。
  • エージェントがリモートで無効になっている場合、コールは無視されます。 
  • コールがメモリから削除され、アプリケーションが再起動されるか、デバイスが再起動されると、エージェントは通常どおり初期化されます。 

クラッシュ レポート コールバックの追加

モバイル RUM を使用している場合、コードの他の部分(Google Analytics など)がモバイル RUM が収集するクラッシュレポート情報を使用できるようにすることがあります。サマリークラッシュ情報を渡せるようにするには、クラッシュレポートのランタイムコールバックを設定します。iOS エージェントがクラッシュを検出して報告するときにコールバックを取得するには、コードに次のプロトコルを実装する必要があります。

@protocol ADEumCrashReportCallback <NSObject>
  
- (void)onCrashesReported:(NSArray<ADEumCrashReportSummary 
*> 
*)crashReportSummaries;
  
@end
CODE

このコールバックはアプリケーションの 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
CODE

Google Analytics などの別の分析ツールに情報を送信する場合は、次の 5 つのプロパティすべてを含めることをお勧めします。

  • exceptionNameexceptionReason はオプションであり、クラッシュの原因をすばやく特定するのに役立ちます。これらは、例外レポートランタイム(Objective-C など)内でクラッシュ原因が発生した場合にのみ表示されます。
  • signalNamesignalCode は、クラッシュをすばやく識別するのに役立ちます。これらはシステムから取得するものであり、ランタイムとは独立しています。
  • その他の情報については、 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);
    }
}
CODE

エージェントの構成時に、ADEumCrashReportCallback プロトコルを実装するオブジェクトを設定します。

ADEumAgentConfiguration *config = [ADEumAgentConfiguration new];
config.crashReportCallback = myCrashReportCallback;
CODE

前回の実行からクラッシュの検出と収集が行われた場合、メイン/UI スレッドでコールバックが呼び出されます。詳細については、最新の iOS SDK ドキュメントを参照してください。

エラーと例外のレポート

ADEumInstrumentation クラスの reportError メソッドを使用して例外を報告できます。報告された例外は、セッション詳細に表示されます。

このメソッドには、次の 2 つの署名があります。

Objective-C 関数の署名説明
(void)reportError:(NSError *)error withSeverity (ADEumErrorSeverityLevel)severity;

この署名を使用してエラーを報告し、問題の重大度レベルを設定し、スタックトレースを送信します。

この関数の署名は、デフォルトでスタックトレースを送信します。スタックトレースを送信しない場合は、次の関数の署名を追加の引数 andStackTrace とともに使用し、その値を NO に設定します。

(void)reportError:(NSError *)error withSeverity:(ADEumErrorSeverityLevel)severity andStackTrace:(BOOL)stacktrace;


この署名を使用してエラーを報告し、問題の重大度レベルを設定し、スタックトレースを含めるかどうかを明示的に指定します。

stacktraceYES に設定して、報告されるエラーにスタックトレースを含めると、[Code Issues Details] ダイアログにスタックトレースを表示できます。

スタックトレースなしでエラーを報告するには、stacktraceNO. に設定します。

重要度レベル

問題に次の重大度レベルのいずれかを設定することもできます。重大度レベルを使用すると、[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 {
   ...
}
CPP
var err: Error? = nil
try? FileManager.default.contentsOfDirectory(atPath: "pathToFile")
if err != nil {
    ADEumInstrumentation.reportError(err, withSeverity: ADEumErrorSeverityLevelCritical, andStackTrace: false)
} else {
  ...
}
RUBY

次のようにカスタムエラーを作成して報告することもできます。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];
CPP
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)
RUBY

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];
CPP
let config = ADEumAgentConfiguration(appKey: <#EUM_APP_KEY#>);
// Enable ANR detection
config.anrDetectionEnabled = true;
ADEumInstrumentation.initWith(config); 
RUBY

ANR を使用したスタックトレースのレポート

ANR 検出を有効にすることに加えて、プロパティ anrStackTraceEnabledYES(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];
CPP
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)
RUBY

 

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

クラッシュレポートはデフォルトで有効になっていますが、インストゥルメンテーション構成を使用して手動でクラッシュレポートを無効にできます。他のクラッシュレポートツールを使用している場合、競合を最小限に抑え、クラッシュレポートの結果を最適化するために、クラッシュレポートを無効にする場合があります。 

次のコード例に示すように、 crashReportingEnabled プロパティを使用してインストゥルメンテーションを構成することにより、クラッシュレポートを無効にできます。

ADEumAgentConfiguration *config = [[ADEumAgentConfiguration alloc] initWithAppKey:appKey];
config.crashReportingEnabled = No
[ADEumInstrumentation initWithConfiguration:config];
CPP
let config = ADEumAgentConfiguration(appKey: <#EUM_APP_KEY#>);
config.crashReportingEnabled = false;
ADEumInstrumentation.initWith(config); 
RUBY

ハイブリッド アプリケーション サポートの構成

デフォルトでは、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];
CPP

JavaScript エージェントのインジェクションはデフォルトで有効になっています。Ajax コールの収集とレポートも有効にするには、次のようにします。

ADEumAgentConfiguration 
*adeumAgentConfig = [[ADEumAgentConfiguration alloc] initWithAppKey: <#EUM_APP_KEY#>];
// Enable the collection and reporting of Ajax calls
adeumAgentConfig.jsAgentAjaxEnabled  = YES;
[ADEumInstrumentation initWithConfiguration:adeumAgentConfig];
CPP

ハイブリッド アプリケーション サポートの静的構成

次の場合には、静的構成を使用する必要があります。

  • 強制的に WKWebView や Ajax コールをインストゥルメント化する(ランタイム構成をオーバーライドする)
  • ハイブリッドサポートを無効にし、ランタイム構成をオーバーライドする
  • URL を自己ホストされた JavaScript 拡張ファイルに設定する

次の表は、info.plist ファイルでサポートされているプロパティとデフォルト値です。

プロパティデフォルト値説明

serverJsAgentEnabled

true

クライアントがこのフラグに false を受け取ると、JavaScript エージェントは無効になります。したがって、WKWebView と Ajax リクエストはモニターされません。

インジェクションは、新しい WKWebView の作成時に発生します。このため、このフラグが false に設定されているときに WKWebView が作成された場合、その特定の WKWebView は、 その後フラグが true に設定されてもインストゥルメント化されません。

ForceWebviewInstrumentationfalsetrue に設定すると、iOS エージェントはランタイム構成に関係なく、JavaScript エージェントを WKWebView に挿入します。
ForceAjaxInstrumentationtruetrue に設定すると、ランタイム構成に関係なく、Ajax オペレーションは常に収集および報告されます。
ADRUMExtUrlHttp

http://cdn.appdynamics.com

JavaScript エージェントは、基本 JavaScript エージェントと JavaScript エージェントの拡張という 2 つのコンポーネントで構成されています。基本 JavaScript エージェントは、モバイルエージェントのバイナリに組み込まれ、上記のルールに従って挿入されます。

初期化後、JavaScript エージェントは、これらのプロパティによって指定された URL から JavaScript エージェント拡張を取得します。

ADRUMExtUrlHttpshttps://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>
CPP

プログラムによるセッションの制御

デフォルトでは、ユーザが非アクティブになってからモバイルセッションが終了します。たとえば、ユーザがアプリケーションを開くと、セッションは開始され、ユーザが設定した期間にアプリケーションを使用しなくなった後にのみ終了します。ユーザがアプリケーションの再使用を開始すると、新しいセッションが開始されます。 

ただし、セッションの期間を定義するのに非アクティブな期間を設定する代わりに、次の API を使用して、セッションの開始と終了をプログラムで制御できます。

 - (void)startNextSession
CPP

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

セッションフレームの開始と終了

SessionFrame API を使用して、セッションアクティビティに表示されるセッションフレームを作成できます。セッションフレームは、セッション中にユーザが実行している内容のコンテキストを提供します。この API を使用すると、ユーザ画面の命名方法が向上し、ビジネスコンテキスト内のユーザフローを記録できます。 

使用例

次に、SessionFrame API の一般的な使用例を示します。

  • 1 つの ViewController では複数の関数が実行されていて、個々の関数をより詳細に追跡する必要があります。
  • ユーザフローは、複数の ViewController またはユーザの操作におよびます。たとえば、API を使用してセッションフレーム「Login」、「Product Selection」、および「Purchase」を作成して、ユーザが購入のためにフローを記録することができます。
  • ユーザの操作に基づいて動的情報をキャプチャし、オーダー ID などのセッションフレームに名前を付けることができます。

SessionFrame API

次の表に、セッションフレームで使用できる3つの方法を示します。つまり、startSessionFrame を使用してセッションフレームを開始してから、返された ADeumSessionFrame オブジェクトを使用してセッションフレームの名前を変更し、終了します。 

クラスメソッド[説明(Description)]

ADEumInstrumentation

+ (ADEumSessionFrame *)startSessionFrame:(NSString *)name

セッションフレームを開始して名前を付けるには、これを使用します。セッションフレームに名前を付けると、[Sessions Dialog] でフレームを簡単に識別して追跡できます。

ADEumSessionFrame

- (void)updateName:(NSString *)name

セッションフレームの名前を変更します。ADEumSessionFrame オブジェクト(startSessionFrame から返される)からこのメソッドを呼び出すことができます。

ADEumSessionFrame

- (void)end

セッションフレームを終了します。startSessionFrame から返された ADEumSessionFrame オブジェクトからこのメソッドを呼び出すことができます。

クラスメソッド[説明(Description)]

ADEumInstrumentation

startSessionFrame(_ name: String?) -> ADEumSessionFrameセッションフレームを開始して名前を付けるには、これを使用します。セッションフレームをネーミングすると、のフレームを簡単に識別して追跡できます。Sessions Dialog.
ADEumSessionFrame
updateName(_ name: String?)セッションフレームの名前を変更します。startSessionFrame から返された ADEumSessionFrame オブジェクトからこのメソッドを呼び出すことができます。
ADEumSessionFrameend()セッションフレームを終了します。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;
}
CPP
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
}
RUBY

カスタムアプリケーション名のエージェントの構成

デフォルトでは、AppDynamics はアプリケーションの名前を自動的に検出します。アプリケーション名は、バンドル ID の文字列形式です。したがって、バンドル ID が com.example.appdynamics.HelloWorld の場合、アプリケーション名は「com.example.appdynamics.HelloWorld」となります。 

ただし、原則としてさまざまな地域のアプリケーションストアに異なるバンドル ID を付けたアプリケーションバイナリを展開することがあります。バンドル ID が異なる場合でも、1 つのアプリケーションに属するすべてのデータがまとめて収集され表示されるようにするには、アプリケーションにカスタム名を指定して共通名を設定します。これを行うには、ADEumInstrumentation の設定に使用する ADEumAgentConfiguration インスタンスでアプリケーション名プロパティを設定します。詳細については、最新の iOS SDK ドキュメントを参照してください。

@property (nonatomic, strong) NSString *applicationName; 
CODE

一部の HTTP リクエストを無視するためのエージェントの構成

NSURL を使用した HTTP リクエストは、アプリケーションの内部で使用され、実際のネットワークリクエストを表すものではない場合があります。これらのリクエストに基づいて作成されたメトリックは、一般的に問題の追跡には役立たないため、そのデータが収集されないようにする場合があります。特定の NSURL リクエストを無視するには、ADEumInstrumentation の設定に使用する ADEumAgentConfiguration インスタンスに除外 URL パターンプロパティを設定します。できるだけ簡潔な正規表現を使用します。詳細については、最新の iOS SDK ドキュメントを参照してください。

@property (nonatomic, strong) NSSet * excludedUrlPatterns;
CPP

カスタム HTTP ライブラリでのエージェントの使用

iOS エージェントは、 NSURLConnection または NSURLSession クラスのいずれかによって基盤となる実装が処理されたときに、自動的にネットワークリクエストを検出します。これにより、ほとんどの iOS ネットワークリクエストが対象になります。ただし、モバイルアプリケーションでは、カスタム HTTP ライブラリが使用される場合があります。  

リクエストトラッキングの追加

リクエストトラッキングを手動で追加するには、リクエストの開始と終了のタイミングをエージェントに通知します。また、応答のステータスをエージェントに通知するようにプロパティを設定します。

リクエストのトラッキングを開始して完了する

HTTP リクエストのトラッキングを開始するには、リクエストを送信する直前に次のメソッドを呼び出します。

このメソッドを使用する前に、 ADEumInstrumentationinitWithKey メソッドのいずれかを使用してエージェントを初期化する必要があります。

@interface ADEumHTTPRequestTracker : NSObject
... 
+ (ADEumHTTPRequestTracker *)requestTrackerWithURL:(NSURL *)url;
CPP

ここで、url は要求されている URL です。このパラメータに nil は使用できません。

HTTP リクエストのトラッキングを完了するには、応答またはエラーを受信した直後に、トラッカーオブジェクトに適切な properties を設定し、次のメソッドを呼び出してリクエストの結果をエージェントに返します。このメソッドを呼び出した後は、このオブジェクトを使用し続けることはできません。別のリクエストを追跡するには、requestTrackerWithURL を再度呼び出します。

- (void)reportDone;
CPP


設定するプロパティ

エージェントにコールの結果を返すには、requestTrackerWithURL オブジェクトに次のプロパティを設定する必要があります。

@property (copy, nonatomic) NSError *error;
CPP

応答の受信に失敗した場合を示します。リクエストが成功した場合は、nil である必要があります。

@property (copy, nonatomic) NSNumber *statusCode;
CPP


応答の HTTP ステータスコード(受信した場合)を示します。
  • 応答を受信した場合は、整数である必要があります。

  • エラーが発生し、応答が受信されなかった場合、これは nil にする必要があります。

    @property (copy, nonatomic) NSDictionary *allHeaderFields;
    CPP

サーバの応答ヘッダーのキーと値を表すディクショナリを指定します。このディクショナリの形式は、NSURLRequestallHTTPHeadersFields プロパティと同じである必要があります。ディクショナリエレメントは、キーと値のペアで構成されます。キーはヘッダーキー名で、値はヘッダー値です。

エラーが発生し、応答が受信されなかった場合、これは nil にする必要があります。  

例:

次のようなリクエストスニペットがあるとします。

- (NSData *)sendRequest:(NSURL *) url error:(NSError **)error { 
      // implementation omitted 
      NSData *result = nil; 
      if (errorOccurred) { 
          *error = theError; 
      } else { 
          result = responseBody; 
      } 
      return result; 
  }
CPP

トラッカーを追加すると、次のようになります。

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

Enable Server-Side Correlation

リクエストとサーバ側の処理の相関を有効にするには、サーバ側エージェントが検出できる発信リクエストに特定のヘッダーを追加し、応答でサーバ側エージェントから取得したヘッダーを返して、iOS エージェントが使用できるようにします。


これは、標準 HTTP ライブラリに対して自動的に実行されます。

@interface ADEumServerCorrelationHeaders : NSObject 
+ (NSDictionary *)generate; 
@end
CPP

次の作業が必要です。

  1. バックエンドにリクエストを送信する前に、generate メソッドを呼び出し、生成されたヘッダーを設定します。

  2. 上記の allHeaderFields プロパティを使用して、応答ヘッダーを返します。

Configure Agent to Use Custom HTTP Library

iOS エージェントは、ビーコンを送信するために HTTP を使用します。この目的で、エージェントがカスタム HTTP ライブラリを使用する構成を行うには、次の手順を実行します。

  1. このプロトコルに準拠したクラスを実装します。

    /
    *
    * 
    
    * 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
    CPP
  2. ADEumInstrumentation を初期化する前に ADEumAgentConfigurationcollectorChannel プロパティを設定します。これは ADEumCollectorChannel を実装するクラスのインスタンスを渡します。詳細については、最新の iOS SDK ドキュメントを参照してください。

    @property (nonatomic, strong) id<ADEumCollectorChannel> collectorChannel;
    CPP

ネットワークリクエストの URL の変換

アプリケーションがネットワークリクエストを行う場合、機密情報が含まれている URL を EUM サーバーに報告したくない場合があります。その場合は、ネットワークリクエスト URL を報告する前に変換するか、すべて無視します。 

インポートを行うには以下を実行します。

  1. 特定の URL を変更または無視するネットワーク リクエスト コールバックを実装します。 
  2. 初期化コードにネットワーク リクエスト コールバックを登録します。

ネットワーク要求のコールバックの実装

特定の URL を変更または無視するコールバックでは、次のようにプロトコルを実装します。コールバックメソッド networkRequestCallback は同期的に実行されるので、関数からすぐに戻ることをお勧めします。

- (BOOL)networkRequestCallback:(ADEumHTTPRequestTracker *)networkRequest
CPP

URL の変換

通常 、networkRequestCallback メソッドは次の手順に従って URL を変換する必要があります。

  1. 正規表現やパターンマッチングなどの手法を使用して、特定の URL を識別します。
  2. ADEumHTTPRequestTracker オブジェクトの url プロパティを変更します。(ADEumHTTPRequestTracker オブジェクトのその他のプロパティの変更は無視されます。)
  3. url プロパティに有効な URL を割り当てます。 
  4. 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;
} 
CPP
func networkRequestCallback(_ networkRequest: ADEumHTTPRequestTracker?) -&gt; Bool {
    let maskURL = "http://networkrequest-mask.com"
    let url = URL(string: maskURL)
    networkRequest?.url = url
    return true
}
RUBY

ただし、一般的には次の例に示すように、機密情報が含まれている 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;
}
CPP
func networkRequestCallback(_ networkRequest: ADEumHTTPRequestTracker?) -&gt; 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
}
RUBY

URL の無視

networkRequestCallback メソッドが false を返した場合、ビーコンはドロップされます。ビーコンを無視する一般的なプロセスは次のとおりです。

  1. 正規表現やパターンマッチングなどの手法を使用して、特定の URL を識別します。

  2. false を返します。

コールバック networkRequestCallback が常に NO(Objective-C)または false(Swift)を返すようにすれば、理論的にはすべてのネットワークリクエストを無視できます。

- (BOOL)networkRequestCallback:(ADEumHTTPRequestTracker *)networkRequest
{
    return NO;
}
CPP
func networkRequestCallback(_ networkRequest: ADEumHTTPRequestTracker?) -&gt; Bool {
    return false
}
RUBY

ただし、一般的には次の例に示すように、モニタしないネットワークリクエストを識別し、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;
}
CPP
func networkRequestCallback(_ networkRequest: ADEumHTTPRequestTracker?) -&gt; Bool {
    let urlString = networkRequest?.url.absoluteString
    var returnBeacon = true
    if !(Int((urlString as NSString?)?.range(of: "avatar").location ?? 0) == NSNotFound) {
        returnBeacon = false
    }
    return returnBeacon
}
RUBY

コールバックの登録

コールバックを実装した後、次に示すようにプロトコルメソッドを実装するオブジェクトを初期化コードに登録します。iOS エージェントがネットワーク リクエスト ビーコンを作成する準備ができたら、最初に ADEumHTTPRequestTracker オブジェクトを使用してコールバックを呼び出します。

ADEumAgentConfiguration 
*config = [[ADEumAgentConfiguration alloc] initWithAppKey: <#EUM_APP_KEY#>];
config.networkRequestCallback = self;
[ADEumInstrumentation initWithConfiguration:config];
CPP
let config = ADEumAgentConfiguration(appKey: <#EUM_APP_KEY#>)
config.networkRequestCallback = self
ADEumInstrumentation.initWith(config)
RUBY

ロギングの有効化とロギングレベルの設定

ロギングレベルを有効にして設定するには、メソッド 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];
    ...
}
CPP
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
}
RUBY



iOS SDK のドキュメント

最新の iOS SDK ドキュメント、または以下に記載されている以前のバージョンを参照してください。

4.5.6 以降、iOS エージェントは、コントローラと他の AppDynamics プラットフォーム コンポーネントとは異なるバージョン番号になりました。すべての iOS エージェント機能を完全にサポートするために必要なコントローラおよび EUM サーバーの最小バージョンについては、「モバイル エージェント バージョンおよび展開サポートマトリックス」を参照してください。