1

I am trying to integrate Azure App Insights with an Azure Function App (HttpTriggered). I want to add my own keys and values in the "customDimensions" object of the requests table. Right now it only shows the following:

On query

requests
| where iKey == "449470fb-****" and id == "5e17e23e-****" 

I get this:

LogLevel: Information
Category: Host.Results
FullName: Functions.FTAID
StartTime: 2017-07-14T14:24:10.9410000Z
param__context: ****
HttpMethod: POST
param__req: Method: POST, Uri: ****
Succeeded: True
TriggerReason: This function was programmatically called via the host APIs.
EndTime: 2017-07-14T14:24:11.6080000Z

I want to add more key values such as:

EnvironmentName: Development
ServiceLine: Business

Based on this answer, I implemented the ITelemetryInitializer interface as follows:

public class CustomTelemetry : ITelemetryInitializer
{
    public void Initialize(ITelemetry telemetry)
    {
        var requestTelemetry = telemetry as RequestTelemetry;
        if (requestTelemetry == null) return;
        requestTelemetry.Context.Properties.Add("EnvironmentName", "Development");

    }
}

Here is how the run.csx code for the Azure Function App looks like:

public static async Task<HttpResponseMessage> Run(HttpRequestMessage req, ExecutionContext context, TraceWriter log)
{
    // Initialize the App Insights Telemetry
    TelemetryConfiguration.Active.InstrumentationKey = System.Environment.GetEnvironmentVariable("APPINSIGHTS_INSTRUMENTATIONKEY", EnvironmentVariableTarget.Process);
    TelemetryConfiguration.Active.TelemetryInitializers.Add(new CustomTelemetry());
    TelemetryClient telemetry = new TelemetryClient();

    var jsonBody = await req.Content.ReadAsStringAsync();
    GetIoItemID obj = new GetIoItemID();
    JArray output = obj.GetResponseJson(jsonBody, log, telemetry);

    var response = req.CreateResponse(HttpStatusCode.OK);
    response.Content = new StringContent(output.ToString(), System.Text.Encoding.UTF8, "application/json");
    return response;
}

But this did not work...

John Gardner
  • 24,225
  • 5
  • 58
  • 76
Pranshu Gupta
  • 634
  • 9
  • 13

1 Answers1

0

I believe, since you're creating the TelemetryClient yourself in this example, you don't need to bother with the telemetry initializer, you could just do

var telemetry = new TelemetryClient();
telemetry.Context.Properties["EnvironmentName"] = "Development";

directly, and everything sent by that instance of that telemetry client will have those properties set.

You'd need that telemetry initializer if you don't have control over who's creating the telemetry client and want to touch every item of telemetry created wherever?

I don't know how that TelemetryClient instance gets used downstream in azure functions though, so i'm not entirely positive, though.

Edit: from azure functions post about this, it says:

We’ll be working hard to get Application Insights ready for production workloads. We’re also listening for any feedback you have. Please file it on our GitHub. We’ll be adding some new features like better sampling controls and automatic dependency tracking soon. We hope you’ll give it a try and start to gain more insight into how your Functions are behaving. You can read more about how it works at https://aka.ms/func-ai

and the example from that func-ai link has a couple things:

1) it creates the telemetry client statically up front once (instead of in each call to the function)

private static TelemetryClient telemetry = new TelemetryClient();
private static string key = TelemetryConfiguration.Active.InstrumentationKey = System.Environment.GetEnvironmentVariable("APPINSIGHTS_INSTRUMENTATIONKEY", EnvironmentVariableTarget.Process);

and inside the function it is doing:

telemetry.Context.Operation.Id = context.InvocationId.ToString();

to properly do correlation with events you might create with your telemetry client so you might want to do that too.

2) it appears that the telemetry client you create you can use, but they create their own telemetry client and send data there, so anything you touch in your telemetry client's context isn't seen by azure functions itself.

so, to me that leads me to something you can try:

add a static constructor in your class, and in that static constructor, do the telemetry initializer thing you were doing above. possibly this gets your telemetry initializer added to the context before azure functions starts creating its request and calling your method?

If that doesn't work, you might need to post on their GitHub or email the person listed in the article for more details on how to do this?

John Gardner
  • 24,225
  • 5
  • 58
  • 76