如何使用依赖注入正确设置 Azure Functions 日志记录、实时指标和应用洞察
How to properly set up Azure Functions logging, live metrics, and app insights with dependency injection
大约一个月前,我注意到旧 Azure Functions 门户界面中的一些监控功能停止工作。我在 Azure Functions Host GitHub 上写了更多关于问题的详细信息,但我的特定问题尚未得到解答。
现在 Azure Functions 门户界面似乎默认为新的 "management experience",它看起来与 Azure 的其余部分更相似,因此,更明显的是我们使用日志记录的方式出了问题和追踪。
我的问题是:是否有人有关于如何设置 Azure Function 日志记录、实时指标和应用洞察跟踪的任何代码示例,以便:
- 使用依赖注入
- 使用新的 "management experience" 界面
目前,为了查看特定的 Azure Function 在做什么,我必须转到旧的 Azure 界面并研究日志流。功能确实有效,它们在日志流中吐出信息,但仅限于旧界面,而且在监控方面似乎没有多少其他工作。使用旧界面:
- 调用日志,当您在“函数(只读)> [函数] > 监视器下按 "Monitor" link 时获得的调用日志,即使函数根据日志肯定是被调用了。
- Live 应用程序指标 link 导致默认 "Not available: your app is offline or using an older SDK" 和一些动画演示图表。
这些在一个月前运行良好。现在,没那么多了。
使用新界面:
- 监控 > 日志流除了单词 "Connected!" 外什么都没有显示,无论详细程度如何。
- 监控 > 日志流 > 在实时指标中再次打开只会产生默认值 "Not available: your app is offline or using an older SDK"。
使用“函数”>“函数”>“[单击一个函数]”转到新界面中的特定函数:
- Developer > Code + Test > Test-button > 运行,日志 window 弹出,只是说 "Connected!" 没有别的,再一次不管冗长。
- Monitor > Invocations,这里没有注册任何调用痕迹,尽管这个函数显然是根据旧接口日志流被调用的。
- Monitor > Logs,再一次,只是说 "Connected!",不管冗长。
我不明白为什么它在一个月前突然停止工作,为什么这么多东西在新界面上似乎不起作用。我们的函数的 NuGet 包都是最新的。
在日志记录方面,记录器是依赖注入的,因此我们可以在多个 classes 中使用它,而不仅仅是默认的 Functions.cs class:
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);
App Insights 跟踪器也使用建议的解决方法 here 依赖注入,即我们的 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:此外,我们的函数 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 秒。实时指标视图效果更好,尤其是当您直接从应用程序洞察中打开时。
通过应用上述“解决方法”,我能够重现您的问题。没有它,一切正常。
完整样本: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 .我相应地更新了代码。
大约一个月前,我注意到旧 Azure Functions 门户界面中的一些监控功能停止工作。我在 Azure Functions Host GitHub 上写了更多关于问题的详细信息,但我的特定问题尚未得到解答。
现在 Azure Functions 门户界面似乎默认为新的 "management experience",它看起来与 Azure 的其余部分更相似,因此,更明显的是我们使用日志记录的方式出了问题和追踪。
我的问题是:是否有人有关于如何设置 Azure Function 日志记录、实时指标和应用洞察跟踪的任何代码示例,以便:
- 使用依赖注入
- 使用新的 "management experience" 界面
目前,为了查看特定的 Azure Function 在做什么,我必须转到旧的 Azure 界面并研究日志流。功能确实有效,它们在日志流中吐出信息,但仅限于旧界面,而且在监控方面似乎没有多少其他工作。使用旧界面:
- 调用日志,当您在“函数(只读)> [函数] > 监视器下按 "Monitor" link 时获得的调用日志,即使函数根据日志肯定是被调用了。
- Live 应用程序指标 link 导致默认 "Not available: your app is offline or using an older SDK" 和一些动画演示图表。
这些在一个月前运行良好。现在,没那么多了。
使用新界面:
- 监控 > 日志流除了单词 "Connected!" 外什么都没有显示,无论详细程度如何。
- 监控 > 日志流 > 在实时指标中再次打开只会产生默认值 "Not available: your app is offline or using an older SDK"。
使用“函数”>“函数”>“[单击一个函数]”转到新界面中的特定函数:
- Developer > Code + Test > Test-button > 运行,日志 window 弹出,只是说 "Connected!" 没有别的,再一次不管冗长。
- Monitor > Invocations,这里没有注册任何调用痕迹,尽管这个函数显然是根据旧接口日志流被调用的。
- Monitor > Logs,再一次,只是说 "Connected!",不管冗长。
我不明白为什么它在一个月前突然停止工作,为什么这么多东西在新界面上似乎不起作用。我们的函数的 NuGet 包都是最新的。
在日志记录方面,记录器是依赖注入的,因此我们可以在多个 classes 中使用它,而不仅仅是默认的 Functions.cs class:
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);
App Insights 跟踪器也使用建议的解决方法 here 依赖注入,即我们的 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:此外,我们的函数 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 秒。实时指标视图效果更好,尤其是当您直接从应用程序洞察中打开时。
通过应用上述“解决方法”,我能够重现您的问题。没有它,一切正常。
完整样本: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 .我相应地更新了代码。