C# — get data from Azure Log Analytics/Monitor

Michal Molka
3 min readNov 24, 2023

--

Everyone knows that we can query data from Log Analytics through Azure Portal. But not everyone knows that we can do the same stuff with a .NET app.

Here is an exemplary KQL code which is our base for this case.

CDBPartitionKeyRUConsumption 
| where DatabaseName == 'iowa_db'
| summarize RequestCharge = sum(RequestCharge) by OperationName, CollectionName, format_datetime(TimeGenerated, 'yyyy-MM-dd')
| project TimeGenerated, CollectionName, OperationName, RequestCharge
| order by TimeGenerated desc , CollectionName asc, OperationName asc, RequestCharge desc

And how it looks like at the Azure Portal.

When it comes to C# code, we need to prepare a query and get a proper credential in order to authenticate to Log Analytics. In this case we authorize the app through a Service Principal. Additionally, we need to use two libraries:

  • Azure.Monitor.Query,
  • Azure.Identity.
using Azure.Monitor.Query;
using Azure.Identity;
// AzureVariables... is a separate custom class where tenantId, clientId, clientSecret are saved as strings
// Create a credential to aunthenticate to Log Analytics, a Service Principal is used in this case
var credential = new ClientSecretCredential(AzureVariables.tenantId, AzureVariables.clientId, AzureVariables.clientSecret);
var logAnalyticsClient = new LogsQueryClient(credential);

string kqlQuery = """
CDBPartitionKeyRUConsumption
| where DatabaseName == 'iowa_db'
| summarize RequestCharge = sum(RequestCharge) by OperationName, CollectionName, format_datetime(TimeGenerated, 'yyyy-MM-dd')
| project TimeGenerated, CollectionName, OperationName, RequestCharge
| order by TimeGenerated desc , CollectionName asc, OperationName asc, RequestCharge desc
""";

In the first example we collect data into a built-in type — a single, integer column list. Useful if your result has only one column or record.

// Built-in type
Azure.Response<IReadOnlyList<int>> response = await logAnalyticsClient.QueryWorkspaceAsync<int>(
AzureVariables.logAnalyticsWorkspaceId,
"CDBControlPlaneRequests | summarize count()",
new QueryTimeRange(TimeSpan.FromDays(14)));

System.Console.WriteLine("Response value: {0}", response.Value.First());

More complicated structures can be handled in two ways. The first one is based on a class.

    public class RUConsumption
{
public string? TimeGenerated { get; set; }
public string? CollectionName { get; set; }
public string? OperationName { get; set; }
public long RequestCharge { get; set; }
}

...

// Response query at class object
Azure.Response<IReadOnlyList<RUConsumption>> response00 = await logAnalyticsClient.QueryWorkspaceAsync<RUConsumption>(
AzureVariables.logAnalyticsWorkspaceId,
kqlQuery,
new QueryTimeRange(TimeSpan.FromDays(7)));

foreach (var item1 in response00.Value)
{
System.Console.WriteLine(
$@"Date: {item1.TimeGenerated.ToString()}, Container: {item1.CollectionName}, Operation: {item1.OperationName}, RU: {item1.RequestCharge}");
}

And the second one is a table object which provides more elasticity. You don’t need to declare any model.

Azure.Response<LogsQueryResult> response02 = await logAnalyticsClient.QueryWorkspaceAsync(
AzureVariables.logAnalyticsWorkspaceId,
kqlQuery,
new QueryTimeRange(TimeSpan.FromDays(7)));

LogsTable table = response02.Value.Table;

foreach (var row in table.Rows)
{
Console.WriteLine(row["TimeGenerated"] + " " + row["CollectionName"] + " " + row["OperationName"] + " " + row["RequestCharge"]);
}

Here is the code: GitHub

The next article shows how to ingest logs into Azure Monitor: C# — Ingest custom logs into Azure Log Analytics | by Michal Molka | Dec, 2023 | Medium

--

--

Michal Molka
Michal Molka

Written by Michal Molka

Architect | Azure | Power BI | Fabric | Power Platform | Infrastructure | Security | M365

No responses yet