c# - 如何使用依赖注入正确设置 Azure Functions 日志记录、实时指标和应用洞察
问题描述
大约一个月前,我注意到旧 Azure Functions 门户界面中的一些监视功能停止工作。我在Azure Functions Host GitHub上写了有关这些问题的更多详细信息,但我的特定问题尚未得到解答。
现在,Azure Functions 门户界面似乎默认为新的“管理体验”,看起来与 Azure 的其他部分更相似,因此,更明显的是,我们使用日志记录和跟踪的方式出现了问题。
我的问题是:是否有人有关于如何设置 Azure 函数日志记录、实时指标和应用程序洞察跟踪的代码示例,以便它:
- 使用依赖注入
- 与新的“管理体验”界面配合使用
目前,为了查看特定的 Azure Function 正在做什么,我必须转到旧的 Azure 界面并研究日志流。函数确实有效,它们在日志流中输出信息,但仅在旧界面中,并且在监控方面似乎没有太多其他工作。使用旧界面:
- 调用日志,当您按下“功能(只读)> [功能] > 监控”下的“监控”链接时获得的日志,即使根据日志肯定会调用这些函数,也根本没有显示任何调用。
- 实时应用指标链接会导致默认的“不可用:您的应用处于离线状态或使用较旧的 SDK”以及一些动画演示图表。
这些在一个月前工作得很好。现在,没有那么多。
使用新界面:
- 监控 > 日志流只显示“已连接!”一词,无论其详细程度如何。
- Monitoring > Log Stream > Open in Live Metrics 再次生成默认的“不可用:您的应用程序处于离线状态或使用较旧的 SDK”。
使用 Functions > Functions > [click on a function] 转到新界面中的特定功能:
- 开发人员 > 代码 + 测试 > 测试按钮 > 运行,弹出日志窗口,只显示“已连接!” 没有别的,不管冗长。
- Monitor > Invocations,这里没有注册调用跟踪,即使该函数显然是根据旧接口日志流调用的。
- Monitor > Logs,再次,只是说“已连接!”,不管冗长。
我不明白为什么它在一个月前突然停止工作,以及为什么这么多东西似乎不适用于新界面。我们的 Functions 的 NuGet 包都是最新的。
在日志记录方面,记录器是依赖注入的,因此我们可以在多个类中使用它,而不仅仅是在默认的 Functions.cs 类中:
using Microsoft.Extensions.Logging;
public class EventForwarder
{
private readonly ILogger<EventForwarder> log;
我们通过使用扩展方法记录,真的没什么特别的:
using Microsoft.Extensions.Logging;
public static class LoggerExtensions
{
public static void Info(this ILogger log, string msg) => log.LogInformation(msg);
应用程序洞察跟踪器也使用此处建议的解决方法注入依赖项,即我们的 Startup.cs 看起来很精简:
using Microsoft.ApplicationInsights.Extensibility;
using Microsoft.Azure.Functions.Extensions.DependencyInjection;
using Microsoft.Extensions.DependencyInjection;
[assembly: FunctionsStartup(typeof(EventForwarder.Startup))]
namespace EventForwarder
{
public class Startup : FunctionsStartup
{
public override void Configure(IFunctionsHostBuilder builder)
{
// https://github.com/Azure/azure-functions-host/issues/5353
builder.Services.AddSingleton(sp =>
{
var key = Environment.GetEnvironmentVariable("APPINSIGHTS_INSTRUMENTATIONKEY");
return string.IsNullOrWhiteSpace(key) ? new TelemetryConfiguration() : new TelemetryConfiguration(key);
});
我们正在执行 Http 重试跟踪,除其他外,如下所示:
public class HttpRetryPolicyService
{
private readonly ILogger<HttpRetryPolicyService> log;
private readonly TelemetryClient insights;
public HttpRetryPolicyService(ILogger<HttpRetryPolicyService> log,
TelemetryConfiguration insightsConfig)
{
this.log = log;
insights = new TelemetryClient(insightsConfig);
}
...
private void LogRetry(DelegateResult<HttpResponseMessage> message, TimeSpan delay, int attempt, Context context)
{
if (message.Exception != null)
{
log.Warn($"Exception details: {message.Exception}");
insights.Track(message.Exception);
我们正在使用扩展方法进行跟踪,如下所示:
using Microsoft.ApplicationInsights;
namespace EventForwarder.Static
{
public static class TelemetryExtensions
{
public static void Track(this TelemetryClient insights, string eventName)
{
insights.TrackEvent(eventName);
insights.Flush();
}
我错过了什么?
编辑 #1:顺便说一句,不幸的是,在“发布”对话框中添加 Application Insights 作为服务依赖项并不能解决这些问题。
编辑#2:此外,我们的 Functions host.json 文件都看起来像这样:
{
"version": "2.0",
"healthMonitor": {
"enabled": true,
"healthCheckInterval": "00:00:10",
"healthCheckWindow": "00:02:00",
"healthCheckThreshold": 6,
"counterThreshold": 0.80
},
"logging": {
"fileLoggingMode": "always",
"applicationInsights": {
"enableLiveMetrics": true,
"samplingSettings": {
"isEnabled": true
}
},
"logLevel": {
"EventForwarder": "Information"
}
}
}
解决方案
这就是破坏您的应用程序的原因,将其删除,一切正常:
// https://github.com/Azure/azure-functions-host/issues/5353
builder.Services.AddSingleton(sp =>
{
var key = Environment.GetEnvironmentVariable("APPINSIGHTS_INSTRUMENTATIONKEY");
return string.IsNullOrWhiteSpace(key) ? new TelemetryConfiguration() : new TelemetryConfiguration(key);
});
我的猜测是,既然已经推出了错误修复,解决方法实际上会破坏日志记录。
我创建了一个示例应用程序,其中日志记录和日志流工作得非常好,也有依赖注入。我使用 Windows 和 Linux 消费计划对其进行了测试。函数应用是使用 Azure 门户中的向导创建的,选择 .NET Core 3.1。请注意,TrackEvent
它不会显示在函数的日志流中。它显示在 Application Insights Live Metrics 中。在显示“已连接”后,最长可能需要 30 秒才能显示实际日志。Live Metrics 视图效果更好,尤其是当您直接从应用程序洞察中打开时。
通过应用上述“解决方法”,我能够重现您的问题。没有它,一切正常。
完整示例:https ://github.com/LXBdev/Functions-V3-sample
public class Startup : FunctionsStartup
{
public override void Configure(IFunctionsHostBuilder builder)
{
builder.Services.AddScoped<MyService>();
}
"logging": {
"applicationInsights": {
"samplingExcludedTypes": "Request",
"samplingSettings": {
"isEnabled": true
}
},
"logLevel": {
"Functions_V3_sample": "Information"
}
}
public MyService(ILogger<MyService> logger, TelemetryClient telemetry)
{
Logger = logger ?? throw new ArgumentNullException(nameof(logger));
Telemetry = telemetry ?? throw new ArgumentNullException(nameof(telemetry));
}
public void Foo()
{
Logger.LogInformation("Foo");
Telemetry.TrackTrace("BarLog", Microsoft.ApplicationInsights.DataContracts.SeverityLevel.Information);
Telemetry.TrackEvent("BarEvent");
}
更新:我的原始答案和示例中的 host.json 存在问题 - 由于https://github.com/Azure/azure-functions-host/issues/4345,日志并没有真正保留到 AppInsights 。我相应地更新了代码。
推荐阅读
- clang-format - clang-format 选项在 C++ / 标头访问修饰符之前和之后添加换行符?
- python - 无法使用 openpyxl 在 excel 文件中写入 html 内容
- php - 文件不存储
- python - 使用我的 launch.json 调试烧瓶时不尊重 pythonEnv 特定路径
- android - 用户无法在 Play 商店同时安装安卓应用。如何解决这个问题?
- reactjs - 不变式失败:浏览器历史记录需要一个 DOM
- r - Pycharm 和 R 插件 - RConsole 无法启动
- javascript - 如何使用 axios 在 react-native 中调用带有身份验证令牌的直接 pdf 下载 api
- mysql - mysql删除行后回收mysql磁盘空间
- java - Java Selenium WebDriver:点击 Instagram 登录按钮