Azure Application Insights を Java アプリから使おう

# Application Insights を Javaアプリから使おう

アプリケーション開発者にとって、実際にアプリがどう動いているかを監視するのは、大事なことだったりします。そのため、例外をハンドルしたり、ログを仕込んだりと色々と準備しておくことも多いでしょう。

今回、ここで紹介する Application Insights ですが、コードに修正を入れることなくアプリケーションの各種メトリクスデータを取得できる優れものです。ログはもちろん、パフォーマンス、例外と言った記録を収集し蓄積してくれます。

公式ドキュメントの入り口は以下です。今では Azure Monitor の一機能的な位置づけになっています。

[Azure Application Insights とは何か - Azure Monitor | Microsoft Docs](https://docs.microsoft.com/ja-jp/azure/azure-monitor/app/app-insights-overview?WT.mc_id=AZ-MVP-5001265)

# データモデル

はじめに Application Insights で収集するデータモデルを理解すると、全体像の把握に繋がると思います。Application Insights が収集するデータは抽象化されており、主要な言語は対応しています。（C#/Java/JavaScript/Python/Node.js) 

どのようなデータを収集するかといえば、代表的な物は以下の通りです。

|データ  |意味  |
|---|---|
|リクエスト  | HTTPのリクエストを記録する  |
|トレース  |アプリケーションのログを記録する  |
| 例外 | アプリケーションがスローした例外を記録する|
| メトリック| Javaの場合だと、JVMの情報が定期的に記録される|
|依存関係| アプリが依存する外部コンポーネントを記録する。JDBCとか|

[Azure Application Insights Telemetry のデータ モデル - Azure Monitor | Microsoft Docs](https://docs.microsoft.com/ja-jp/azure/azure-monitor/app/data-model?WT.mc_id=AZ-MVP-5001265)

例えば、 Java アプリケーションに Application Insights の設定を行っておけば、これらの情報が収集され、Azure 上にある Application Insights に情報が送られ続けます。これらをどのように見るか（可視化）は、ポータルで色々な方法が用意されていますし、クエリ言語でデータを検索することもできます。

# Application Insights for Java

現在、2.6系と、3.0系の2つのバージョンがあります。

前者は、アプリケーションにライブラリを含める形でパッケージングする必要がありますので、既存資産に手を入れる必要がります。メンテナンスはされていますが、最新ではないので3.0を使うことをお勧めします。カスタムメトリクスを取得したい場合は、こちらを使う必要もあったりしますが、それは別の機会に。

現時点でのlatestは、3.0系です。 Java エージェントの仕組みを使用しており、既存資産に手を入れずApplication Insights に対応させることができます。

使い方は簡単で、JVM 引数に `-javaagent:path/to/applicationinsights-agent-3.0.3.jar` と指定するだけです。後で説明しますが、キーの設定は環境変数等に必要ですが。

以下のGithubから最新がダウンロード出来ると思います。執筆時点では、`3.0.3`が最新で、Java8以降が対象です。

* https://github.com/microsoft/ApplicationInsights-Java/releases

また、エージェント方式のドキュメントは以下にあります。

[Azure Monitor Application Insights Java - Azure Monitor | Microsoft Docs](https://docs.microsoft.com/ja-jp/azure/azure-monitor/app/java-in-process-agent)

# 何が収集されるか

先ほどのドキュメントにもかかれていますが、適当引用しますと、主要のコンポーネントに対応し、それらのメトリクスが自動収集されます。

リクエスト

> * JMS コンシューマー
> * Kafka コンシューマー
> * Netty/WebFlux
> * Servlets
> * Spring スケジュール

ログ
> * java.util.logging
> * Log4j (MDC プロパティを含む)
> * SLF4J/Logback (MDC プロパティを含む)

依存関係
> * Apache HttpClient と HttpAsyncClient
> * java.net.HttpURLConnection
> * JMS
> * Netty クライアント / OkHttp
> * JDBC

# 実際ためしてみる

そこそこのアプリじゃないと、集まるデータもあつまらないので、Spring Pet Clicnc アプリで試してみます。以下から、適当にCloneして環境を整えます。

https://github.com/spring-projects/spring-petclinic

Application Insights は、Azure ポータルから作成し、インストルメンテーションキーを含む接続文字列を取得しておきます。Application Insights は、Azure 上で動くアプリ限定というわけではありません。オンプレや他プラットフォームからも利用できます。テレメトリの送信はHTTPベースですので、気軽に利用できると思います。

`mvn spring-boot:run` すると、アプリが起動しますので、ブラウザでアクセスしてみましょう。おなじみの画面が表示されます。

![2021-05-02 10_18_21-PetClinic __ a Spring Framework demonstration - [InPrivate] - Microsoft​ Edge.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/34017/1107e1b1-6840-515e-33fe-8c5f49639f74.png)


一旦終了し、以下の設定を行います。

pom.xml の maven plugin のJVM引数の構成を設定します。

```xml
        <configuration>
          <jvmArguments>-javaagent:c:\yourpath\applicationinsights-agent-3.0.3.jar</jvmArguments>
        </configuration>
```

次に接続文字列を環境変数に設定します。

```
set APPLICATIONINSIGHTS_CONNECTION_STRING=InstrumentationKey=...
```

# 観察してみる

再度実行して、Webを操作してみましょう。しばらくすると、送信されたテレメトリをAzure  ポータル側で見られるようになります。代表的なものをいくつか見てみます。

## ライブメトリクス

簡単に動作しているか確認するには、ライブメトリクスを開きます。リアルタイムにアプリケーションの状況が確認できます。言語によってはサポートしてない場合もあった気もしますが、Java の 3.0系ではサポートされています。

![2021-05-02 10_40_29-qiitaappinsights - Microsoft Azure および他 1 ページ - 職場 - Microsoft​ Edge.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/34017/cc1fe789-703f-807a-1fde-af77def177c6.png)


## 検索

ざっくりどんなものが記録されているか確認するには、トランザクションの検索を見てみます。下記の画像のように、Request/Dependency テレメトリが記録されていることがわかります。

![2021-05-02 10_42_21-qiitaappinsights - Microsoft Azure および他 1 ページ - 職場 - Microsoft​ Edge.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/34017/487e04eb-758a-3025-610a-9106bbf2464b.png)


## アプリケーションマップ

自アプリケーションと、外部コンポーネントの依存関係がマップ形式表示されます。Spring Pet Clinicですと、外部コンポーネントが内部のDBくらいしかないので、この程度の表示になってしまいますが、ストレージに依存していたり、CosmosDbに依存したり、外部のAPIに依存していれば、当然それらはマップ化されます。

![2021-05-02 10_44_35-qiitaappinsights - Microsoft Azure および他 1 ページ - 職場 - Microsoft​ Edge.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/34017/9c5c2aa1-8eab-c7d7-7b1d-a9656b1a3a0f.png)

## 失敗

例外が記録されます。ハンドルされないものや、例外オブジェクト付のログなんかは、ここに記録されます。Spring Pet Clinic では、例外を起こす画面があるので、そのページをアクセスしてみましょう。

この例ではあまり有意な情報はでませんが、エラーの上位や、エラーをドリルダウンしていくことができます。

![2021-05-02 10_49_06-qiitaappinsights - Microsoft Azure および他 1 ページ - 職場 - Microsoft​ Edge.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/34017/fd769a14-c912-e1af-f5db-2c1b179b7cc1.png)

## 詳細

ドリルダウンしていくと以下のような詳細画面を表示できます。どのリクエストから、どの外部コンポーネントが呼ばれているのかを、チャート形式で見ることが出来ます。例外基点でどのようなリクエストがエラーを引き起こしたかなどの原因究明に役立つでしょう。

![2021-05-02 10_50_51-エンド ツー エンド トランザクションの詳細 - Microsoft Azure および他 1 ページ - 職場 - Microsoft​ Edge.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/34017/dc52ecc9-bfed-87c2-2343-cb2b9e8ada6b.png)


# ログの検索

記録された生のデータは、ログの検索から見ることが出来ます。テレメトリ毎にKQLというクエリ言語で検索したり、それらをグラフ化したりできます。以下はリクエストを取得した例です。

![2021-05-02 10_53_31-qiitaappinsights - Microsoft Azure および他 1 ページ - 職場 - Microsoft​ Edge.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/34017/2da1690a-486f-4c88-d534-dd64562ce1d5.png)

余談ではありますが、ログを検索すれば、どのようなSQLが発行されたかを確認したり、

![2021-05-02 10_54_40-qiitaappinsights - Microsoft Azure および他 1 ページ - 職場 - Microsoft​ Edge.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/34017/378f2380-74a9-5423-d3ee-a2beaa330d0a.png)

VMの統計情報を見ることも出来ます。

![2021-05-02 10_55_31-qiitaappinsights - Microsoft Azure および他 1 ページ - 職場 - Microsoft​ Edge.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/34017/ce3d51d2-6169-bf5c-b9b4-75ff170ae677.png)

# まとめ

今回は、Azure Application Insights を試してみましたが、アプリケーション開発者にとって入れて損することはないので、是非設定しましょう。WebApps/Functions などは、ポータルから設定することもできるので、ほぼなにもすることはありません( すでに、3.0 ベースのエージェントになっていると思いますが、未確認）

一定量までは無料で使うことも出来ますし、色々試してみることをお勧めします。ある程度データが蓄積されてないと面白くないのですが。