normalian blog

Let's talk about Microsoft Azure, ASP.NET and Java!

Application Insights を Java のコンソールアプリで利用する

Application Insights のドキュメントを確認すると Web アプリでの利用が多いが、実はコンソールアプリケーションでも利用可能なことをご存じだろうか?
今回は Java コンソールアプリで Application Insights で利用する方法を紹介する。すでに Github にて Console App で Appinsights 利用するサンプル として公開中なので、必要な方は確認してほしい。

Application Insights をコンソールアプリで利用する場合の TIPS

まずはソースコードを見てほしい。

package com.mydomain.appinsightsconsole;

import com.microsoft.applicationinsights.TelemetryClient;
import com.microsoft.applicationinsights.TelemetryConfiguration;

public class App {
	public static void main(String[] args) {
		// Application Insights の設定を有効化
		TelemetryConfiguration configuration = TelemetryConfiguration.getActive();
		TelemetryClient telemetryClient = new TelemetryClient(configuration);

		telemetryClient.trackTrace("コンソールアプリからのトレースメッセージ");
		telemetryClient.trackException(new RuntimeException("コンソールアプリの自作例外"), null, null);

		// 最後に flush しないとリクエストがメモリ上に滞留したままアプリが終了する
		telemetryClient.flush();

		System.out.println("end");
	}
}

重要なのは以下の点だ。

  • TelemetryClient インスタンス作成前に TelemetryConfiguration#getActive() メソッドを呼び出して設定を有効化する
  • アプリケーション終了前に TelemetryClient#flush() メソッドを呼ぶこと

うまく動けば以下のように管理ポータル上に情報が即座に反映されるはずだ。
f:id:waritohutsu:20160324175238p:plain

Azure Toolkit for Eclipse の2016/3/6 更新と Maven プロジェクトを WebApps にデプロイする方法

2016年3月7日に Azure Toolkit for Eclipse がリリースされた。主なインストール手順は Azure Toolkit for Eclipse のインストール に記載があるので詳細は不要だと認識してるが、同更新での主な追加機能は以下となる。

  • Java の Web アプリ( Tomcat or Jetty で動くアプリ )を Azure Web Apps にデプロイできる!
  • ② Azure Explorer ビューを利用して WebApps の操作ができる!
  • クラウドサービスにデプロイ向けの Tomcat, Jetty, Zulu OpenJDK がサポートするバージョンを更新

上記の機能を簡単に紹介しよう。

① Azure Web Apps へのデプロイ

ずっとクラウドサービスにしかデプロイできなかったので悲しい気持ちになっていたが、ようやく WebApps のデプロイが可能になった。「Dynamic Web Project」形式で新規作成したプロジェクトに対し、右クリックのメニューから Azure - Plublish as Azure Web App... を選択することでデプロイ可能だ。
以下の様に API Apps も含めてごそっとでるが、ランタイムが JRE になっているものを選択してデプロイしよう。
f:id:waritohutsu:20160317173129p:plain
「Deploy to root」を選択すると ROOT.war の名前にリネームしてデプロイしてくれる点も便利だ。

② Azure Explorer ビューを利用する!

以下のノリで Eclipse のビューから Web Apps、ストレージ、サブスクリプションの簡易的な操作ができる。
f:id:waritohutsu:20160317173138p:plain


Tomcat, Jetty, Zulu OpenJDK がサポートするバージョンを更新

Tomcat, Jetty は以下のバージョンが利用可能。
f:id:waritohutsu:20160317173143p:plain
Zulu OpenJDK の最新版は以下となる。
f:id:waritohutsu:20160317173152p:plain

Azure Web Apps へ Maven 形式のプロジェクトをデプロイする方法

さて、冒頭で「Dynamic Web Project 形式で新規作成」という記載をしたが、まっとうな Java プロジェクトならば Gradle なり Maven なりを利用しているのが普通だろう。参考のために Maven プロジェクトを Azure Web Apps にデプロイする TIPS を紹介しておく。

まずは、以下の様に Maven 形式の Web アプリのプロジェクトを作成し、Eclipse 形式のファイルを生成する。

C:\opt\workspace>mvn archetype:generate -DgroupId=com.mydomain.deploy2webapp -DartifactId=Deploy2AzureWebApp -DarchetypeArtifactId=maven-archetype-webapp -DinteractiveMode=false
C:\opt\workspace>cd Deploy2AzureWebApp
C:\opt\workspace\Deploy2AzureWebApp>mvn eclipse:eclipse

次に、Eclipse に生成したプロジェクトをインポートする。この時点では右クリックメニューの Azure が存在しないので、右クリックメニューから「Properties」を選択し、以下のステップに従って設定を行う。
f:id:waritohutsu:20160317175118p:plain
左ツリーから Project Facets を選択し、Convert to faceted from.. を選択し、Dynamic Web Module にチェックボックスを追加した後、Further configuration available... を押下し、content directory: を Maven プロジェクトの形式に合わせた src/main/webapp に変更する。

上記の実施後に *.jsp ファイルに対して「The superclass "javax.servlet.http.HttpServlet" was not found on the Java Build Path」エラーが発生するので、以下の画面に従って Tomcat(または Jetty )のサーバーランタイムを追加する。
f:id:waritohutsu:20160317175226p:plain

以上を実施すればプロジェクトの右クリックメニューに Azure が追加されるので、無事に Azure Web Apps にデプロイできるようになる。

現場からは以上だ(`・ω・´)ゞ

Microsoft Azure のリソースグループからテンプレートをエクスポートして環境をコピーする

Microsoft Azure がリソースグループと呼ばれる管理単位を利用し、仮想マシンや WebApps といったリソースをひとまとまりで管理することが可能になる。これにより、リソースの区切り単位が明確になった他、リソースグループ単位で一括で削除ができるために削除忘れが減る等の利点が存在した。
そんなリソースグループだが、昨今は「作成した既存環境のリソースグループをテンプレートとしてエクスポートする」という機能が追加された。これにより、お気軽に既存環境のコピーが可能となった。主に以下の用途で使えるのではないかという推察だ。

  • 開発チームが増員した際、増員者分の環境をコピーする
  • カスタマイズありの SaaS 系サービスの提供ベンダが、各顧客向けに用意する環境としてコピーする

早速使ってみる

最近 Application Insights の検証に利用していたリソースが残っているので、以下のリソースをコピーすることを考えてみる。
f:id:waritohutsu:20160314161435p:plain

設定 - テンプレートのエクスポート を選択すると、以下の画面が表示される。
f:id:waritohutsu:20160314161644p:plain

上記から ファイルに保存 を選択し、ExportedTemplate-"リソースグループ名".zip ファイルをダウンロードすると以下の中身になる。

  • deploy.ps1 … テンプレートデプロイ用のスクリプト
  • template.json … リソースグループのテンプレート、原則修正不要のはずだがちょくちょく修正が必要
  • parameters.json … テンプレートのパラメータ、こちらで値を設定する

上記のうち parameters.json を新規に作るリソース向けに仮想マシン名、ユーザ名、パスワード等々を修正して deploy.ps1 を実行すると以下のようになる。

PS C:\tmp\ExportedTemplate-arm-appinsights-linux-group> .\deploy.ps1
コマンド パイプライン位置 1 のコマンドレット deploy.ps1
次のパラメーターに値を指定してください:
subscriptionId: "サブスクリプションID"
resourceGroupName: "作成済みのリソースグループ、存在しないとエラーになる"
deploymentName: "任意名"
Logging in...

"中略"

Using existing resource group "作成済みのリソースグループ"

DeploymentName     : template
CorrelationId      : xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
ResourceGroupName  : "作成済みのリソースグループ"
ProvisioningState  : Succeeded
Timestamp          : 2016/03/14 6:28:29
Mode               : Incremental

"中略"

上記に実行するだけで容易に既存リソースのコピーが可能だ。まだ発展途上ではあるが、改善後は様々な用途が考えられる面白い機能といえる。

既知の注意点

まだプレビュー機能であるため、以下に注意が必要だ。

  • パブリック IP アドレス の重複に注意

仮想マシンにパブリック IP アドレスを付与済みであり、DNS 名を登録している場合、template.json の以下の個所を修正する必要がある。

        {
            "comments": "Generalized from resource: 'もろもろID'",
            "type": "Microsoft.Network/publicIPAddresses",
            "name": "[parameters('publicIPAddresses_AppInsightsVM2_name')]",
            "apiVersion": "2015-06-15",
            "location": "japaneast",
            "properties": {
                "publicIPAllocationMethod": "Dynamic",
                "idleTimeoutInMinutes": 4,
                "dnsSettings": {
                    "domainNameLabel": "'ここはそのままコピーすると重複してエラー'"
                }
            }
        },

何も修正しないと以下のようなエラーになる。

New-AzureRmResourceGroupDeployment : 13:19:16 - Resource Microsoft.Network/publicIPAddresses 'AppInsightsVMPubIP' failed with message 'DNS record '自身で設定済のdns名'.japaneast.cloudapp.azure.com is already used by another public IP.'
発生場所 C:\tmp\ExportedTemplate-arm-appinsights-linux-group\deploy.ps1:99 文字:5
+     New-AzureRmResourceGroupDeployment -ResourceGroupName $resourceGr ...
+     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : NotSpecified: (:) [New-AzureRmResourceGroupDeployment], Exception
    + FullyQualifiedErrorId : Microsoft.Azure.Commands.Resources.NewAzureResourceGroupDeploymentCommand

管理画面から閲覧可能だが、以下のようにサポートされていないリソースがあるので、テンプレートのエクスポート時に注意が必要だ。
f:id:waritohutsu:20160314161755p:plain

Application Insights の collectd プラグインを利用して Linux のCPUやメモリの負荷状況を取得する

Application Insights が発表されてからかなりの時間が経過したが、実は Application Insights に collectd と連携してログ情報を取り扱う機能が追加されているのをご存じだろうか?
Application Insights のライブラリはアプリケーション( war, ear の中身等)に仕込んで設定するのが原則のソリューションだ。
そんな Application Insights だが、Windows Server の場合は Application Insights Status Monitor をインストールすれば特に追加の対応が不要な一方、Linux 側には同等のコンポーネントが存在しなかった。
今回紹介する collectd と Application Insights を連携することで、特にアプリケーション自体を変更をすることなく OS に対して追加の設定のみで CPU 使用率、メモリ使用量、I/O 使用量を取得することが可能になる。

今回構築する環境

Application Insights と collectd を連携するためには以下が必要となる。

collectd 自体は collectdをインストールしてサーバの監視をしよう! を見て頂くとして、Application Insights と collectd を連携する手順を次から記載する。

環境構築に必要な手順

手順の概要は collectd: Application Insights での Unix パフォーマンス メトリック に記載があるが、こちらでもフォローアップする。

まずは CentOSSSH でログインし、以下のコマンドを叩き込む。collectd をインストールする場合、EPEL パッケージを入れる必要があるので、注意が必要だ。

yum install epel-release
yum update
yum install java-1.8.0-openjdk.x86_64 java-1.8.0-openjdk-devel.x86_64 
yum install httpd httpd-devel
yum install collectd collectd-rrdtool collectd-web collectd-java

次に以下の設定のために /etc/collectd/collectd.conf を編集する。

  • collectd の java, cpu, load, disk プラグインを有効化する
  • collectd の Application Insights Java Plugin を設定する

以下の様な記載になる認識だ。

...
# collectd plugins
LoadPlugin cpu
LoadPlugin disk
LoadPlugin load
...

# Enable Java Plugin
LoadPlugin "java"

# Configure Java Plugin
<Plugin "java">
  JVMArg "-verbose:jni"
  JVMArg "-Djava.class.path=/usr/share/collectd/java/applicationinsights-collectd-1.0.3.jar:/usr/share/collectd/java/collectd-api.jar"

  # Enabling Application Insights plugin
  LoadPlugin "com.microsoft.applicationinsights.collectd.ApplicationInsightsWriter"

  # Configuring Application Insights plugin
  <Plugin ApplicationInsightsWriter>
    InstrumentationKey "<自身の instrument key>"
  </Plugin>

</Plugin>

上記で記載した Application Insights collectd ライター プラグイン を取得する必要があるので、リンクより取得する。また、applicationinsights-collectd-x.x.x.jar はバージョンアップがこまめにされているので、リンクが切れていたら「バージョンが上がったのかな?」と推察してリンクからバージョンを修正して jar を取得する心意気が必要になる。
また、上記で記載した通り ApplicatinInsights.xml という構成ファイルが必要になる点にも注意が必要だ。

mv /home/azureuser/applicationinsights-collectd-1.0.3.jar /usr/share/collectd/java/
mv /home/azureuser/ApplicationInsights.xml /usr/share/collectd/java/ApplicationInsights.xml

ApplicatinInsights.xml を配置しない場合、以下の様なエラーが発生して ApplicationInsights の情報が Azure ポータル側に反映されない。

[root@AppInsightsVM ~]# tail -n 30 /var/log/messages
......
Mar  5 04:36:27 AppInsightsVM collectd: [Dynamic-linking native method java.io.FileOutputStream.writeBytes ... JNI]
<b><span style="color: #ff0000">Mar  5 04:36:27 AppInsightsVM collectd: AI: INFO 05-03-2016 04:36, 1: Configuration file 'ApplicationInsights.xml' was NOT found by default class loader
Mar  5 04:36:27 AppInsightsVM collectd: AI: INFO 05-03-2016 04:36, 1: Did not find configuration file 'ApplicationInsights.xml' in '/usr/share/collectd/java'
Mar  5 04:36:27 AppInsightsVM collectd: AI: INFO 05-03-2016 04:36, 1: Did not find configuration file 'ApplicationInsights.xml' in '/usr/share/collectd/java'
Mar  5 04:36:27 AppInsightsVM collectd: AI: WARN 05-03-2016 04:36, 1: Configuration file 'ApplicationInsights.xml' could not be found</span></b>

以上で設定は完了だが、SELinux の設定が有効化されている場合、collectd を実行した場合に以下のエラーが発生する。

[root@AppInsightsVM ~]# tail -n 30 /var/log/messages                                                                                                                   
Mar  5 04:13:38 AppInsightsVM systemd: collectd.service: main process exited, code=exited, status=1/FAILURE
Mar  5 04:13:38 AppInsightsVM systemd: Unit collectd.service entered failed state.
Mar  5 04:13:38 AppInsightsVM systemd: collectd.service failed.
Mar  5 04:13:38 AppInsightsVM systemd: collectd.service holdoff time over, scheduling restart.
Mar  5 04:13:38 AppInsightsVM systemd: Started Collectd statistics daemon.
Mar  5 04:13:38 AppInsightsVM systemd: Starting Collectd statistics daemon...
<span style="color: #ff0000"><b>Mar  5 04:13:38 AppInsightsVM collectd: OpenJDK 64-Bit Server VM warning: INFO: os::commit_memory(0x00007fc7b780a000, 2555904, 1) failed; error='Permission denied' (errno=13)</b></span>
Mar  5 04:13:38 AppInsightsVM collectd: #
Mar  5 04:13:38 AppInsightsVM collectd: # There is insufficient memory for the Java Runtime Environment to continue.
Mar  5 04:13:38 AppInsightsVM collectd: # Native memory allocation (mmap) failed to map 2555904 bytes for committing reserved memory.
Mar  5 04:13:38 AppInsightsVM collectd: # An error report file with more information is saved as:

今回は以下のコマンドを利用して一時的に SELinux を無効化するが、自身の環境とポリシーに合わせて設定を行ってほしい。

[root@AppInsightsVM ~]# setenforce 0

上記の完了後、collectd と Apache を起動する。

[root@AppInsightsVM ~]# systemctl start collectd
[root@AppInsightsVM ~]# systemctl start httpd

設定がうまくいっている場合、管理ポータルから情報の取得が可能となる。以下の様にポータルの Application Insights 画面からメトリックスエクスプローラの「グラフの追加」から各種グラフを表示することができる。
f:id:waritohutsu:20160306122839p:plain

Microsoft Azure の Machine Learning を利用して日経平均株価を予測してみる~その①まずは作ってみる~

Microsoft Azure にて Machine Learning がリリースされてから大分経過したのはご存知の方も多いと思う。話題にあがることは多いので知識として知っている方は多いと思うが、実際に利用したことのあるかたは実は少ないのではないだろうか?
実際に手を動かす方が理解は容易であるため、最近 20,000 円台を回復しつつまた下がった日経平均株価を予測するサンプルの作成を通して Microsoft Azure の Machine Learning(以下、Azure ML)の利用方法を学習したいと思う。

念のための注意となるが、今回のサンプルの結果を見て株や金融商品の売買をすることは控えて頂きたい。機械学習自体は歴史も長く奥の深い分野であり、今回紹介する内容は「Azure ML の利用方法をサンプル作成から紹介する」ものであって「機械学習を利用して日経平均株価を高精度で予測する」ものではない。

作成するサンプルの概要

今回は 日経平均プロフィル-日経の指数公式サイト- に公開されている過去15年分の日経平均株価のデータを利用し、翌日の日経平均株価を予測するサンプルを作成する。

上記のデータを利用し、機械学習の Web サービスを作成するが、入力と結果は以下になる。

Azure ML の管理画面である Azure Machine Learning Studio からの動作イメージは以下になる。
f:id:waritohutsu:20151216163046p:plain

以下のうち、Scored Labels 列の値である 19053.57… が予測した日経平均株価の値となる。
f:id:waritohutsu:20151216163108p:plain

Azure Machine Learning Studio を開く

手順は省くが、まずは Microsoft Azure の管理ポータルから Machine Learning を選択して以下の管理画面に到達してほしい。
f:id:waritohutsu:20151216163128p:plain

学習用データを Azure Machine Learning Studio に登録

日経平均プロフィル-日経の指数公式サイト- より日経平均株価のデータが日次で CSV 形式として保存されている nikkei_stock_average_daily_jp.csv を取得する。
CSV ファイルには データ日付, 終値, 始値, 高値, 安値 しか項目がないので、Excel でファイルを開き、前日終値, 前日始値, 前日高値, 前日安値列を追加して 終値, 始値, 高値, 安値の値を1日分ずらしてコピーする。
前日のデータが存在しなくなる初日データ(サンプル作成時は 2012/1/4 日)行は削除し、データ最終行にある「本資料は日経の著作物であり、本資料の全部又は一部を、いかなる形式によっても日経に無断で複写、複製、転載または流布することができません。」の文章が記載されている行も削除する。

最終的な形式は以下のようになるイメージだ。最後に、秀丸等でファイルを開きなおし、 Shift-JIS 形式になっているデータを UTF-8 形式に保存しなおせば完了だ*1
f:id:waritohutsu:20151216163143p:plain

Azure Machine Learning Studio を開き、[New]-[FROM LOCAL FILE]を選択する。
f:id:waritohutsu:20151216163201p:plain

以下の画面の様に作成した CSV データを選択し、Azure ML にデータセットを登録する。
f:id:waritohutsu:20151216163211p:plain

登録したデータからモデルを学習する

管理画面の[NEW]-[EXPERIMENT] から Blank Experiment を選び、からのシートを作成する。以下の画面が表示されればOKだ。
f:id:waritohutsu:20151216163350p:plain

次に、画面左の[Saved Datasets]-[My Datasets]から先ほど登録した日経平均株価CSV データを選択し、ドラッグアンドドロップで移動して作成する。

作成後、データセットの真ん中下側にある丸を右クリックし、Visualize を選択すると以下の画面が表示され、正常にデータが読み込めていることが理解できる。
f:id:waritohutsu:20151216163417p:plain

次に、学習には不要である データ日付, 始値, 高値, 安値列を削除する。前日のデータを利用して終値を計算するため、これらの列は不要なためだ。
[Data Transformation]-[Manipulation] から Project Columns を選択し、ドラッグアンドドロップでシート上に配置する。さらに、データセットの真ん中下側にある丸を左クリックし、そのままマウスをドラッグして Project Columns につなぐ。以下のような画面になれば成功だ。
f:id:waritohutsu:20151216163453p:plain

このままではどの列を選択するかを指示できていないため、画面右の Launch Column Selector を起動して必要な列だけピックアップするため、以下の様に設定する。
f:id:waritohutsu:20151216163503p:plain

次に、モデル向けの学習データ、学習精度を確認するためのデータに分割するため [Data Transformation]-[Sample and Split] の Split Data を選択してシートに配置し、以下のように Project Columns と接続する。
f:id:waritohutsu:20151216163521p:plain

今回は特に Split Data の設定はしないが、必要な場合は振り分けの Random Seed や分配率等を変えても良いだろう。

次に学習するモデルを配置する。まずは [Train] から Train Model をシート上に配置し、モデルに利用するアルゴリズムである線形回帰(Linear Regression)をシート上に配置し、それらを以下のように配置する。
f:id:waritohutsu:20151216163605p:plain

ここでさらに Train Model を選択し、画面右から Launch column Selector を押して予測する列を選択するが、今回は当然「終値」を選択する。ここまでで、実サンプルデータを利用してモデルに学習させるボックスの配置は完了した。

次に学習したモデルを評価するためのボックスを配置する。画面左より Score Model と Evaluate Model を選択し、以下のように配置する。Split データの一部を学習のために利用し、残ったデータをモデル評価のために利用しているのが理解できると思う。
f:id:waritohutsu:20151216170117p:plain

あらかた完成したので、画面下より[Save]-[Save As]を選択して任意の名前で保存する。次に、シートを実行するために [RUN] を押下する。
私が試した際には1分ほどで完了したが、以下の画面の様に各ボックスに緑のチェック印がついていれば完了だ。
f:id:waritohutsu:20151216170127p:plain

Evaluated Model の真ん中下を右クリックし、Visualize を選択すると以下のようにモデルに対する評価を確認できる。
f:id:waritohutsu:20151216170139p:plain

それぞれ、作成したモデルの正確さを評価する値になる。

Mean Absolute Error 145.023541
Root Mean Squared Error 204.021175
Relative Absolute Error 0.046778
Relative Squared Error 0.002936
Coefficient of Determination 0.997064

上記のうち、特に Root Mean Squared Error Coefficient of Determination から以下が理解できる。

  • Coefficient of Determination:1 に近いほどモデルの精度が高いため、今回はモデルの精度が良い
  • Root Mean Squared Error:二乗平均平方根の値であるため、予測値と実際の値とのかい離が大きいと思われる

上記から、予測精度は悪くないが、外した場合の誤差が大きいということが読み取れる。株価予測としては数値の誤差が大きいことに不安を感じるものの、ここまでで学習モデルの完了だ。

Web サービスとして公開する

学習したモデルを利用し、Web サービスとして他アプリと連携できるかたちで公開する。画面下より [Predict Web Service - Recommended] を押下する。シート内でごにょごにょとボックスが動いて以下の形になるはずだ。
f:id:waritohutsu:20151216170241p:plain

Web Service Input が Project Column につながっているが、このままだと不要なデータも引数として入力する必要があるので以下の形に変更し、さらに Project Column から「終値」を選択列から除外する。
f:id:waritohutsu:20151216170255p:plain

あとは [Run] で実行した後に [DEPLOY WEB SERVICE]を選択することでAzure Machine Learning Studio で Web サービスとして登録される。
無事に Web サービスとして登録されると以下の画面が表示される。
f:id:waritohutsu:20151216170303p:plain

上記の[Test]ボタンを押下すると引数を入力する画面が表示されるので、冒頭でスクリーンショットを利用して紹介した通り、日経平均株価の予測ができる。

考察について

2015年12月10日までのデータを利用して実際に試した結果は以下となった。

  • 予測値:19053.57
  • 実際の値:19,230.48

本来日経平均株価を予測するためには、NYダウ平均、為替、先物、原油価格等の様々なパラメータ値はもちろんのこと、政治的な要因も大きく絡むために今回利用したパラメータだけではデータが少なすぎることが原因だと思われる。
本サンプルの拡張としては「パラメータ値を増やす」はもちろんだが、「今回利用した Linear Regression だけでなく異なる回帰アルゴリズムの利用を検討する」といった方法も考えられる。

予測精度そのものは改善の必要があるが、慣れている人間ならば上記のサンプルを20分~30分程度で作成することが可能な点も含め、Microsoft Azure の Machine Learning が容易に利用できることが理解できたと思う。

是非皆さまも利用を検討して頂きたい。

*1:UTF-8にしないとAzure Machine Learning Studio で文字化けする

AppInsights の Java SDK を利用して CentOS の CPU 使用率、メモリ使用量、Process IO rate を確認する

前回までの記事で、Application Insights の JavaSDK を利用することで、Windows の場合に CPU 使用率、メモリ使用量、Process IO rate が取得できることが分かった。
Unix の場合はどうなのかと確認したところ、ApplicationInsights-Java/core/src/main/java/com/microsoft/applicationinsights/internal/perfcounter/ 内に Unix の性能情報を取得することができそうなクラスが存在することが分かった。

AppInsights の JavaJDK を仕込んだアプリを CentOS で動かしてみる

Azure のテンプレートから CentOS 7.1 を選択し、OpenJDK 1.8.0 と Tomcat をインストールし、Windows の場合と同様の war をデプロイして Java Web アプリを動かしてみた。
アプリ稼働後、数分でパフォーマンス情報が Application Insights のポータルに反映される。念のため yes >> /dev/null コマンドで CPU 負荷をかけると、以下のグラフの様に CPU 使用率が増加していることもわかる。
f:id:waritohutsu:20151206141759p:plain

どこの情報を取得しているのかソースコードを確認してみる

パッケージを確認すると、以下の7クラスが存在する。Abstract の名前が含まれるクラスは置いておくとして、CPU 使用率、メモリ使用量、Process IO rate を取得していることが推察できる。

  • AbstractUnixPerformanceCounter.java
  • UnixParsingState.java
  • UnixProcessIOPerformanceCounter.java
  • UnixProcessIOtParser.java
  • UnixTotalCpuPerformanceCounter.java
  • UnixTotalMemInfoParser.java
  • UnixTotalMemoryPerformanceCounter.java

CPU 使用率はどこを見ているのかを確認すると、UnixTotalCpuPerformanceCounter.java に記載されるように /proc/stat の値を確認していることが分かる。

メモリ使用量については UnixTotalMemoryPerformanceCounter.java を確認すると /proc/meminfo の情報を取得していることが分かる。

Process IO rate は UnixProcessIOPerformanceCounter.java より、/proc/"自身のプロセスID"/io から取得していることが分かる。

また、ここでは詳細に解説しないが、上記の各 PerformanceCounter クラスは、war アプリケーション起動時に初期化される。このため、特に開発者側が意識をせずに利用することができる点も利便性が高いといえる。

AppInsights の Java SDK が出力するログを確認したい場合

Application Insights を利用する場合、設定ファイルが読み込まれたか?何か内部エラーが発生していないか等を詳細に確認したい場合がある。その際に利用できる InternalLogger について紹介する。

有効化する - コンソール出力編

以下のように ApplicationInsights.xml の SDKLogger タグを追加する。

<?xml version="1.0" encoding="utf-8" standalone="no"?>
<ApplicationInsights xmlns="http://schemas.microsoft.com/ApplicationInsights/2013/Settings" schemaVersion="2014-05-30">
        "中略"
	<SDKLogger>
	</SDKLogger>
	<DisableTelemetry>false</DisableTelemetry>
</ApplicationInsights>

ソースコードを確認すると理解できるが、SDKLogger タグが存在している場合に初期化処理が実行されるようになっている。

デフォルトでは以下のように CONSOLE に最初が"AI"として情報が出力される設定になっている。

情報: At least one JAR was scanned for TLDs yet contained no TLDs. Enable debug logging for this logger for a complete list of JARs that were scanned but no TLDs were found in them. Skipping unneeded JARs during scanning can improve startup time and JSP compilation time.
AI: INFO 30-11-2015 00:08, 19: Registering WebApp with name 'AppInsightWebApp'
AI: INFO 30-11-2015 00:08, 19: Configuration file has been successfully found as resource
AI: WARN 30-11-2015 00:08, 19: 'MaxTelemetryBufferCapacity': null value is replaced with '500'
AI: WARN 30-11-2015 00:08, 19: 'FlushIntervalInSeconds': null value is replaced with '5'
AI: TRACE 30-11-2015 00:08, 19: Using Http Client version 4.3+
AI: TRACE 30-11-2015 00:08, 19: No back-off container defined, using the default 'EXPONENTIAL'
AI: WARN 30-11-2015 00:08, 19: 'Channel.MaxTransmissionStorageCapacityInMB': null value is replaced with '10'
AI: TRACE 30-11-2015 00:08, 19: C:\Users\"username"\AppData\Local\Temp\AISDK\native\1.0.1 folder exists
AI: TRACE 30-11-2015 00:08, 19: Java process name is set to 'javaw'
AI: TRACE 30-11-2015 00:08, 19: Successfully loaded library 'applicationinsights-core-native-win64.dll'
AI: TRACE 30-11-2015 00:08, 19: Registering PC 'JSDK_ProcessMemoryPerformanceCounter'
AI: TRACE 30-11-2015 00:08, 19: Registering PC 'JSDK_ProcessCpuPerformanceCounter'
AI: TRACE 30-11-2015 00:08, 19: Registering PC 'JSDK_WindowsPerformanceCounterAsPC'
AI: INFO 30-11-2015 00:08, 19: Registered WebApp 'AppInsightWebApp' key='AppInsightWebApp'
AI: INFO 30-11-2015 00:08, 19: Successfully registered the filter 'ApplicationInsightsWebFilter'
11 30, 2015 12:08:29 午前 org.apache.coyote.AbstractProtocol start
情報: Starting ProtocolHandler ["http-nio-8080"]
11 30, 2015 12:08:29 午前 org.apache.coyote.AbstractProtocol start
情報: Starting ProtocolHandler ["ajp-nio-8009"]
11 30, 2015 12:08:29 午前 org.apache.catalina.startup.Catalina start
情報: Server startup in 2452 ms
AI: TRACE 30-11-2015 00:08, 32: InProcessTelemetryChannel sending telemetry

有効化する - ファイル出力編

AppInsights Java SDKソースコードを確認すると SDKLoggerXmlElement にて JAXB を利用して拡張機能が実装されていることが分かる。
InternalLogger を確認すると CONSOLE 以外にも FILE が存在するので、さっそく試すと以下のエラーが出力された。

AI: INFO 30-11-2015 00:14, 19: Registering WebApp with name 'AppInsightWebApp'
AI: INFO 30-11-2015 00:14, 19: Configuration file has been successfully found as resource
AI: SDK Internal Logger internal error while initializing 'FILE': 'Unique log file prefix is not defined'.

上記から prefix の文字を含めて設定する必要があるらしいことが分かる。SDKLoggerXmlElement.java を確認すると設定項目があるので、以下を設定する。

	<SDKLogger type="FILE">
		<UniquePrefix>AppInsightWebApp</UniquePrefix>
	</SDKLogger>

無事アプリケーションが起動すると %TEMP%\javasdklogs\AppInsightWebApp-2015-11-29-23-20-05-JavaSDKLog3742616972029564770.jsl としてファイルが作成された。
ソースコードを確認すると File.createTempFile( uniquePrefix + LOG_FILE_PREFIX, LOG_FILE_SUFFIX, baseFolder) としてファイルを作成していることが確認できる。