C# 如何通过依赖项注入正确设置Azure功能日志记录、实时度量和应用程序洞察
大约一个月前,我注意到旧Azure Functions门户界面中的一些监控功能停止工作。我在网上写了更多关于这些问题的细节,但我的具体问题到目前为止还没有得到回答 现在,Azure功能门户界面似乎默认为新的“管理体验”,它看起来更类似于Azure的其余部分,因此,更明显的是,我们使用日志记录和跟踪的方式出了问题 我的问题是:关于如何设置Azure功能日志记录、实时度量和应用程序洞察跟踪,有人有任何代码示例吗:C# 如何通过依赖项注入正确设置Azure功能日志记录、实时度量和应用程序洞察,c#,azure,azure-functions,azure-application-insights,C#,Azure,Azure Functions,Azure Application Insights,大约一个月前,我注意到旧Azure Functions门户界面中的一些监控功能停止工作。我在网上写了更多关于这些问题的细节,但我的具体问题到目前为止还没有得到回答 现在,Azure功能门户界面似乎默认为新的“管理体验”,它看起来更类似于Azure的其余部分,因此,更明显的是,我们使用日志记录和跟踪的方式出了问题 我的问题是:关于如何设置Azure功能日志记录、实时度量和应用程序洞察跟踪,有人有任何代码示例吗: 与依赖项注入一起使用 与新的“管理体验”界面配合使用 目前,为了查看特定Azure函数
- 调用日志,即当您按下“函数(只读)>[function]>Monitor”下的“监视器”链接时得到的日志,显示根本没有调用,即使函数肯定是根据日志调用的
- Live app metrics链接会导致默认的“不可用:您的应用程序处于脱机状态或使用较旧的SDK”以及一些动画演示图表
- 监控>日志流显示除“已连接!“,不管是否冗长
- 再次监视>日志流>在Live Metrics中打开只会生成默认值“不可用:您的应用程序处于脱机状态或使用较旧的SDK”
- 开发者>代码+测试>测试按钮>运行,日志窗口弹出,只是说“连接!“除此之外,别无他事,再也不管冗长了
- Monitor>Invocations,这里没有注册调用跟踪,即使函数显然是根据旧接口日志流调用的
- 监视器>日志,再一次,只是说“已连接!“,不管是否冗长
using Microsoft.Extensions.Logging;
public class EventForwarder
{
private readonly ILogger<EventForwarder> log;
app insights tracer还使用建议的解决方案注入依赖项,即我们的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);
我错过了什么
编辑#1:顺便说一句,在发布对话框中将应用程序洞察作为服务依赖项添加,不幸的是,不能解决这些问题
编辑#2:另外,我们的函数host.json文件都是这样的:
这就是破坏你的应用程序的原因,删除它,一切都应该正常:
// 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);
});
我的猜测是,既然bug修复已经推出,解决方法实际上会破坏日志记录
我创建了一个示例应用程序,其中日志记录和日志流工作得非常好,还使用依赖项注入。我使用Windows和Linux消费计划对其进行了测试。该函数应用程序是使用Azure门户中的向导创建的,选择.NET Core 3.1。请注意,TrackEvent
不会显示在函数的日志流中。它会显示在Application Insights Live Metrics中。在显示“已连接”后,可能需要30秒才能显示实际日志。Live Metrics视图工作得更好,尤其是直接从Application Insights打开时
我可以通过应用上面提到的“变通方法”重现您的问题。没有它,一切都会正常进行
全样本:
publicMyService(ILogger记录器、遥测客户端遥测)
{
Logger=Logger??抛出新的ArgumentNullException(name of(Logger));
遥测=遥测??抛出新的ArgumentNullException(nameof(遥测));
}
公共图书馆
{
Logger.LogInformation(“Foo”);
Telemetry.TrackTrace(“BarLog”,Microsoft.ApplicationInsights.DataContracts.SeverityLevel.Information);
遥测跟踪事件(“BarEvent”);
}
更新:我的原始答案中的host.json有问题,示例日志没有真正持久化到AppInsights,因为。我相应地更新了代码
您好,我正在使用新的azure功能,application insights的所有功能似乎都运行良好(只需从azure门户启用application insights)。那么,我可以知道您为什么要使用DI吗?@IvanYang对于依赖注入的任何其他用例来说都是一样的,即可测试性、可模拟性、IoC,避免静态/全局上下文,并且不必在每次方法/函数调用中传递日志记录、跟踪和其他服务类。在我看来,即使将它们封装在某种类型的服务对象。从2x版本开始正式支持它:是的,今天早上确认了它。事实上,以前需要的解决方法现在正在打破除“经典体验”之外的所有日志记录“日志流。您的示例之所以有效,是因为您在MyService中使用了以函数开头的名称空间,请继续,并将其更改为类似的内容。它不会记录。您可能有这些问题,因为我的原始答案在
host.json
中缺少一个关键部分。我已经更新了解决方案。
using Microsoft.ApplicationInsights;
namespace EventForwarder.Static
{
public static class TelemetryExtensions
{
public static void Track(this TelemetryClient insights, string eventName)
{
insights.TrackEvent(eventName);
insights.Flush();
}
{
"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);
});
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");
}