Azure Functions で実行時のIDを取得する

Azure Functionsを使ってるときに今実行されている状態のIDを使いたい場合があるかと思います。後で追跡する場合に呼び出されたIDとか関連付けされていると便利ですよね。

というわけで、呼び出しログ(Invocation Log)とかで使われるIDをコード内で使う方法です。

C#の場合

using System;

public static void Run(string input, ExecutionContext executionContext, TraceWriter log)
{
    log.Info($"InvocationId: {executionContext.InvocationId}");
}

C#の場合はExecutionContext型の引数を受け取るようにすればOKです。ExecutionContext型にはInvocationIdプロパティがあるのでそちらを参照します。ちなみに内部的にも同じ型でcontextという名前でバインディングされるので、contextという引数名にするとバインディングエラーになります。修正されるかもしれませんが。

JavaScriptの場合

module.exports = function (context, input) {
    context.log('Node.js manually triggered function called with input:', input);
    context.log(context.bindingData.InvocationId)
    context.done();
};

JavaScriptの場合はcontextのbindingDataにInvocationIdが生えてるのでそちらを使います。

実行結果はこんな感じで、呼び出しIDが取得できます。

2016-08-03T19:14:03.491 Function started (Id=f58733a5-d6ce-4035-8a42-c6b95b7d79b7)
2016-08-03T19:14:03.491 InvocationId: f58733a5-d6ce-4035-8a42-c6b95b7d79b7
2016-08-03T19:14:03.491 Function completed (Success, Id=f58733a5-d6ce-4035-8a42-c6b95b7d79b7)

Azure Functions で実行中にコンパイルするとどうなるの

裏でFunction Appが実行中のときにコンパイルして(コンパイルエラーになったりして)るときに実行中のものはどうなるのか、予想では別物なんで問題ないと思いますが一応。

検証用コード

using System.Net;

public static async Task<HttpResponseMessage> Run(HttpRequestMessage req, TraceWriter log)
{
    log.Info($"Start ----");
    // parse query parameter
    string name = req.GetQueryNameValuePairs()
        .FirstOrDefault(q => string.Compare(q.Key, "name", true) == 0)
        .Value;

    await Task.Delay(TimeSpan.FromSeconds(20));

    // Get request body
    dynamic data = await req.Content.ReadAsAsync<object>();

    // Set name to query string or body data
    name = name ?? data?.name;

   log.Info($"End ----------");
   return name == null
        ? req.CreateResponse(HttpStatusCode.BadRequest, "Please pass a name on the query string or in the request body")
        : req.CreateResponse(HttpStatusCode.OK, "Hello " + name);
}

HttpTriggerなC#のテンプレートにStartとEndのログと間にTask.Delayで処理止めてるだけのシンプルなやつです。
※ログにFunction Startedとか出るので無駄な気もするけど一応

手順的にはこんな感じ

1.  上記コードを実行する(適当に呼び出す)
2. Task.Delayしてる間にコードを適当に弄ってSaveしてコンパイルエラーにする
3. 結果を見る
4. そのまま再度呼び出す

実行結果はこんな感じになりました

2016-07-19T03:34:42.334 Function started (Id=14c91f2c-2490-437c-b461-258a13872d82)
2016-07-19T03:34:42.334 Start ----
2016-07-19T03:34:45.698 Script for function 'HttpTriggerCSharp1' changed. Reloading.
2016-07-19T03:34:45.698 Compiling function script.
2016-07-19T03:34:45.776 run.csx(14,13): error CS1002: ; expected
2016-07-19T03:34:45.776 run.csx(11,48): error CS0246: The type or namespace name 'aaaa' could not be found (are you missing a using directive or an assembly reference?)
2016-07-19T03:34:45.776 run.csx(14,13): error CS0103: The name 'data' does not exist in the current context
2016-07-19T03:34:45.776 run.csx(17,20): error CS0103: The name 'data' does not exist in the current context
2016-07-19T03:34:45.776 run.csx(14,5): warning CS0168: The variable 'dynamic' is declared but never used
2016-07-19T03:34:45.776 Compilation failed.
2016-07-19T03:35:02.334 End ----------
2016-07-19T03:35:02.334 Function completed (Success, Id=14c91f2c-2490-437c-b461-258a13872d82)
2016-07-19T03:35:27.915 Function compilation error
2016-07-19T03:35:27.915 run.csx(14,13): error CS1002: ; expected
2016-07-19T03:35:27.915 run.csx(11,48): error CS0246: The type or namespace name 'aaaa' could not be found (are you missing a using directive or an assembly reference?)
2016-07-19T03:35:27.915 run.csx(14,13): error CS0103: The name 'data' does not exist in the current context
2016-07-19T03:35:27.915 run.csx(17,20): error CS0103: The name 'data' does not exist in the current context
2016-07-19T03:35:27.915 run.csx(14,5): warning CS0168: The variable 'dynamic' is declared but never used
2016-07-19T03:35:27.915 Function completed (Failure)
2016-07-19T03:35:27.961 Exception while executing function: Functions.HttpTriggerCSharp1. Microsoft.Azure.WebJobs.Script: Script compilation failed.

StartとEndの間でコンパイル走ってエラーになってますが、Function Id=14c91f2c-2490-437c-b461-258a13872d82は継続して処理が完了してます。

その後再度呼び出してみるとコンパイルが完了してないので再度コンパイル→失敗→500エラーが返る、という感じです。

予想通りでしたね。なんかおかしい、という場合はぜひ追加の検証をお願いします。

Azure Functions / Overview and Under the hood

2016年12月5日更新

ちゃんと書いてなかった気がするのと、某所で喋ったのでスライドの中身を適当にコピペします。そのうち動画・スライドが公開される気もしますが。→ されました

※2016年12月5日現在の情報です。
※だらだら長くなってしまった…

続きを読む