Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Intercept Azure Function Host Shutdown: Flush Application Insights TelemetryClient

I am playing a little bit with Azure Function: Mostly I try to migrate an existing webjob to Azure Functions and now it is time for me to integrate Application Insights in one of my function.

So basically I only need one instance of the TelemetryClient but this assumes that I am able to flush the in-memory buffer when the application stops.

I've used a TimerTrigger but it was just for testing purpose.

I've referenced the Microsoft.ApplicationInsights nuget package (from this SO post) and my run.csx file looks like that:

using System;
using Microsoft.ApplicationInsights;
using Microsoft.Azure.WebJobs;

public static void Run(TimerInfo myTimer, TraceWriter log)
{
    MyTimerJob.TelemetryClient.TrackEvent("AzureFunctionTriggered");
    log.Verbose($"C# Timer trigger function executed at: {DateTime.Now}");
}    

public static class MyTimerJob
{
    public static readonly TelemetryClient TelemetryClient;

    static MyTimerJob(){
        TelemetryClient = new TelemetryClient()
            { InstrumentationKey = "MyInstrumentationKey" };

        // When it shutdowns, we flush the telemty client.
        new WebJobsShutdownWatcher().Token.Register(() =>
        {
            TelemetryClient.TrackEvent("TelemetryClientFlush");
            TelemetryClient.Flush();
        });
    }
}

This implementation is a bit tricky...

  • I have a static TelemetryClient to ensure that I am going to reuse the same instance.
  • I tried using the WebJobsShutdownWatcher to detect when the host is stopping so that I can flush the TelemetryClient.

To simulate the application shutdown, I've created a "test" app setting in the underlying web app and I modify it when I want the host to restart:

Azure Function - Application terminated log

Unfortunately this does not work... I did not see any event with name "TelemetryClientFlush" from the app insights dashboard:

Microsoft Application Insights - Custom Events dashboard

So I am now wondering if there is any way to intercept when the azure function host is stopping ?

like image 478
Thomas Avatar asked Apr 21 '16 05:04

Thomas


People also ask

How does Azure function connect to application insights?

In your function app, select Configuration under Settings, and then select Application settings. If you see a setting named APPINSIGHTS_INSTRUMENTATIONKEY , Application Insights integration is enabled for your function app running in Azure.


2 Answers

In addition to what Mathew described, you may want to play around with the cancellation token we'll pass if requested.

If you add a CancellationToken type argument to your function, we'll pass in a token that will be signaled when the host shuts down under normal circumstances. Using that may get you close to what you need:

using System;
using System.Threading;
using Microsoft.ApplicationInsights;

public static readonly TelemetryClient TelemetryClient = new  TelemetryClient(){ InstrumentationKey = "MyInstrumentationKey" };
public static bool first = true;
public static void Run(TimerInfo myTimer, TraceWriter log, CancellationToken token)
{
    if(first){
        token.Register(() =>
        {
            TelemetryClient.TrackEvent("TelemetryClientFlush");
            TelemetryClient.Flush();
        });
        first = false;
    }

    TelemetryClient.TrackEvent("AzureFunctionTriggered");
    log.Verbose($"C# Timer trigger function executed at: {DateTime.Now}");
}
like image 86
Fabio Cavalcante Avatar answered Oct 31 '22 12:10

Fabio Cavalcante


While Azure Functions does run on top of the WebJobs SDK, it does not run under the traditional Kudu WebJobs infrastructure. The WebJobsShutdownWatcher actually relies on functionality of the Kudu host, specifically the sentinel file indicated by WEBJOBS_SHUTDOWN_FILE. Basically when the Kudu host is shutting down it touches this file which the watcher is monitoring. Since no such file is being touched, your code is not being triggered.

We could make changes to allow the watcher to work as is, or we might instead introduce a new pattern for Functions. I've logged an issue in our repo here tracking this suggestion. I think the scenario is important and we'll give it some thought.

like image 26
mathewc Avatar answered Oct 31 '22 11:10

mathewc