Azure Functionsの実行時に、そのログをApplication Insightsにデータを送る


概要

AzureにはAzure FunctionsというAWS Lambdaのようなサービスがあります。
Azure FunctionsはLambdaと同じく、一定時間毎やあるWebHookが呼ばれた際など、なんらかのイベントが発生したときに、サーバー上にあるC#やJavaScript(NodeJS)のコードが実行されるというものです。

その際、Functions自体の動作ログをApplication Insightsに送信しておき、Application Insights上で見られたら良いなと思ったので、その方法を調べました。

上手く送信出来るようになると、下図のようにApplication Insightsでログが見られるようになります。

下準備

FunctionsでApplication Insightsライブラリを使えるようにする

まずは、Azure FunctionsでApplication Insightsのライブラリを読み込めるようにします。
wwwroot以下に対象Function名の付いたフォルダがあります。そのフォルダ内にproject.jsonを作成し、次のような内容を書いておきます。project.jsonを保存すると、勝手にライブラリがNuGetからダウンロードされ、当該Functionで利用可能になります。
今のところ、Azure Portal上ではproject.jsonを作成できないので、ここだけはKuduを利用したり、Visual Studio経由でアップロードするなどの手間がかかります。

{
  "frameworks": {
    "net46": {
      "dependencies": {
        "Microsoft.ApplicationInsights": "2.1.0"
      }
    }
  }
}

Application InsightsのINSTRUMENTATIONKEYをFunctionsから参照出来るようにする

Azure FunctionsのApp Service Settingsを開き、『アプリケーション設定』の項目でAPPINSIGHTS_INSTRUMENTATIONKEYというキーを作成し、値にはApplication InsightsのINSTRUMENTATIONKEYを設定します。

ここで設定したキーはEnvironment.GetEnvironmentVariable("APPINSIGHTS_INSTRUMENTATIONKEY")というコードで参照出来ます。

実際にFunctionsのコードから利用する

実際のコードは次のような形です。
ポイントとして、TelemetryClientContext.Operation.Idに、当該FunctionのInvocationId(呼び出しID)を設定しています。
このInvocationIdはFunctionが呼び出される度にユニークな値となるので、どの呼び出しに関するテレメトリかを後から追跡しやすくなります。Application Insightsも、Operation.Id毎にテレメトリをグルーピングしてくれます。

using System;
using System.Diagnostics;
using System.Linq;
using Microsoft.ApplicationInsights;
using Microsoft.ApplicationInsights.DataContracts;

public static void Run(TimerInfo myTimer, TraceWriter log, ExecutionContext executionContext)
{
    var stopwatch = new Stopwatch();
    stopwatch.Start();
    var processStartTime = DateTimeOffset.UtcNow;
    var functionSucceed = true;

    var telemetryClient = new TelemetryClient { InstrumentationKey = Environment.GetEnvironmentVariable("APPINSIGHTS_INSTRUMENTATIONKEY") };
    telemetryClient.Context.Operation.Id = executionContext.InvocationId.ToString();
    telemetryClient.TrackTrace(
                message: "The function has started",
                severityLevel: SeverityLevel.Information,
                properties: new Dictionary<string, string>() {
                    { "somePropertyName", "somePropertyValue"},
                });
    try
    {
        //Functionsで行う処理などを書く
        //適宜telemetryClient.TrackTrace()やtelemetryClient.TrackMetric()などを呼び出してもよい。
    }
    catch (Exception e)
    {
        functionSucceed = false;
        telemetryClient.TrackException(
            exception: e,
            properties: new Dictionary<string, string>() {
                    { "somePropertyName", "somePropertyValue"},
                });
    }
    finally
    {
        stopwatch.Stop();

        telemetryClient.TrackRequest(
            new RequestTelemetry(
                name: "何かわかりやすい名前。このAzureFunctionの名前など設定すること",
                startTime: processStartTime,
                duration: sw.Elapsed,
                responseCode: "",
                success: functionSucceed));
    }
    telemetryClient.Flush();

}

参考にしたサイト