I successfully retrieved the exception logs in the Azure Function app under Invocations after updating the Program and FuncIntegrationDemo classes in the .NET 8 Isolated HTTP trigger function model.
**Program.cs :**
I added the following to the `Program.cs` file to enable `GlobalExceptionMiddleware` to catch exceptions globally, log them, and return standardized responses.
```csharp
services.AddSingleton<TelemetryClient>();
services.AddSingleton<IFunctionsWorkerMiddleware, GlobalExceptionMiddleware>();
services.AddScoped<ICMHCCRM, CMHCCRM>();
```
Below is the complete `Program` class.
```csharp
using FunctionApp14.Models;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Microsoft.ApplicationInsights;
using Microsoft.Azure.Functions.Worker.Middleware;
using FunctionApp14.Middleware;
var host = new HostBuilder()
.ConfigureFunctionsWebApplication()
.ConfigureAppConfiguration((context, config) =>
{
config.SetBasePath(Directory.GetCurrentDirectory())
.AddJsonFile("local.settings.json", optional: true, reloadOnChange: true)
.AddEnvironmentVariables();
})
.ConfigureServices((context, services) =>
{
services.AddApplicationInsightsTelemetryWorkerService();
services.AddSingleton<TelemetryClient>();
services.AddSingleton<IFunctionsWorkerMiddleware, GlobalExceptionMiddleware>();
services.AddScoped<ICMHCCRM, CMHCCRM>();
})
.Build();
host.Run();
```
**Functions/FuncIntegrationDemo.cs :**
I used the following code to get detailed exception information in the `FuncIntegrationDemo` class.
```csharp
_logger.LogError(ex, "Unhandled exception in FuncIntegrationDemo");
_logger.LogError($"Exception details: {ex}");
```
Below is the complete `FuncIntegrationDemo` class.
```csharp
using FunctionApp14.Models;
using Microsoft.Azure.Functions.Worker;
using Microsoft.Azure.Functions.Worker.Http;
using Microsoft.Extensions.Logging;
using System.Net;
namespace FunctionApp14
{
public class FuncIntegrationDemo
{
private readonly ILogger<FuncIntegrationDemo> _logger;
private readonly ICMHCCRM _crm;
public FuncIntegrationDemo(ICMHCCRM crm, ILogger<FuncIntegrationDemo> logger)
{
_crm = crm;
_logger = logger;
}
[Function("FuncIntegrationDemo")]
public async Task<HttpResponseData> Run([HttpTrigger(AuthorizationLevel.Function, "get", "post")] HttpRequestData req)
{
string logMessage = string.Empty;
_logger.LogInformation("C# HTTP trigger function processed a request.");
var SourceViewName = req.Query.GetValues("sourceViewName")?.FirstOrDefault();
if (string.IsNullOrEmpty(SourceViewName))
{
logMessage = "Please pass a Source view name on the query string";
_logger.LogInformation(logMessage);
var reqResponse = req.CreateResponse(HttpStatusCode.BadRequest);
await reqResponse.WriteStringAsync("Please pass a Source view name on the query string");
return reqResponse;
}
try
{
await _crm.MethodThrowingException(SourceViewName);
var response = req.CreateResponse(HttpStatusCode.OK);
await response.WriteStringAsync($"The record successfully synched with CRM !!!");
return response;
}
catch (Exception ex)
{
_logger.LogError(ex, "Unhandled exception in FuncIntegrationDemo");
_logger.LogError($"Exception details: {ex}");
var errorResponse = req.CreateResponse(HttpStatusCode.InternalServerError);
await errorResponse.WriteStringAsync("An unexpected error occurred. Please try again later.");
return errorResponse;
}
}
}
}
```
**Middleware/GlobalExceptionMiddleware.cs :**
```csharp
using Microsoft.ApplicationInsights;
using Microsoft.Azure.Functions.Worker.Middleware;
using Microsoft.Azure.Functions.Worker;
using Microsoft.Extensions.Logging;
namespace FunctionApp14.Middleware;
public class GlobalExceptionMiddleware : IFunctionsWorkerMiddleware
{
private readonly ILogger<GlobalExceptionMiddleware> _logger;
private readonly TelemetryClient _telemetryClient;
public GlobalExceptionMiddleware(ILogger<GlobalExceptionMiddleware> logger, TelemetryClient telemetryClient)
{
_logger = logger;
_telemetryClient = telemetryClient;
}
public async Task Invoke(FunctionContext context, FunctionExecutionDelegate next)
{
try
{
await next(context);
}
catch (Exception ex)
{
_logger.LogError(ex, "Unhandled exception occurred in function execution.");
var telemetryProperties = new Dictionary<string, string>
{
{ "FunctionName", context.FunctionDefinition.Name },
{ "InvocationId", context.InvocationId }
};
_telemetryClient.TrackException(ex, telemetryProperties);
throw;
}
}
}
```
**.csproj :**
```XML
<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="Microsoft.ApplicationInsights.WorkerService" Version="2.22.0" />
<PackageReference Include="Microsoft.Azure.Functions.Worker" Version="2.0.0" />
<PackageReference Include="Microsoft.Azure.Functions.Worker.Sdk" Version="2.0.0" />
<PackageReference Include="Microsoft.Azure.Functions.Worker.Extensions.Http.AspNetCore" Version="2.0.0" />
<PackageReference Include="Microsoft.Azure.Functions.Worker.ApplicationInsights" Version="2.0.0" />
<PackageReference Include="Microsoft.Azure.Functions.Worker.Extensions.Http" Version="3.2.0" />
<PackageReference Include="Microsoft.Identity.Client" Version="4.66.2" />
<PackageReference Include="Insight.Database" Version="8.0.1" />
<PackageReference Include="Xrm.Tools.CRMWebAPI" Version="1.0.25" />
</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>
```
**Azure Function App Invocations :**
I successfully retrieved the exception logs in the Azure function app under Invocations.
![enter image description here](https://i.imgur.com/34VTh36.png)
This worked for me.
My `connectionstring` is
``` C#
"Server=tcp:<servername>.database.windows.net,1433;Initial Catalog=<databasename>;Encrypt=True;TrustServerCertificate=False;Connection Timeout=30;Authentication=Active Directory Managed Identity";
```
For reference check this [document](https://learn.microsoft.com/en-us/sql/connect/ado-net/sqlclient-troubleshooting-guide?view=sql-server-ver16#login-phase-errors).
> **Note :-**
> - Make sure your Ip address is allowed for connection
> - Make sure you are using latest version of `EntityFramework` and `Microsoft.Data.SqlClient`.
> - Make sure you have assigned role correct managed identity.
> - Make sure you are using minimum TLS version 1.2
Enable Managed identity in Azure Function. One Enterprise application Service Principal will be created with your function name.
[![][1]][1]
Assign the role using the Query.
```
DECLARE @USERNAME nvarchar(128)
SET @USERNAME = 'my-system-assign-identity-name'
BEGIN
EXECUTE('CREATE USER "' + @USERNAME + '" FROM EXTERNAL PROVIDER');
EXECUTE('ALTER ROLE db_datareader ADD MEMBER "' + @USERNAME + '"');
EXECUTE('ALTER ROLE db_datawriter ADD MEMBER "' + @USERNAME + '"');
END
```
My code:
```csharp
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Azure.Functions.Worker;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Logging;
namespace FunctionApp3
{
public class Function
{
private readonly ILogger<Function> _logger;
private readonly MyDbContext _context;
public Function(ILogger<Function> logger, MyDbContext context)
{
_logger = logger;
_context = context;
}
[Function("Function")]
public async Task<IActionResult> Run([HttpTrigger(AuthorizationLevel.Anonymous, "get", "post")] HttpRequest req)
{
_logger.LogInformation("C# HTTP trigger function processed a request.");
var data = await _context.Test.ToListAsync();
// Process or log the fetched data
foreach (var item in data)
{
Console.WriteLine($"Id: {item.Id}, Name: {item.Name}");
}
return new OkObjectResult("Welcome to Azure Functions!");
}
}
public class MyDbContext : DbContext
{
public MyDbContext(DbContextOptions<MyDbContext> options) : base(options) { }
public DbSet<Test> Test { get; set; }
}
public class Test
{
public int Id { get; set; }
public string Name { get; set; }
}
}
```
**`Program.cs`:**
```csharp
using FunctionApp3;
using Microsoft.Azure.Functions.Worker;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
using Microsoft.EntityFrameworkCore;
var host = new HostBuilder()
.ConfigureFunctionsWebApplication()
.ConfigureServices(services =>
{
services.AddApplicationInsightsTelemetryWorkerService();
services.ConfigureFunctionsApplicationInsights();
services.AddDbContext<MyDbContext>(option =>
{
option.UseSqlServer("Server=tcp:<servername>.database.windows.net,1433;Initial Catalog=<databasename>;Encrypt=True;TrustServerCertificate=False;Connection Timeout=30;Authentication=Active Directory Managed Identity");
});
})
.ConfigureLogging(logging =>
{
logging.Services.Configure<LoggerFilterOptions>(options =>
{
LoggerFilterRule defaultRule = options.Rules.FirstOrDefault(rule => rule.ProviderName
== "Microsoft.Extensions.Logging.ApplicationInsights.ApplicationInsightsLoggerProvider");
if (defaultRule is not null)
{
options.Rules.Remove(defaultRule);
}
});
})
.Build();
host.Run();
```
**`.csproj`:**
```xml
<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="Microsoft.Azure.Functions.Worker" Version="1.20.1" />
<PackageReference Include="Microsoft.Azure.Functions.Worker.Extensions.Http" Version="3.1.0" />
<PackageReference Include="Microsoft.Azure.Functions.Worker.Extensions.Http.AspNetCore" Version="1.2.0" />
<PackageReference Include="Microsoft.Azure.Functions.Worker.Sdk" Version="1.16.4" />
<PackageReference Include="Microsoft.ApplicationInsights.WorkerService" Version="2.21.0" />
<PackageReference Include="Microsoft.Azure.Functions.Worker.ApplicationInsights" Version="1.1.0" />
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="8.0.4" />
<PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer" Version="8.0.4" />
</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>
```
### `Data`:
[![][2]][2]
### `OUTPUT`:
Log stream:
[![][3]][3]
**If you are still facing the same error, I would request to create support request with azure**
[1]: https://i.imgur.com/EHq0yIc.png
[2]: https://i.imgur.com/oFBMVqu.png
[3]: https://i.imgur.com/tqlfvMD.png