WebpackでApplication Insightのコードを埋め込む。

Microsoft Azureが提供するサービスの1つにApplication Insightsがある。 これはアプリケーションのメトリクスを収集、集計するための機能を提供してくれるサービスで、お手軽に導入できて便利なのでよく使っている。

公式ドキュメントでは、HTMLにコードを埋め込む方法を書いているが、JavaScriptなどをWebpackで一元管理したい場合については触れられていない。 ということで、そのやり方を調べてみた。

目次

HTMLにタグを埋め込む方法

公式ドキュメントで紹介されている方法だと、ウェブページの情報を取得するには、下記のコードをHTMLのヘッダー部に埋め込むだけでできる。

<script type="text/javascript">
var appInsights=window.appInsights||function(a){
  function b(a){c[a]=function(){var b=arguments;c.queue.push(function(){c[a].apply(c,b)})}}var c={config:a},d=document,e=window;setTimeout(function(){var b=d.createElement("script");b.src=a.url||"https://az416426.vo.msecnd.net/scripts/a/ai.0.js",d.getElementsByTagName("script")[0].parentNode.appendChild(b)});try{c.cookie=d.cookie}catch(a){}c.queue=[];for(var f=["Event","Exception","Metric","PageView","Trace","Dependency"];f.length;)b("track"+f.pop());if(b("setAuthenticatedUserContext"),b("clearAuthenticatedUserContext"),b("startTrackEvent"),b("stopTrackEvent"),b("startTrackPage"),b("stopTrackPage"),b("flush"),!a.disableExceptionTracking){f="onerror",b("_"+f);var g=e[f];e[f]=function(a,b,d,e,h){var i=g&&g(a,b,d,e,h);return!0!==i&&c["_"+f](a,b,d,e,h),i}}return c
  }({
      instrumentationKey:"<your instrumentation key>"
  });
  
window.appInsights=appInsights,appInsights.queue&&0===appInsights.queue.length&&appInsights.trackPageView();
</script>

Azure Application Insights for JavaScript web apps | Microsoft Docs

Webpack で埋め込む方法

Application Insights のJavaScript SDKがあるので、それを使う。

もちろん、Webpackでなくても出来るのだけれど、とりあえず今自分が使っているのがWebpackなので、それでやってみた。

パッケージのインストール

npm(もしくはyarn)を使って、依存に追加する。

npm install -D applicationinsights-js

Application Insightsを埋め込む

Application Insightsは、ブラウザ上で発生した例外も拾って収集してくれる。 そのためには、 他のJSライブラリが読み込まれるタイミングよりも先にApplication Insightsが有効になる必要がある

なので、WebpackのエントリーポイントになっているJSファイルのなるべく先頭に下記のコードを追加する。

import { AppInsights } from 'applicationinsights-js'

AppInsights.downloadAndSetup({ instrumentationKey: INSTRUMENTATION_KEY });
AppInsights.trackPageView()

上記のINSTRUMENTATION_KEYは、実際に発行したキーの値に置き換える。 ソースを読むとわかるのだけど、実際にdownloadAndSetupがやっているのは、上で紹介したHTMLにタグを埋め込む方法と同じことをやっている*1

リリースの時だけ埋め込むようにする

開発時にはデータを収集しない、またはしたくない場合がある。 そういう時は、環境変数などでビルド時に埋め込むかどうか判断させるなどの対応が必要になる。 例えば、INSTRUMENTATION_KEYが存在している時だけに埋め込むようにしようとした場合にだけ埋め込むようにする。そのために、ここではWebpackのDefinePluginを使う。

まず、INSTRUMENTATION_KEYを実際の値と置き換えるために、Webpackの設定にDefinePluginを有効にする。

plugins: [
  new webpack.DefinePlugin({
    INSTRUMENTATION_KEY: JSON.stringify(process.env.INSTRUMENTATION_KEY)
  })
]

また、先のエントリーポイントのコードも下記のようにして、INSTRUMENTATION_KEYがある時のみに読み込まれるようにする。

import { AppInsights } from 'applicationinsights-js'

if (INSTRUMENTATION_KEY) {
  AppInsights.downloadAndSetup({ instrumentationKey: INSTRUMENTATION_KEY });
  AppInsights.trackPageView()
}

こうすることで、WebpackがビルドするJavaScript内のINSTRUMENTATION_KEYがビルド時に環境変数INSTRUMENTATION_KEYで渡した値に置き換えられる。つまり、

INSTRUMENTATION_KEY=******* npx webpack

としてビルドした時のみにApplication Insightsのコードが埋め込まれるようになる。

実際にVue.jsのアプリケーションに組み込んでみたものが下記のプルリクエストなので、参考になれば。

github.com

*1:なぜ頑なに動的に埋め込もうとするのかはわかってない。