Hi @Maxime Callebaut ,
I am able to get the table using below code In Azure Function App after deployment:
Program.cs:
using Azure.Identity;
using Azure.Monitor.Query;
using Azure.Monitor.Query.Models;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
using System.Text.Json;
var rith = Host.CreateDefaultBuilder()
.ConfigureFunctionsWebApplication()
.ConfigureAppConfiguration((context, config) =>
{
config.SetBasePath(context.HostingEnvironment.ContentRootPath)
.AddJsonFile("local.settings.json", optional: true, reloadOnChange: true)
.AddEnvironmentVariables();
})
.ConfigureServices(services =>
{
services.AddLogging();
services.AddSingleton<LogAnalyticsSettings>(provider =>
{
var json = Environment.GetEnvironmentVariable("LogAnalyticsConfig");
if (string.IsNullOrWhiteSpace(json))
{
throw new InvalidOperationException("Missing LogAnalyticsConfig environment variable.");
}
return JsonSerializer.Deserialize<LogAnalyticsSettings>(json)
?? throw new InvalidOperationException("Invalid LogAnalyticsConfig JSON.");
});
var credential = new DefaultAzureCredential();
services.AddSingleton(new LogsQueryClient(credential));
services.AddSingleton<ILogAnalyticsService, LogAnalyticsService>();
services.AddSingleton<IDatabaseService, DatabaseService>();
})
.Build();
rith.Run();
public interface ILogAnalyticsService
{
Task<LogsQueryResult> QueryLogsAsync(string kql, DateTimeOffset startTime, DateTimeOffset endTime);
}
public interface IDatabaseService
{
}
public class LogAnalyticsSettings
{
public string WorkspaceId { get; set; } = string.Empty;
}
public class LogAnalyticsService : ILogAnalyticsService
{
private readonly LogsQueryClient _queryClient;
private readonly LogAnalyticsSettings _settings;
private readonly ILogger<LogAnalyticsService> _logger;
public LogAnalyticsService(LogsQueryClient queryClient, LogAnalyticsSettings settings, ILogger<LogAnalyticsService> logger)
{
_queryClient = queryClient;
_settings = settings;
_logger = logger;
}
public async Task<LogsQueryResult> QueryLogsAsync(string kql, DateTimeOffset startTime, DateTimeOffset endTime)
{
var timeRange = new QueryTimeRange(startTime, endTime);
_logger.LogInformation("Running KQL: {Kql} from {StartTime} to {EndTime}", kql, startTime, endTime);
return await _queryClient.QueryWorkspaceAsync(_settings.WorkspaceId, kql, timeRange);
}
}
public class DatabaseService : IDatabaseService
{
}
Function.cs:
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Azure.Functions.Worker;
using Microsoft.Extensions.Logging;
namespace FunctionApp15
{
public class Function1
{
private readonly ILogger<Function1> ri_lg;
private readonly ILogAnalyticsService _logAnalyticsService;
public Function1(ILogger<Function1> logger, ILogAnalyticsService logAnalyticsService)
{
ri_lg = logger;
_logAnalyticsService = logAnalyticsService;
}
[Function("Function1")]
public async Task<IActionResult> Run(
[HttpTrigger(AuthorizationLevel.Function, "get", "post")] HttpRequest req)
{
ri_lg.LogInformation("Function1 triggered to query Log Analytics.");
string kql = "AppTraces | limit 10";
try
{
var result = await _logAnalyticsService.QueryLogsAsync(
kql,
DateTimeOffset.UtcNow.AddDays(-1),
DateTimeOffset.UtcNow);
\ var table = result.Table;
var rows = table.Rows.Select(row =>
{
var dict = new Dictionary<string, object>();
for (int i = 0; i < table.Columns.Count; i++)
{
dict[table.Columns[i].Name] = row[i];
}
return dict;
});
return new OkObjectResult(rows);
}
catch (Exception ex)
{
ri_lg.LogError(ex, "Failed to query Log Analytics.");
return new ObjectResult("Error querying logs.") { StatusCode = 500 };
}
}
}
}
csproj:
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
<AzureFunctionsVersion>v4</AzureFunctionsVersion>
<OutputType>Exe</OutputType>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>
<ItemGroup>
<FrameworkReference Include="Microsoft.AspNetCore.App" />
<PackageReference Include="Azure.Identity" Version="1.13.2" />
<PackageReference Include="Azure.Monitor.Query" Version="1.6.0" />
<PackageReference Include="Microsoft.Azure.Functions.Worker" Version="2.0.0" />
<PackageReference Include="Microsoft.Azure.Functions.Worker.Extensions.Http" Version="3.2.0" />
<PackageReference Include="Microsoft.Azure.Functions.Worker.Extensions.Http.AspNetCore" Version="2.0.0" />
<PackageReference Include="Microsoft.Azure.Functions.Worker.Sdk" Version="2.0.0" />
</ItemGroup>
<ItemGroup>
<None Update="host.json">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Update="local.settings.json">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
<CopyToPublishDirectory>Never</CopyToPublishDirectory>
</None>
</ItemGroup>
<ItemGroup>
<Using Include="System.Threading.ExecutionContext" Alias="ExecutionContext" />
</ItemGroup>
</Project>
After Deploying In Function App added the below environment variable in Settings Section in Environment variables as below:
{
"name": "LogAnalyticsConfig",
"value": "{\"WorkspaceId\": \"59ca9hhhhb583c79\"}",
"slotSetting": false
}
Then Enabled Managed Identity as below:
Then given Monitoring Contributor Role to the managed identity of the function app in Log analytics Workspace:
Output:
If this answer was helpful, please click "Accept the answer" and mark Yes
, as this can help other community members.
If you have any other questions or are still experiencing issues, feel free to ask in the "comments" section, and I'd be happy to help.