将EventLog输出添加到已经使用ILoggerFactory的现有.net应用程序中



我有一个。net 7 web应用程序,使用注入的ILoggerFactory来记录日志。

在我们的开发环境中,我们在控制台中得到输出,这很好。

在使用IIS的Windows服务器上,我想将此日志输出重定向到系统事件日志。

我可以在应用中使用DI:

// Program.cs
var builder = WebHost.CreateDefaultBuilder(args);
...
// Add Windows EventLog
builder.ConfigureLogging(l => l.AddEventLog(...));

然而,这意味着我的应用程序将只能在Windows上运行(AddEventLog将在任何非Windows服务器上崩溃),我不希望这样。

另外,AddEventLog可以硬编码应用程序名称,但如果还没有在事件日志中注册,则会崩溃(默认是"Application"".NET Runtime",这没有多大用处),所以我希望在配置中设置事件日志,而不是硬编码。

看起来这已经是CreateDefaultBuilder:

// HostingHostBuilderExtensions.cs > AddDefaultServices
bool isWindows = RuntimeInformation.IsOSPlatform(OSPlatform.Windows);
...
if (isWindows)
// Add the EventLogLoggerProvider on windows machines
logging.AddEventLog();

这将建议所有我需要做的是添加一个配置部分到appSettings.json:

{
"Logging": {
"EventLog": {
"LogLevel": {
"Default": "Information"
},
"SourceName": "My App"
}
}
...

但是添加这个配置部分没有任何作用——似乎只有控制台日志记录是由CreateDefaultBuilder设置的。

似乎我可以使用DOTNET_STARTUP_HOOKS环境变量(文档很少,但Azure和类似的使用)来添加如下内容:

internal class StartupHook
{
public static void Initialize() {
// override app to output to Event Log
// loading dependencies here is nasty
// we don't have access to the app builder and AddEventLog()
// so probably have to kludge Console.SetOut somehow
}
}

然后我可以在Windows中设置这个变量,在其他不支持事件日志的主机环境中跳过它。

然而,这感觉就像一个很多乱搞一个高级的未记录的特性来做一些必须是真正常见的做法。当然,我不是第一个不希望限制Windows依赖来设置日志输出的。net开发人员。

  • 是否有办法将内置的。net事件日志输出添加到现有的,编译的。net应用程序与现有的配置功能?
  • 为什么在CreateDefaultBuilder中明显忽略的代码?
  • 或者,如果我必须使用DOTNET_STARTUP_HOOKS我不能是第一个需要这个,有人已经写了吗?

这些问题是由于多年来运行和配置web应用程序的多种模式造成的,任何试图谷歌其中一个的尝试都会发现其他的类似文档,这是一种痛苦。

有3次迭代,我使用最古老的:

  • WebHost.CreateDefaultBuilder是随。net Core 1一起发布的最小构建器,当时的想法是保持它的最小化并手动添加所有内容。在某一时刻……我想)UseKestrel/UseIIS是烤进去的,但它不包括日志记录。

  • Host.CreateDefaultBuilder是一个重建(。. NET 5)使得这个通用的应用程序,而不是网站。它增加了对原始WebHost变体所缺乏的事件日志的支持。

  • WebApplication.CreateBuilder在。net 6中简化了这一点,但与前两者使用的Startup.cs不兼容。

升级和事件日志工作,但忽略appsettings.json,但这似乎是一个错误在。net: https://github.com/dotnet/runtime/issues/80724

您可以通过手动重新注册事件记录器提供程序来解决此问题:

[System.Runtime.Versioning.SupportedOSPlatform("windows")]
public static void SetEventLogConfig(WebApplicationBuilder builder) {
string? eventLog = builder.Configuration["Logging:EventLog:SourceName"];
if(eventLog is not null)
builder.Logging.AddEventLog(c => c.SourceName = eventLog);
}
// then in program.cs
var builder = WebApplication.CreateBuilder(args);
...
if(RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
SetEventLogConfig(builder);

最新更新