Azure Functions のログを Application Insights でモニターする(2018年夏版)

日頃、Azure Functionsを運用していると、何かとログを見る機会が多いのですが、ここ最近でAzure Functionsのログや監視周りがいろいろと新しくなっていて、仕事上でも各プロジェクトの現場で説明する機会が多くなったので、少しまとめておきたいと思います。

Azure Functionsのログ周りで、現時点(2018年夏)で特に気にしておくポイントは以下4点あたりかと思っています。

  • ビルトインの監視機能は使わない
  • ログはApplication Insightsに送信する
  • C#ではILoggerを使う
  • ログ周りの設定をhost.jsonに入れておく

これ以外のポイントについては、公式ドキュメントにいろいろ書かれています。

ログの出力先

ポータルでFunction Appを新規作成すると、ログの出力先にBlobストレージが含まれてしまいます。これを公式ドキュメントでは「ビルトイン監視機能」と呼んでいるようですが、本番環境などではこれを使い続けることは推奨されていないようです。なので、最初からApplication Insightsのみを利用するように変更するようにしています。

もし、Function Appのリソース作成時にApplication Insightsの利用をONにしている場合は、アプリケーション設定からAzureWebJobsDashboardの項目を削除するだけで、Blobストレージへの出力(ビルトイン監視機能)が停止されます。

リソース作成時にApplication Insightsを紐付けていない場合は、アプリケーション設定からAzureWebJobsDashboardを削除しつつ、APPINSIGHTS_INSTRUMENTATIONKEYを追加しキーをセットすればOKです。

こうすると、Azure FunctionsのポータルのFunctionのMonitorブレードでApplication Insightsのログをいい感じに表示してくれるようになります。

Function Appのモニター

エラーが発生した場合などログを分析する際も、いちいちApplication Insightsのブレードに移動しなくても詳細が確認出来ます。

Functionsモニターの詳細画面

ロガーの使い方

ILoggerを利用する

Visual StuidoのFunctions(C#)テンプレートから生成されるコードでは、ロガーとしてTraceWriterが組み込まれていますが、公式ドキュメントではILoggerを使うように推奨されているので、サクッとロガーを変更してしまいましょう。

[FunctionName("UsingILogger")]
public static void Run([QueueTrigger("il-items")] string item, ILogger log)
{
// output information log using ILogger
log.LogInformation("{item}によってFunctionが起動しました", item);
}

また、ILoggerを使うことで、構造化ログを出力できるようになります。構造化ログを出力するにはILoggerを以下のように書きます。

// Structured logging
const string key1 = "key1 value";
const string key2 = "value of key2";
log.LogInformation("key1のvalueは{key1}で, Key2のvalueは{key2}です", key1, key2);

構造化ログを出力すると、Application Insightsの中で独立したプロパティとして扱えるので、ログの検索やフィルタ等に便利です。

Application Insightsでの構造化ログ

カスタムな項目にはプレフィックスとしてprop__が付いてしまうのは仕様のようです。

エラーログとException

また、ILogggerLogError()を使ってエラーログを出力しただけだと、Application Insights側ではそれをException扱いにはしません。Application InsightsではFunctionレベルではなくHostレベルでのエラーをFunction全体の例外として扱うためです。

Monitorのアラート設定でException発生をトリガーにしてメール通知をする等のシナリオでは、HostレベルにExceptionを通知する必要があります。コードでは何らかのExceptionがThrowされるように実装します。
HostレベルでExceptionを起こせば、以下のようにFunctionの実行自体が「失敗」としてマークされ、Application Insightsでは例外として認識されます。

Application Insightsでの例外表示

host.jsonでの各種設定

ログ出力に関する各種設定はhost.jsonをカスタマイズすることで対応します。
何も書かなければデフォルトの設定が適用されます。設定できる項目とデフォルトについては以下の公式ドキュメントに記載されています。

ログレベル

ログレベルの制御はloggerプロパティの変更で各種項目を以下のレベルに設定可能です。

  • Trace
  • Debug
  • Information
  • Warning
  • Error
  • Critical
  • None
{
"logger": {
"categoryFilter": {
"defaultLevel": "Information",
"categoryLevels": {
"Host": "Error",
"Function": "Information",
"Host.Aggregator": "Information"
}
}
}
}

例えば上記のようにデフォルトをInfomationに設定しつつ、HostレベルのログのみをErrorに設定するようなことが可能です。ただし、HostError以上にしてしまうと、正常に実行された際のログがFunctionsのモニター画面やApplication Insightsに残らないので、実行数や成功時のログを記録したい場合はInfomationにしておく必要があります。

ログの集計間隔

Functionの実行数などをモニターしたい場合は、ログの集計間隔(アグリゲーター)をどう設定するかがポイントになります。デフォルトでは、30秒か1,000回実行のどちらか早い方で集計されるので、変更する場合は以下のようにhost.jsonを設定します。

{
"aggregator": {
"batchSize": 100,
"flushTimeout": "00:00:10"
}
}

host.jsonはFunctionレベルではなく、Function Appレベル全体に適用される点には注意しましょう。各Function毎に設定を変えたい場合は、Function App自体を別にする必要があります。

なお、今回のサンプルコードは以下のリポジトリに置いてあります。