How to query Application Insights with C#

Update: the code example in this article uses an API that is now deprecated. It will only be useful if you are stuck using old NuGet library to query Application Insights. For new code, you should use https://www.nuget.org/packages/Azure.Monitor.Query/ instead. This article does not provide code example on how to use that newer API.

Application Insights is a great tool for monitoring solutions deployed to Azure.

A user-friendly interface for Application Insights can be found in Azure Portal, and often it’s what we need. However, occasionally, we might want to automate some process that requires access to logs, and we want to query Application Insights from .NET code.

I needed it a few times, and could never easily find a code sample in Google, so I publish my blog post to have such code snippet easily available.

Prerequisites

The code requires installing the Microsoft.Azure.ApplicationInsights.Query package in your project.
You also need to generate a secret key to authenticate to Application Insights API.

Querying Application Insights via API from C#

public async Task GetMostRecentFailedRequests()
{
    // You can generate key in Azure Portal, in Application Insights' "API Access" pane
    string applicationId = "c22a7f19-b6...[censored]";
    string key = "24io8jb...[censored]";
    
    // Create client
    var credentials = new ApiKeyClientCredentials(key);
    var applicationInsightsClient = new ApplicationInsightsDataClient(credentials);

    // Query Application Insights
    var query = $"requests" +
                $" | where timestamp > ago(24h)" +
                $" | where success == false" +
                $" | order by timestamp desc" +
                $" | project timestamp, url, resultCode" +
                $" | take 3";
    var response = await applicationInsightsClient.Query.ExecuteWithHttpMessagesAsync(applicationId, query);
    
    // Parse result 
    if (response.Response.IsSuccessStatusCode)
    {
        foreach (var row in response.Body.Results)
        {
            Console.WriteLine($"[{row["timestamp"]:s}][{row["resultCode"]}] Failed request to: {row["url"]}");
        }
    }
}Code language: C# (cs)

// example output of the above function in console window
[2021-10-03T11:54:16][404] Failed request to: http://generatordiety.pl/apple-touch-icon.png
[2021-10-03T11:05:32][404] Failed request to: http://generatordiety.pl/.env
[2021-10-03T11:05:31][404] Failed request to: http://generatordiety.pl/.envCode language: Access log (accesslog)

Bonus: how to convert DateTimeOffset to a date understood by Kusto

I found DateTimeOffset parameter to be quite often useful in queries. Here is a snippet for this specific type’s conversion that will nicely preserve time zone information:

DateTimeOffset lastMidnight = DateTimeOffset.UtcNow.Date;
string query = $"(...) | where timestamp > todatetime(\"{lastMidnight:O}\")";
// The "O" or "o" standard format specifier represents a custom date and time format string using a pattern
// that preserves time zone information and emits a result string that complies with ISO 8601. Code language: C# (cs)

And that’s all here, it should be a good place to start.

7 thoughts on “How to query Application Insights with C#”

    • Hi Mani. I believe it’s not possible to authenticate using Instrumentation Key because it is not considered a secret. For example, in JavaScript applications using Application Insights SDK there is no way to hide the Instrumentation Key from people using the website. In backend applications, it would be easier to keep it secret, but the Instrumentation Key is still not meant for authentication.

      Reply
  1. What about the URI for the Application Insight? Shouldn’t that be passed as well?

    Also, the key (APP Key I suppose) can it be used for PROD env?

    Reply
    • The code sample is for a now-deprecated library `Microsoft.Azure.ApplicationInsights.Query`. I believe that at this time, there was just one, global Application Insights endpoint hard-coded into the SDK and developers didn’t have to provide any URL. This might be different in the newer SDK, `Azure.Monitor.Query`, but I haven’t used that one so far.

      As for the production environment, I cannot see a reason why this approach couldn’t be used. We just need to keep the secret key secret 🙂

      Reply
  2. Hi,

    When i try to call query 2 times, it remains awaiting a response in second time, but if i call directly the second query it return the expected results.
    Is like i cant call 2 times for 2 different queries.

    Any thought?

    Thanks

    Reply

Leave a Comment