欢迎来到Introzo百科
Introzo百科
当前位置:网站首页 > 技术 > .NET Core日志[4]:将日志写入EventLog

.NET Core日志[4]:将日志写入EventLog

日期:2023-10-01 12:53

-->

面向Windows的程序员应该对Event Log很熟悉,所以很多人一提到日志,首先想到的就是EventLog。 EventLog不仅记录Windows系统自身的各种事件日志,我们的应用程序还可以使用提供的API将日志消息写入EventLog。与EventLog相关的API在System.Diagnostics.EventLog类型中定义。我们不仅可以用它来读取、写入和删除日志,还可以用它来创建和删除事件源。 .NET Core的日志模型使用EventLogLogger来实现与EventLog的集成,但是EventLogLogger使用的是抽象的EventLog。本文已同步至《www.introzo.com Core框架揭秘》]

目录
1。摘要事件日志
2。 EventLogLogger
3。 EventLogLoggerProvider

1。摘要事件日志

EventLogLogger 在 NuGet 包“Microsoft.Extensions.Logging.EventLog”中定义。截至当前版本,NuGet 包托管的程序集仅适用于 .NET Framework 应用程序。换句话说,Eve​​ntLogLogger仅提供对Windows EventLog的支持。尽管如此,日志模型仍然通过接口抽象了EventLog的相关操作。

ConsoleLogger 使用 IConsole 接口来抽象不同平台的控制台。 EventLogLogger 使用的抽象 EventLog 由 IEventLog 接口表示。如下面的代码片段所示,IEventLog接口只定义了一个唯一的方法WriteEntry来写入日志。提供的参数用于指定日志的消息文本(message)、类型(type)、事件ID(eventID)和类别(category)。 )。为了防止单个日志包含太多内容,IEventLog接口定义了一个只读属性MaxMessageSize来设置日志消息文本允许的最大长度。

1:公共接口IEventLog

2:{

3:void WriteEntry(字符串消息,EventLogEntryType类型,int事件ID,短类别);

4: int MaxMessageSize { 获取; }

5:}

6:

7:公共枚举EventLogEntryType

8:{

9:错误 = 1,

10:警告=2,

11:信息=4,

12:成功审核 = 8

13:失败审核 = 16

14:}

EventLog记录的每条日志都有一个由枚举EventLogEntryType表示的类型,相当于日志级别。对于该枚举中定义的五种类型,Error、Warning、Information 与同名日志级别含义相同,而 SuccessAudit 和 FailureAudit 代表“Audit”事件的日志,分别代表“成功”事件的日志。事件”和“失败事件”回顾。 EventLogLogger在使用EventLog写入日志时,会将指定的日志级别转换为EventLog日志类型。转换规则很简单:Error、Warning、Information的日志级别转换为同名的EventLog日志类型,其他级别转换为Information类型。

具有以下定义的 WindowsEventLog 是 IEventLog 接口的默认实现者。 WindowsEventLog 实际上是 EventLog 对象的封装,由 DiagnosticsEventLog 属性表示。这个封装的EventLog对象是在构造函数中通过指定相应参数的日志名称(logName)、机器名称(machineName)和事件源名称(sourceName)来创建的。在实现的WriteEntry方法中,直接调用这个EventLog的WriteEntry来完成日志的写入。 WindowsEventLog 的 MaxMessageSize 属性返回常量 31839,日志消息文本不能超过此长度。

1:公共类WindowsEventLog:IEventLog

2:{

3: private const int MaximumMessageSize = 31839;

4:

5:公共int MaxMessageSize

6:{

7:获取{返回MaximumMessageSize; }

8:}

9:

10: 公共System.Diagnostics.EventLog DiagnosticsEventLog { 获取; }

11:

12: public WindowsEventLog(string logName, string machineName, string sourceName)

13:{

14: DiagnosticsEventLog = new System.Diagnostics.EventLog(logName, machineName, sourceName);

15:}

16:

17:public void WriteEntry(字符串消息,EventLogEntryType类型,int事件ID,短类别)

18:{

19:DiagnosticsEventLog.WriteEntry(消息、类型、事件ID、类别);

20:}

21:}

二、EventLogLogger

日志模型利用EventLogger实现了与EventLog的集成。具体来说,一个EventLogger实际上是对EventLog对象的封装,它利用了向EventLog写入日志。EventLogLogger类型具有如下的定义,我们可以看到它具有构造函数,除了提供两个Logger名称之外,其中一个构造函数具有一个类型为EventLogSettings的参数,这个封装的EventLog对象正式创建通过该参数提供的信息出来的。

1:公共类EventLogLogger:ILogger

2:{

3: public EventLogLogger(字符串名称);

4:public EventLogLogger(字符串名称,EventLogSettings设置);

5:

6:public IDisposable BeginScope(TState状态);

7: public bool IsEnabled(LogLevel logLevel);

8:public void Log(LogLevel logLevel, EventId eventId, TState 状态, Exception 异常,

9:Func格式化程序);

10:}

11:

12:公共类EventLogSettings

13:{

14: 公共 IEventLog 事件日志 { 获取;放; }

15:

16: 公共字符串 LogName { get;放; }

17: 公共字符串机器名{ get;放; }

18: 公共字符串 SourceName { get;放; }

19:

20:公共Func过滤器{获取;放; }

21:}

如上面的代码片段所示,我们可以使用EventLogSettings对象的EventLog属性来向EventLogLogger提供特定的EventLog对象。如果此属性为 Null,EventLogLogger 将使用 EventLogSettings 的其他三个属性(LogName、MatcheName 和 SourceName)创建 WindowsEventLog 对象。除了这四个与创建或提供EventLog对象相关的属性之外,EventLogSettings还有另一个Func类型的属性,Filter,它自然代表日志消息过滤器。

当EventLogLogger使用EventLogSettings创建WindowsEventLog对象时,如果EventLogSettings对象中没有显式设置相关属性(LogName、MatcheName和SourceName),则会采用预定义的默认值。具体来说,这三者对应的默认值分别是“Application”[1]、“.” (代表本地机器)和“应用程序”。如果我们调用第一个构造函数重载,实际上将使用这些默认值在内部创建一个 WindowsEventLog 对象。如果调用构造函数时没有指定名称(name参数),则将使用类型名称(“EventLogLogger”)来命名创建的Logger。

EventLogLogger 和 DebugLogger 一样,不支持日志上下文作用域,所以它的 BeginScope 方法和返回的对象实际上是没有意义的。 EventLogSettings 的 Filter 属性返回一个 Func 对象,IsEnabled 方法将使用该对象。如果未显式提供委托对象,则意味着该方法始终返回 True。当调用Log方法时,它会按照与DebugLogger完全相同的方式格式化最终的日志消息文本,因此异常重复描述的问题仍然存在。日志消息最终通过调用EventLog的WriteEntry方法写入EventLog,但在此之前,它会检查格式化的日志消息文本是否超出MaxMessageSize属性限制的长度。如果超过这个限制,日志消息将会被分割和合并。多次写入EventLog。

3。 EventLogLoggerProvider

EventLogLogger 由相应的EventLogLoggerProvider 提供。以下代码反映了该类型的完整定义。我们可以调用如下所示的三个扩展方法AddEventLog来创建对应的EventLoggerProvider,并将其注册到指定的LoggerFactory上。我们可以使用此方法来指定EventLogSettings对象以及用于提供或协助创建EventLog的最低日志级别。

1:公共类EventLoggerProvider:ILoggerProvider,IDisposable

2:{

3:私有只读EventLogSettings_settings;

4:公共EventLogLoggerProvider():this(null)

5:{}

6:

7:公共EventLogLoggerProvider(EventLogSettings设置)

8:{

9:_settings=设置;

10:}

11:

12: public ILogger CreateLogger(字符串名称)

13:{

14: return new EventLogLogger(name, _settings ?? new EventLogSettings());

15:}

16:

17: public void Dispose()

18:{}

19:}

20:

21:公共静态类EventLoggerFactoryExtensions

22:{

23: public static ILoggerFactory AddEventLog(这个 ILoggerFactory 工厂);

24:public static ILoggerFactory AddEventLog(此ILoggerFactory工厂,EventLogSettings设置);

25:公共静态ILoggerFactory AddEventLog(此ILoggerFactory工厂,LogLevel minLevel);

26:}

我们还通过简单的控制台应用程序演示了 EventLog 的日志记录。我们的第一选择是创建一个空的控制台应用程序并在 project.json 中添加所需的依赖项。由于 EventLog 的日志记录仅适用于 .NET Framework 应用程序,因此我们仅为该应用程序定义了 .NET Framework 4.6.1 (net461) 的框架。

1:{

2:...

3:“依赖项”:{

4:“Microsoft.Extensions.DependencyInjection”:“1.0.0”,

5:“Microsoft.Extensions.Logging”:“1.0.0”,

6:“Microsoft.Extensions.Logging.EventLog”:“1.0.0”

7:},

8:

9:“框架”:{

10:“net461”:{

11:“框架组件”:{

12:“系统.运行时”:{

13:“类型”:“构建”

14:}

15:}

16:}

17:}

18:}

我们编写了以下程序来完成EventLog的记录。如下面的代码片段所示,我们首先为要写入的日志创建一个名为“Demo”的Event Source(一般代表写入日志的应用程序或服务的名称)。接下来,我们使用依赖注入创建了LoggerFactory对象,并调用扩展方法AddEventLog创建了EventLoggerProvider对象并将其注册到LoggerFactory中。我们在调用此 AddEventLog 方法时指定了一个 EventLogSettings 对象,并将其 SourceName 属性设置为“Demo”。我们最终使用这个 LoggerFactory 对象来创建相应的 Logger,并用它来写入带有 Error 级别的日志。

1:公开课节目

2:{

3: public static void Main(string[] args)

4:{

5: if(!EventLog.SourceExists("演示"))

6:{

7:EventLog.CreateEventSource("演示", "应用程序");

8:}

9:

10:新的ServiceCollection()

11: .AddLogging()

12: .BuildServiceProvider()

13: .GetService()

14: .AddEventLog(new EventLogSettings { SourceName = "Demo" })

15: .CreateLogger()

16: .LogError("数据库连接失败(数据库:{数据库},用户名:{用户})","TestDb","sa");

17:}

18:}

由于上述程序涉及查看和创建Event Source,因此需要在管理员权限下正常运行。运行程序并查看事件查看器后,我们将看到此日志消息被写入。如图10所示,由于我们调用扩展方法AddEventLog时提供的EventLogSettings没有明确指定EventLog名称,所以我们的日志将默认写入Application EventLog。


[1] Windows 默认提供了三种EventLog,分别是Application、System 和Security。应用程序生成的日志只能写入应用程序日志和系统日志。安全日志是只读的。除了这三种类型的EventLog之外,我们还可以为应用程序创建独立的EventLog。

.NET Core 日志[1]:使用统一方式记录日志
.NET Core 日志[2]:将日志写入控制台
.NET Core 日志[3]:写入日志 Write到调试窗口
.NET Core 日志[4]:使用EventLog 写入日志
.NET Core 日志[5]:使用TraceSource 写入日志

-->