如何为Unity容器配置ILogger<T>支持EventLog和AppInsights日志
解决方案
前置依赖安装
先安装以下缺失的NuGet包,已安装的Topshelf、Unity相关包无需改动:
Microsoft.Extensions.Logging:日志核心抽象库Microsoft.Extensions.Logging.EventLog:Windows事件日志官方输出提供程序Microsoft.Extensions.Logging.ApplicationInsights:Application Insights官方日志输出提供程序
原有代码问题说明
你原先写的两行ILogger注册逻辑存在两个核心问题:
- 直接new的空
LoggerFactory未挂载任何输出提供程序,所有日志调用不会被写入任何存储 - 泛型
ILogger<T>的实例需要从配置完成的日志工厂生成,直接做类型映射无法生成可用的日志实例
正确配置代码
直接替换你Main方法中容器初始化相关的代码即可,完整逻辑如下:
using System; using Topshelf; using Unity; using Unity.Lifetime; using Topshelf.Unity; using Microsoft.Extensions.Logging; namespace WindowsServiceExample { public class Program { static void Main(string[] args) { var container = new UnityContainer(); container.RegisterType<IExamplaryService, ExamplaryService>(new ContainerControlledLifetimeManager()); // 如果你自定义的AppInsights、EventLog服务有额外封装逻辑可以保留,否则官方提供程序已经覆盖写入能力,不需要单独注册 // container.RegisterType<IAppInsightsService, AppInsightsService>(new ContainerControlledLifetimeManager()); // container.RegisterType<IEventLogService, EventLogService>(new ContainerControlledLifetimeManager()); // 初始化日志工厂,挂载两个输出提供程序 var loggerFactory = LoggerFactory.Create(builder => { // 配置全局日志过滤规则,可根据自己需求调整级别 builder.AddFilter("System", LogLevel.Warning) .AddFilter("Microsoft", LogLevel.Warning) .AddFilter("WindowsServiceExample.*", LogLevel.Information) // 挂载Windows事件日志提供程序 .AddEventLog(options => { options.SourceName = "ExamplaryService"; options.LogName = "Application"; }) // 挂载AppInsights提供程序,替换为你自己的AppInsights连接字符串 .AddApplicationInsights("你的Application Insights连接字符串"); }); // 注册日志工厂单例 container.RegisterInstance<ILoggerFactory>(loggerFactory); // 注册泛型ILogger<T>,自动从日志工厂生成对应类别的日志实例 container.RegisterType(typeof(ILogger<>), new InjectionFactory((context, targetType, name) => { var factory = context.Resolve<ILoggerFactory>(); var loggerCategory = targetType.GetGenericArguments()[0].FullName; return factory.CreateLogger(loggerCategory); })); TopshelfExitCode exitCode = HostFactory.Run(hostConfigurator => { hostConfigurator.UseUnityContainer(container); hostConfigurator.Service<IExamplaryService>(serviceConfigurator => { serviceConfigurator.ConstructUsingUnityContainer(); serviceConfigurator.WhenStarted(service => service.Start()); serviceConfigurator.WhenStopped(service => service.Stop()); }); hostConfigurator.RunAsLocalSystem(); hostConfigurator.StartAutomatically(); hostConfigurator.SetServiceName("ExamplaryService"); hostConfigurator.SetDisplayName("Examplary Service"); hostConfigurator.SetDescription("Description of Examplary Service."); hostConfigurator.EnableShutdown(); hostConfigurator.EnablePauseAndContinue(); }); int exitCodeValue = (int)Convert.ChangeType(exitCode, exitCode.GetTypeCode()); Environment.ExitCode = exitCodeValue; } } }
配置说明
- 日志级别可通过
AddFilter方法自定义,上述配置默认关闭系统组件的Info级别日志,只输出业务代码的Info及以上级别日志 - Windows事件日志默认写入系统的Application日志分组,服务以LocalSystem账号运行时会自动创建指定的SourceName,无需提前手动创建
- AppInsights配置完成后,日志会自动上报到对应的AppInsights资源,无需额外编写上报逻辑
- 配置完成后,在服务类中通过构造函数注入
ILogger<你的服务类名>,直接调用LogInformation、LogError等方法,日志会同时写入Windows事件查看器和AppInsights
内容的提问来源于stack exchange,提问作者bodzio05
相关产品推荐
相关产品推荐

