フロントエンド(Angular)にAzure Application Insightsを入れてページビューを計測してみた

Angularって何?

Angular Docs

Angularは、Googleオープンソースコミュニティで開発されているJavaScriptフレームワークです。 AngularJSと呼ばれていたバージョン1(AngularJS 1)から、バージョン2で大きく変更されて、以降はAngularと呼ばれています。 バージョン2時点では「Angular 2」と呼ばれることもありましたが、現在はAngularが正式名称です。
JavaScriptフレームワーク「Angular」新バージョン4の変更点と今後の展望 (1/3):CodeZine(コードジン) より引用。

会社のとあるチームの人たちが使ってるんだけど、最近モニタリングに取り組み始めて、Applicaiton Insightsを使ってる。
個人的にもやらないとなーと思いつつ、手がつけられてなかったので、ちょうどいい機会だからのっかった感じ。

導入方法

手頃なアプリがなかったので、GitHubにあったSpring Frameworkのサンプルアプリpetclinicを使い、Add Application Insights to an Angular SPA – Premier Developer を見ながら導入した。

petclinicはSpring Framework定番のサンプルアプリっぽい。コミュニティで色んな派生アプリを作っている模様。

github.com

マイクロサービス版もある!! Kubernetes + Istioの練習するときに使ってみよう :D

コード

GitHubに置いてみた。

github.com

変更点はここで確認できる。

Comparing spring-petclinic:master...nobiinu-and:monitoring-owner-list · spring-petclinic/spring-petclinic-angular · GitHub

試行錯誤したところ

  • webpackをインストールした
  • logPageViewの引数を指定した
  • Application InsightsのInstrumentation Keyを外出しした

webpackをインストールした

基本、インストールはREADMEの手順に沿って行う。
最後の ng serve でエラーが起きた(メモ忘れたので詳細がわからん)ので、npm install --save-dev webpack をして、webpackをインストールして解決。

logPageViewの引数を指定した

logPageViewはtrackPageViewをラッパーしたもの。
引数を指定しない場合、Application Insightsはページ名にWindowのタイトルを利用する。
サンプルアプリはページごとにWindowのタイトルが変わらないので、コンポーネントの名前を入れてみることにした。
コンポーネント(クラス)の名前は this.constructor.name で指定できる。

Application InsightsのInstrumentation Keyを外出しした

KeyをGitHubで晒すのもなぁと思った(というか、晒してたので慌てて削除した)ので、 Angular 4 で Connection String や Secret を Environment Variables から取得する - Qiitaを参考に外出し。

残ってる課題

全ての画面を対象にする

Add Application Insights to an Angular SPA – Premier Developer にも書かれてるけど、記載されている方法だとコンポーネントごとにコードを記述する必要がある。
コンポーネントの基底クラスを作って、そっちで処理しろって書いてあるんだけど、なんか面倒。

以下のような感じで、ルーティングの NavigationStart イベントを使っても処理できるかもしれない?
(画面名がコンポーネント名の代わりにURLになっちゃうんだけども)

export class AppComponent {

  constructor(router: Router, private myMonitoringService: MyMonitoringService) {
    router.events
    .filter((event) => event instanceof NavigationStart)
    .subscribe((event: NavigationStart) => {
      this.myMonitoringService.logPageView(event.url);
    });
  }
}

一応実装してみた。動いてはいる模様。

Comparing monitoring-owner-list...monitoring-using-router-events · nobiinu-and/spring-petclinic-angular · GitHub

ただ、この方法だとルートガードでキャンセルされた場合(実際に画面遷移しなくても)計測してしまう。
キャンセルされた場合の話を考えるといろいろ難しくなりそうなので、これで置いとくことにする。(別途、キャンセルしたことを通知すればいい気も)

Durationで計測されているのはどの処理なのか?

画面の切り替えは1秒以内で行われているんだけど、Durationで計測されてる時間は2秒以上かかってた。
ちなみに、バックエンドからデータを取ってくる時間は含まれていない(バックエンドの処理に細工して、5秒sleepさせたけど、その時間は含まれなかった)。
処理時間は参考程度にしておくって手もあるんだけど、なんかモニャモニャする。

参考にしたページ