我们将 Azure 进程内函数迁移到 .NET 8 中的独立函数。 添加了以下nuget包
<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>
下面是我的HTTP触发函数,它调用一个名为“MethodThrowingException”的方法进行测试并抛出异常。
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Azure.Functions.Worker;
using Microsoft.Azure.Functions.Worker.Http;
using Microsoft.Extensions.Logging;
using System.Net;
namespace CTSCRMIntegration
{
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.");
//Parse SourceViewName Parameter
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;
}
//Check for record exists in CRM
await _crm.MethodThrowingException(SourceViewName);
var response = req.CreateResponse(HttpStatusCode.OK);
await response.WriteStringAsync($"The record successfully synched with CRM !!!");
return response;
}
}
}
调用以下方法抛出异常
public class CMHCCRM : ICMHCCRM
{
private readonly CRMWebAPIFactory _webApiFactory;
public async Task MethodThrowingException(string sourceViewName)
{
throw new NotImplementedException("The method is not implemented to check the invocation list for blank error message");
}
}
我们在 Program.cs 文件中添加了配置设置,以启用函数应用程序的应用程序设置。我们删除了应用程序设置的默认行为。代码如下:
using Microsoft.Azure.Functions.Worker;
using Microsoft.Azure.Functions.Worker.Builder;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
var host = new HostBuilder()
.ConfigureFunctionsWebApplication().
ConfigureAppConfiguration(app => {
app.SetBasePath(Directory.GetCurrentDirectory())
.AddJsonFile("local.settings.json", optional: true, reloadOnChange: true)
.AddEnvironmentVariables();
})
.ConfigureServices((context, services) => {
services.AddApplicationInsightsTelemetryWorkerService();
services.ConfigureFunctionsApplicationInsights();
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);
}
});
services.AddScoped<ICMHCCRM, CMHCCRM>(x => new CMHCCRM());
}).Build();
host.Run()
这是host.json文件
{
"version": "2.0"
}
我们在函数应用程序中使用 ILogger 来记录错误。我们没有使用 try-catch 块来处理异常。当发生任何未处理的异常时,调用列表不显示详细消息,仅显示空白消息
如果我在 Application Insight 中单击“运行查询”,查询结果将返回空白行。
但是如果我们在异常表上运行查询,异常消息会显示在outerMessage字段中
更新 .NET 8 隔离 HTTP 触发器函数模型中的 Program 和 FuncIntegrationDemo 类后,我成功检索了 Azure Function 应用程序中“调用”下的异常日志。
程序.cs:
我将以下内容添加到
Program.cs
文件中,以使 GlobalExceptionMiddleware
能够全局捕获异常、记录它们并返回标准化响应。
services.AddSingleton<TelemetryClient>();
services.AddSingleton<IFunctionsWorkerMiddleware, GlobalExceptionMiddleware>();
services.AddScoped<ICMHCCRM, CMHCCRM>();
以下是完整的
Program
课程。
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();
函数/FuncIntegrationDemo.cs:
我使用以下代码在
FuncIntegrationDemo
类中获取详细的异常信息。
_logger.LogError(ex, "Unhandled exception in FuncIntegrationDemo");
_logger.LogError($"Exception details: {ex}");
以下是完整的
FuncIntegrationDemo
课程。
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;
}
}
}
}
中间件/GlobalExceptionMiddleware.cs:
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:
<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 函数应用程序调用:
我成功检索了 Azure 函数应用程序中“调用”下的异常日志。