IoT Java SDK は、ゲートウェイ、POS、車のインフォテインメント センターなどのエッジデバイスで実行されている IoT Java アプリケーションに含めることができます。ここでは、Java SDK をインストールし、IoT アプリケーションをインストゥルメント化する方法について説明します。

EUM アプリケーションキーを取得し、IoT C/C++ アプリケーションをインストゥルメント化するには、次の手順を実行します。

この Java SDK は、よりローエンドデバイス向けに特別に設計された非常に軽量なライブラリである点で、AppDynamics Java エージェントとは異なります。また、イベント情報を拡張でき、インストゥルメンテーション コードを設定および制御できるように多くの柔軟性が組み込まれています。

要件の確認

開始する前に、次の要件を満たしていることを確認します。

  • デバイスが次のいずれかのバージョンの Java ランタイムを実行していること。

    • Java SE 7

    • Java SE Embedded 7 

    • Java SE 8

    • Java SE Embedded 8 

  • EUM サーバにビーコンを送信する HTTPS インターフェイス
  • EUM アプリケーションキー

IoT Java SDK の取得

Java SDK は、GitHub から IoT Java SDK を複製またはダウンロードすることによって取得できます。「Build the SDK」に記載されている手順に従って、IoT Java SDK をビルドします。

IntelliJ IDE を使用している場合は、「Working with module dependencies」に記載されている手順に従ってファイル lib/appd-iot-sdk.jar をプロジェクトに追加します。IntelliJ プロジェクトの [External Projects] の下に JAR ファイルが表示されていることを確認します。

IoT Java SDK のアップグレード

GitHub から IoT Java SDK のクローンのルートディレクトリで、次のようにします。

  • 次のリポジトリを更新します。$ git pull origin master
  • Build the SDK」に記載されている手順に従って、IoT Java SDK を再構築します。

Gradle 構成への SDK 依存関係の追加

build.gradle ファイルに以下を追加します。

dependencies {
   runtime group: 'org.slf4j', name: 'slf4j-api', version: '1.7.25'
   runtime group: 'com.google.guava', name:'guava', version:'18.0'
   runtime group: 'com.google.code.gson', name: 'gson', version: '2.8.0'
 }
TEXT

インストゥルメンテーション コードの追加

IoT SDK のインポート

アプリケーションファイルで、Java IoT SDK を含む import ステートメントを追加します。

import com.appdynamics.iot.Instrumentation;
JAVA

IoT Java エージェントの構成

EUM アプリケーションキーと URL を EUM コレクタに提供することによってインストゥルメンテーションを構成します。EUM コレクタ URL が指定されていない場合は、デフォルトの SaaS コレクタ URL が使用されます。

各地域の EUM コレクタ URL については、「Cisco AppDynamics SaaS Domains and IP Ranges」を参照してください。EUM コレクタ URL が指定されていない場合は、デフォルトの SaaS コレクタ URL が使用されます。

import com.appdynamics.iot.AgentConfiguration;
AgentConfiguration.Builder agentConfigBuilder = AgentConfiguration.builder();
AgentConfiguration agentConfig = agentConfigBuilder
        .withAppKey(<EUM_APP_KEY>)
        .build();
JAVA

デバイス情報の設定

デバイスの名前と ID を設定する必要があります。名前は、「EV Model 3」や「Thermostat Model Star7」など、デバイスのタイプとモデルを識別する短い文字列で構成されている必要があります。デバイス ID は、UUID、車の VIN 番号、またはデバイスの MAC アドレスなど、デバイスの一意の識別子である必要があります。

次のコード例では、デバイス ID をランダム UUID に、名前を「Smart Shelf」に設定しています。 

import java.util.UUID;
import com.appdynamics.iot.DeviceInfo;
...
DeviceInfo.Builder deviceInfoBuilder = DeviceInfo.builder("Smart Shelf P1", UUID.randomUUID().toString());
DeviceInfo deviceInfo = deviceInfoBuilder.withDeviceName("Smart Shelf").build();
JAVA

バージョン情報の設定

次に示すように、ファームウェア、ハードウェア、OS、およびソフトウェアのバージョンを設定できます。

import com.appdynamics.iot.VersionInfo;
...
VersionInfo.Builder versionInfoBuilder = VersionInfo.builder();
VersionInfo versionInfo = versionInfoBuilder
 .withFirmwareVersion("2.3.4")
 .withHardwareVersion("1.6.7")
 .withOsVersion("8.9.9")
 .withSoftwareVersion("3.1.1").build();
JAVA

エージェントの初期化

エージェントを初期化するには、AgentConfiguration オブジェクト、DeviceInfo オブジェクト、および VersionInfo オブジェクトを start メソッドに渡します。

Instrumentation.start(agentConfig, deviceInfo, versionInfo);
JAVA

アプリケーションの構築と実行

お気に入りの Java IDE または CLI 環境を使用し、アプリケーションを構築して実行します。AppDynamics IoT Java SDK は、ビルドおよびランタイムのクラスパスにある必要があることに注意してください。

クラスパスにライブラリを追加する手順については、次を参照してください。

アプリケーションを構築して実行する手順については、次を参照してください。

イベントの追加と送信

以下のセクションでは、サポートされているイベント(カスタム、ネットワークリクエスト、エラー)を作成して送信する方法について説明します。

基本的なカスタムイベントの作成

カスタムイベントを使用すると、パフォーマンス、デバイス、またはビジネスロジックデータを報告できます。これは、使用できる最も一般的で設定可能かつ柔軟性の高いデータ型です。

カスタムイベントビルダーには 2 つの必須パラメータがあります。

  • Event Type:短くわかりやすいイベントの説明(「FL Pressure Drop」など)。
  • Description:イベントを説明する文字列(「Front Left Tire Pressure Drop」など)。

このイベントの報告を有意義にするには、タイムスタンプと、1 つ以上のデータ型を指定することを推奨します。

  1. 基本的なカスタムイベントを作成します。

    import com.appdynamics.iot.events.CustomEvent;
    ...
    CustomEvent.Builder builder = CustomEvent.builder("FL Pressure Drop", "Front Left Tire Pressure Drop");
    long eventStartTime = System.currentTimeMillis();
    long duration = 6000;
    builder.withTimestamp(eventStartTime).withDuration(duration);
    builder.addLongProperty("PSI Drop", 37);
    CustomEvent customEvent = builder.build();
    JAVA

    追加の情報は CustomEvent に追加できます。詳細については、最新の Java IoT SDK ドキュメントCustomEvent クラスを参照してください。

  2. カスタムイベントをインストゥルメンテーションに追加します(これにより、インメモリバッファに追加されます)。

    Instrumentation.addEvent(customEvent);
    JAVA
  3. すべてのイベントを EUM サーバに送信します。これはブロッキングコールであるため、アプリケーションは上記のように別のスレッドで送信できます。

    Instrumentation.sendAllEvents();
    JAVA

ネットワークイベントの送信

  1. HttpRequestTracker クラスを使用してネットワーク リクエスト イベントを報告します。このコールはインメモリバッファにイベントを自動的に追加するため、クラスを明示的にインポートする必要があります。

    import com.appdynamics.iot.HttpRequestTracker;
    ...        
    String url = "http://ip.jsontest.com/?callback=showMyIP";        
    // Add a Network Event
    try {
        URL thisUrl = new URL(url);
        // [AppDynamics Instrumentation] Get a Tracker            
        HttpURLConnection con = (HttpURLConnection) thisUrl.openConnection();            
        final HttpRequestTracker tracker = Instrumentation.beginHttpRequest(thisUrl);
        con.setRequestMethod("POST");
        con.setRequestProperty("Accept-Language", "en-US,en;q=0.5");            
        int responseCode = con.getResponseCode();            
        con.setDoInput(true);
        con.setDoOutput(true);
        DataOutputStream wr = new DataOutputStream(con.getOutputStream());
        wr.flush();
        wr.close();
        System.out.println("Response Code :" + responseCode);            
        // [AppDynamics Instrumentation] Retrieve the headers from the response
        Map<String, List<String>> headerFields = null;
        System.out.println("Sending 'POST' request to URL :" + url);
        BufferedReader in;
        String inputLine;
        new InputStreamReader(con.getErrorStream()));
        if (responseCode >= 200 && responseCode < 300) {
            in = new BufferedReader(new InputStreamReader(con.getInputStream()));
        } else {
            in = new BufferedReader(
        }
        StringBuffer response = new StringBuffer();
        if (headerFields != null && headerFields.size() > 0){
            while ((inputLine = in.readLine()) != null) {
               response.append(inputLine);
            }
            in.close();
            // [AppDynamics Instrumentation] Initiate adding NetworkRequestEvent
            if (responseCode >= 200 && responseCode < 300) {
                tracker.withResponseCode(responseCode).withError(response.toString()).reportDone();
                       .withResponseHeaderFields(headerFields)                    
                       .reportDone();
            } else {
                tracker.withResponseCode(responseCode).reportDone();
            }
        } else {
            tracker.withResponseCode(responseCode)
        } 
    // End: Add for AppDynamics Instrumentation - Initiate adding NetworkRequestEvent
    } catch (MalformedURLException e) {
        e.printStackTrace();
    } catch (Exception ex) {            
        ex.printStackTrace();
    }
    JAVA
  2. すべてのイベントを EUM サーバに送信します。これはブロッキングコールです。アプリケーションは、別のスレッドで送信できます。sendAllEvents メソッドを呼び出す前に、複数のイベントをまとめてバッチ処理することを推奨します。

    Instrumentation.sendAllEvents();
    JAVA

エラーイベントの送信

  1. API を使用してエラーイベントを報告します。

    try {
        //Force creating an exception
        float f = (5 / 0);   
    } catch (Throwable t) {
        Instrumentation.addErrorEvent(t, Instrumentation.Severity.ALERT);
    }
    JAVA
  2. すべてのイベントを EUM サーバに送信します。これはブロッキングコールです。アプリケーションは、別のスレッドで送信できます。 

    Instrumentation.sendAllEvents();
    JAVA

コントローラ UI でのインストゥルメンテーションの確認

IoT アプリケーションがコントローラにデータをレポートしたことの確認」を参照してインストゥルメンテーションを確認します。 

ビジネストランザクションをネットワークリクエストと関連付ける(オプション)

ビジネストランザクション(BT)をネットワークリクエストと関連付けるには、ビジネスアプリケーションをインストゥルメント化し、コントローラ UI でビジネストランザクションを有効にしておく必要があります。詳細については、「IoT モニタリング用のビジネストランザクションの相関」を参照してください。

次の手順では、BT 応答ヘッダーを取得し、それらを使用して、その BT を IoT ネットワーク リクエスト イベントと関連付ける方法について説明します。

  1. AppDynamics HTTP リクエストヘッダー ADRUM と ADRUM_1 を含むネットワークリクエストをビジネスアプリケーションの 1 つに対して作成します。

    import com.appdynamics.iot.HttpRequestTracker;
    ...    
    // Create a network request to the business app.  
    String url = "<url_to_business_application>";        
    URL thisUrl = new URL(url);
    [AppDynamics Instrumentation] Get a Tracker            
    HttpURLConnection con = (HttpURLConnection) thisUrl.openConnection();            
    final HttpRequestTracker tracker = Instrumentation.beginHttpRequest(thisUrl);
    con.setRequestMethod("POST"); // Some HTTP method: GET, POST, PUT...
     
    // Add the AppDynamics HTTP headers ADRUM and ADRUM_1 to the request.
    con.setRequestProperty("ADRUM", "isAjax:true");
    con.setRequestProperty("ADRUM_1", "isMobile:true");
     
    // Make the request to your business app.
    con.setDoInput(true);
    JAVA
  2. コールは、関連するビジネストランザクションの情報を含む応答ヘッダーを返します。これらの BT 応答ヘッダーを出力する場合は、次のように表示されます。

    {
      ADRUM_1=[globalAccountName:customer1_78203698-278e-428f-8726-bb381219c6cb], 
      null=[HTTP/1.1 200 OK], 
      ADRUM_0=[clientRequestGUID:2ff45113-6746-4c94-b6d0-4af26055613c], 
      ADRUM_3=[btERT:269], 
      ADRUM_2=[btId:4423], 
      Server=[Jetty(9.4.z-SNAPSHOT)], 
      ADRUM_5=[btDuration:327], 
      ADRUM_4=[serverSnapshotType:f], 
      Content-Length=[514], 
    }
    JAVA

     

  3. BT 応答ヘッダーを含むビーコンを EUM サーバに送信します。

    // Fetch the response headers, which will include the BT headers (ADRUM_0, ADRUM_1, ...).
    Map<String, List<String>> headerFields = con.getHeaderFields();
     
    // Add the BT response headers to the request body of the Network Request event.
    // that you're reporting.
    tracker.withResponseCode(responseCode).withError(response.toString()).reportDone();
                       .withResponseHeaderFields(headerFields)                    
                       .reportDone();
     
    // Report the Network Request event to the EUM Server.
    Instrumentation.sendAllEvents();
    JAVA

     

  4. コントローラ UI では、関連するビジネストランザクションを [Device Details] ダイアログで確認できます。 

SDK のロギングを有効にする(オプション)

IoT Java SDK は、ロギングフレームワークとして Java(SLF4J)用シンプルロギングファサードを使用します。SLF4J と互換性のあるお気に入りのロギングエンジンを使用できます。  

クラスパスでバインドが見つからない場合、SLF4J はデフォルトで非動作の実装になり、次のようなコンソールメッセージが表示されます。

SLF4J: Failed to load class "org.slf4j.impl.StaticLoggerBinder".
SLF4J: Defaulting to no-operation (NOP) logger implementation //
SLF4J: See http://www.slf4j.org/codes.html#StaticLoggerBinder for further details. 


java.util.logging エンジンを使用するには、build.gradle ファイルに次の行を追加します。

dependencies {
   ....
   runtime group: 'org.slf4j', name: 'slf4j-jdk14', version: '1.7.25'
   ....
 }
TEXT

ライブラリからすべてのデバッグメッセージを表示するには、ファイル /Library/Java/JavaVirtualMachines/<your-jdk-version>/Contents/Home/jre/lib/logging.properties の下部に次の行を追加します。

com.appdynamics.iot.level = FINEST

IoT Java インストゥルメンテーションのカスタマイズ(オプション)

 IoT Java SDK を使用して、IoT Java インストゥルメンテーションをさらにカスタマイズできます。最新の IoT Java SDK ドキュメント、または以下に記載されている以前のバージョンを参照してください。

サンプル Java アプリケーションの実行

サンプル Java アプリケーションは、カスタム、ネットワークリクエスト、およびエラーイベントのサンプルデータを送信します。データは、スマート カー アプリケーションをモックし、使用状況情報、ネットワークパフォーマンス、およびエラーをキャプチャします。

サンプルアプリケーションを実行するには、iot-java sdk GitHub リポジトリに記載されている「Getting Started」の手順に従います。 

IoT Java SDK のトラブルシューティング

ここでは、一般的な問題をデバッグする手順について説明します。 

IoT Java エージェントをリンクできません

IoT Java エージェントをリンクしようとしたときに次のエラーが発生した場合は、log4j. での依存関係が原因です。

loader constraint violation: when resolving method "org.slf4j.impl.StaticLoggerBinder.getLoggerFactory()Lorg/slf4j/ILoggerFactory;" the class loader (instance of com/intellij/ide/plugins/cl/PluginClassLoader) of the current class, org/slf4j/LoggerFactory, and the class loader (instance of com/intellij/util/lang/UrlClassLoader) for the method's defining class, org/slf4j/impl/StaticLoggerBinder, have different Class objects for the type org/slf4j/ILoggerFactory used in the signature
java.lang.LinkageError: loader constraint violation: when resolving method "org.slf4j.impl.StaticLoggerBinder.getLoggerFactory()Lorg/slf4j/ILoggerFactory;" the class loader (instance of com/intellij/ide/plugins/cl/PluginClassLoader) of the current class, org/slf4j/LoggerFactory, and the class loader (instance of com/intellij/util/lang/UrlClassLoader) for the method's defining class, org/slf4j/impl/StaticLoggerBinder, have different Class objects for the type org/slf4j/ILoggerFactory used in the signature
	at org.slf4j.LoggerFactory.getILoggerFactory(LoggerFactory.java:273)
	at org.slf4j.LoggerFactory.getLogger(LoggerFactory.java:241)
	at org.slf4j.LoggerFactory.getLogger(LoggerFactory.java:254)
	at com.appdynamics.iot.Instrumentation.<clinit>(Instrumentation.java:39)
	...
BASH

この問題を修正するには、ロギングを有効にするために追加した依存関係を削除する必要があります。したがって、次に示すグループ org.slf4j を指定する行を dependencies: から削除します。

dependencies {
   ....
   runtime group: 'org.slf4j', name: 'slf4j-jdk14', version: '1.7.25'
   ....
}
BASH