1. 程式人生 > >.NET Core的日誌[4]:將日誌寫入EventLog

.NET Core的日誌[4]:將日誌寫入EventLog

面向Windows的程式設計人員應該不會對Event Log感到陌生,以至於很多人提到日誌,首先想到的就是EventLog。EventLog不僅僅記錄了Windows系統自身針對各種事件的日誌,我們的應用也可以利用提供的API將日誌訊息寫到EventLog中。與EventLog相關的API都定義在System.Diagnostics.EventLog這個型別中,我們不僅僅可以利用它讀取、寫入和刪除日誌,還可以使用它來建立和刪除Event Source。.NET Core的日誌模型利用EventLogLogger實現了與EventLog的整合,不過EventLogLogger使用的是一個抽象化的EventLog。本文已經同步到《

ASP.NET Core框架揭祕》之中]

目錄
一、抽象化的EventLog
二、EventLogLogger
三、EventLogLoggerProvider

一、抽象化的EventLog

EventLogLogger定義在“Microsoft.Extensions.Logging.EventLog”這個NuGet包中。就目前這個版本來說,該NuGet包承載的程式集只適用於.NET Framework應用,換句話說,EventLogLogger僅僅提供針對Windows EventLog的支援。儘管如此,日誌模型仍然通過一個介面對EventLog的相關操作進行了抽象。

ConsoleLogger採用IConsole介面對針對不同平臺的控制檯進行了抽象,EventLogLogger使用的抽象化EventLog通過IEventLog介面來表示。如下面的程式碼片段所示,IEventLog介面僅僅定義了一個唯一的方法WriteEntry來寫日誌,提供的引數用於指定日誌的訊息文字(message)、型別(type)、事件ID(eventID)以及類別(category)。為了避免單條日誌包含過多的內容,IEventLog介面定義了一個只讀屬性MaxMessageSize來設定日誌訊息的文字允許的最大長度。

   1: public interface IEventLog
   2: {
   3:     void WriteEntry(string message, EventLogEntryType type, int eventID, short category);
   4:     int MaxMessageSize { get; }
   5: }
   6:  
   7: public enum EventLogEntryType
   8: {
   9:     Error           = 1, 
  10:     Warning         = 2,
  11:     Information     = 4,
  12:     SuccessAudit    = 8 
  13:     FailureAudit    = 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)和Event Source名稱(sourceName)來建立。在實現的WriteEntry方法中,這個EventLog的WriteEntry被直接呼叫來完成日誌的寫入。WindowsEventLog的MaxMessageSize屬性返回一個常量31839,日誌訊息文字不能超過這個長度。

   1: public class WindowsEventLog : IEventLog
   2: {
   3:     private const int MaximumMessageSize = 31839;
   4:  
   5:     public int MaxMessageSize
   6:     {
   7:         get { return MaximumMessageSize; }
   8:     }
   9:  
  10:     public System.Diagnostics.EventLog DiagnosticsEventLog { get; }
  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(string message, EventLogEntryType type, int eventID, short category)   
  18:     {
  19:         DiagnosticsEventLog.WriteEntry(message, type, eventID, category);
  20:     }
  21: }

二、EventLogLogger

日誌模型利用EventLogLogger實現了與EventLog的整合。具體來說,一個EventLogLogger實際上是對EventLog物件的封裝,它利用後者向EventLog寫入日誌。EventLogLogger型別具有如下的定義,我們可以看到它具有兩個建構函式,除了提供Logger名稱之外,其中一個建構函式具有一個型別為EventLogSettings的引數,這個封裝的EventLog物件正式通過該引數提供的資訊創建出來的。

   1: public class EventLogLogger : ILogger
   2: {
   3:     public EventLogLogger(string name);
   4:     public EventLogLogger(string name, EventLogSettings settings);
   5:  
   6:     public IDisposable BeginScope<TState>(TState state);  
   7:     public bool IsEnabled(LogLevel logLevel);
   8:     public void Log<TState>(LogLevel logLevel, EventId eventId, TState state, Exception exception, 
   9:     Func<TState, Exception, string> formatter);
  10: }
  11:  
  12: public class EventLogSettings
  13: {
  14:     public IEventLog              EventLog { get; set; }
  15:  
  16:     public string                 LogName { get; set; }
  17:     public string                 MachineName { get; set; }
  18:     public string                 SourceName { get; set; } 
  19:  
  20:     public Func<string, LogLevel, bool>     Filter { get; set; }
  21: }

如上面的程式碼片段所示,我們可以利用EventLogSettings物件的EventLog屬性向EventLogLogger提供一個具體的EventLog物件。如果這個屬性為Null,EventLogLogger將會利用EventLogSettings的其他三個屬性(LogName、MatcheName和SourceName)建立一個WindowsEventLog物件。除了這四個與建立或者提供EventLog物件相關的四個屬性之外,EventLogSettings還具有另一個Func<string, LogLevel, bool>型別的屬性Filter,它自然代表日誌訊息過濾器。

當EventLogLogger在利用EventLogSettings建立WindowsEventLog物件的時候,如果相關的屬性(LogName、MatcheName和SourceName)在EventLogSettings物件中未作顯式設定,它會採用預定義的預設值。具體來說這三者對應的預設值為“Application”[1]、“.”(代表本機)和“Application”。如果我們呼叫第一個建構函式過載,實際上內部會利用這些預設值建立一個WindowsEventLog物件。如果呼叫建構函式時連名稱(name引數)都沒有指定,那麼型別名稱(“EventLogLogger”)將被用來命名建立的Logger。

EventLogLogger和DebugLogger一樣也不支援日誌上下文範圍,所以它的BeginScope<TState>方法和返回的物件其實毫無意義。EventLogSettings的Filter屬性返回Func<string, LogLevel, bool>物件將被IsEnabled方法使用,如果個委託物件沒有被顯式提供,意味著這個方法總是返回True。當Log方法被呼叫的時候,它會採用與DebugLogger完全一致的方式來格式化最終的日誌訊息文字,所以針對異常的重複描述的問題依然存在。日誌訊息最終通過呼叫EventLog的WriteEntry方法被寫到EventLog中,但是在這之前會檢查格式化後的日誌訊息文字是否超過通過MaxMessageSize屬性限制的長度,如果超過這個限制,日誌訊息將會被拆分並分多次寫入EventLog。

三、EventLogLoggerProvider

EventLogLogger由對應的EventLogLoggerProvider來提供,下面的程式碼體現了這個型別完整的定義。我們可以呼叫如下所示的三個擴充套件方法AddEventLog來建立相應的EventLogLoggerProvider並將其註冊到指定的LoggerFactory之上,我們可以通過這個方法指定用於提供或者輔助建立EventLog的EventLogSettings物件和最低日誌等級。

   1: public class EventLogLoggerProvider : ILoggerProvider, IDisposable
   2: {
   3:     private readonly EventLogSettings _settings;
   4:     public EventLogLoggerProvider() : this(null)
   5:     {}
   6:  
   7:     public EventLogLoggerProvider(EventLogSettings settings)
   8:     {
   9:         _settings = settings;
  10:     }
  11:  
  12:     public ILogger CreateLogger(string name)
  13:     {
  14:         return new EventLogLogger(name, _settings ?? new EventLogSettings());
  15:     }
  16:  
  17:     public void Dispose()
  18:     {}
  19: }
  20:  
  21: public static class EventLoggerFactoryExtensions
  22: {
  23:     public static ILoggerFactory AddEventLog(this ILoggerFactory factory);
  24:     public static ILoggerFactory AddEventLog(this ILoggerFactory factory, EventLogSettings settings);
  25:     public static ILoggerFactory AddEventLog(this ILoggerFactory factory, LogLevel minLevel);
  26: }

我們同樣通過一個簡單的控制檯應用來演示針對EventLog的日誌記錄。我們首選建立一個空的控制檯應用,並在project.json中新增所需的依賴。由於針對EventLog的日誌記錄只適用於.NET Framework應用,所以我們僅僅為應用定義了一個針對.NET Framework 4.6.1(net461)的框架。

   1: {
   2:   ...
   3:   "dependencies": {
   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:    "frameworks": {
  10:     "net461": {
  11:       "frameworkAssemblies": {
  12:         "System.Runtime": {
  13:           "type": "build"
  14:         }
  15:       }
  16:     }
  17:   }
  18: }

我們編寫了下面這段程式來完成針對EventLog的日誌記錄。如下面的程式碼片段所示,我們首先為即將寫入的日誌建立了一個名為“Demo”的Event Source(它一般代表日誌被寫入的應用或者服務的名稱)。接下來我們採用依賴注入的方式建立了一個LoggerFactory物件,並呼叫擴充套件方法AddEventLog建立了一個EventLoggerProvider物件並將其註冊到LoggerFactory上。我們在呼叫這個AddEventLog方法時指定了一個EventLogSettings物件,並將其SourceName屬性設定為“Demo”。我們最終利用這個LoggerFactory物件創建出對應的Logger,並利用它寫入了一條等級為Error的日誌。

   1: public class Program
   2: {
   3:     public static void Main(string[] args)
   4:     {
   5:         if(!EventLog.SourceExists("Demo"))
   6:         {
   7:             EventLog.CreateEventSource("Demo", "Application");
            
           

相關推薦

.NET Core日誌[4]:日誌寫入EventLog

面向Windows的程式設計人員應該不會對Event Log感到陌生,以至於很多人提到日誌,首先想到的就是EventLog。EventLog不僅僅記錄了Windows系統自身針對各種事件的日誌,我們的應用也可以利用提供的API將日誌訊息寫到EventLog中。與EventLog相關的API都定義在System

asp.net core使用serilog日誌推送到騰訊雲日誌服務

為什麼是serilog? Serilog是 .NET 中最著名的結構化日誌類庫。 基於日誌事件log events,而不是日誌訊息log message。 你可以將日誌事件格式化為控制檯的可讀文字或者可以將相同的事件格式化為JSON並將其傳送到遠端日誌伺服器。 應用程式中的日誌語句會建立LogEvent物件,

.NET Core日誌[3]:日誌寫入Debug視窗

定義在NuGet包“Microsoft.Extensions.Logging.Debug”中的DebugLogger會直接呼叫Debug的WriteLine方法來寫入分發給它的日誌訊息。如果需要使用DebugLogger來寫日誌,我們需要將它的提供者DebugLoggerProvider註冊到LoggerFa

.NET Core日誌[2]:日誌輸出到控制檯

對於一個控制檯應用,比如採用控制檯應用作為宿主的ASP.NET Core應用,我們可以將記錄的日誌直接輸出到控制檯上。針對控制檯的Logger是一個型別為ConsoleLogger的物件,ConsoleLogger對應的LoggerProvider型別為ConsoleLoggerProvider,這兩個型別都

.NET Core使用log4Net記錄日誌

com hit appendto append and logger pub his manage 1.引入Nuget包 log4net 2.添加log4Net配置文件 1 <?xml version="1.0" encoding="utf-8" ?> 2

.NET Core使用Nlog記錄日誌

microsoft except urn odin conf -c lena 註入 eight 1.引入Nuget包 Nlog Nlog.Web.AspNetCore 2.添加nlog配置文件 1 <?xml version="1.0"

用 Log4Net 三步實現 .Net Core 類庫 分日誌等級(不同檔案目錄)存日誌

1,建立.Net Core  Web 專案,引入 log4net 2,建立類庫,新增如下 helper方法 1 using log4net; 2 using log4net.Config; 3 using System; 4 using Syste

Asp.Net Core 輕鬆學-利用日誌監視進行服務遙測

前言     在 Net Core 2.2 中,官方文件表示,對 EventListener 這個日誌監視類的內容進行了擴充,同時賦予了跟蹤 CoreCLR 事件的許可權;通過跟蹤 CoreCLR 事件,比如通過跟蹤 CoreCLR 事件,可以瞭解和收集到比如 GC,JIT,ThreadPool,intre

.net core 微服務之日誌落盤設計

oss val www. strong 導致 在線 ron 計算器 name 原文:.net core 微服務之日誌落盤設計 目錄1、設計目標2、日誌流程3、串聯請求事務3.1

.Net Core 整合ExceptionLess分散式日誌框架之本地化部署

## 前言 公司目前使用的專案中關於日誌記錄這塊,之前一直都是使用的Log4net 存放於後臺文件中的,對於異常錯誤啊,或者需要檢視一些詳情錯誤的時候感覺很不方便,要到伺服器上去開啟日誌檔案檢索錯誤,降低了解決問題的速度,所以針對日誌這塊的優化就提上日程了。考慮了好久決定採用ExceptionLess日誌框

.Net Core中的診斷日誌DiagnosticSource講解

### 前言     近期由於需要進行分散式鏈路跟蹤系統的技術選型,所以一直在研究鏈路跟蹤相關的框架。作為能在.Net Core中使用的APM,SkyWalking自然成為了首選。[SkyAPM-dotnet](https://github.com/SkyAPM/Sky

一套標準的ASP.NET Core容器化應用日誌收集分析方案

## 講故事 關注我公眾號的朋友,應該知道我寫了一些雲原生應用收集和分析相關的文章,其中內容大多聚焦某個具體的元件: - 超級有用的TraceId,快點用起來吧! - 如何利用NLog輸出結構化日誌,並在Kibana優雅分析日誌? | - 既然能直接向ElasticSearch寫日誌,為什麼

ASP.NET Core擴充套件庫之日誌

    上一篇我們對Xfrogcn.AspNetCore.Extensions擴充套件庫功能進行了簡單的介紹,從這一篇文章開始,我將逐步介紹擴充套件庫中的核心功能。     日誌作為非業務的通用領域基礎功能,有非常多的技術實現,這些第三方庫避免了我們花費時間去重複實現,

asp.net core 2.1 控制器抽離到類庫中

cat start service public 網站 類庫 class all app startup.cs的ConfigureServices中添加: public void ConfigureServices(IServiceCollection

CentOS&.NET Core初試-4-安裝守護服務(Supervisor)

aspnet 客戶 ins 失效 fault 接收 des rip 執行 系列目錄 CentOS的安裝和網卡的配置 安裝.NET Core SDK和發布網站 Nginx的安裝和配置 安裝守護服務(Supervisor) Supervisor是什麽? Supervisor

.Net Core實踐4 web 反向代理

files 啟動 用戶目錄 ces user async microsoft config 通過 目標 將控制臺程序改成web程序,通過IIS反向代理,處理請求 環境 win10 / .net core 2.1 / centos7 變成web程序 1.在新建的as

Asp.net core實戰4: 建立你的第一個Asp.net core專案

我們劃分為四個步驟建立你的第一個專案: 1.根據官方提供的模板生成一個專案 2.使用NuGet修復所缺少的第三方庫 3.Build你的專案 4.Run你的專案   第一步:建立專案(請自行下載安裝Asp.net core SDK 2.0及Visual Studio2

ASP.NET Core 實戰: .NET Core 2.0 專案升級到 .NET Core 2.1

 一、前言    最近一兩個星期,加班,然後回去後弄自己的部落格,把自己的電腦從 Windows 10 改到 Ubuntu 18.10 又弄回 Windows 10,原本計劃的學習 Vue 中生命週期的相關知識目前也沒有任何的進展,嗯,罪過罪過。看了眼時間,11月也快要結束了,準備補上一

CentOS&.NET Core初試-4-安裝守護服務(Supervisor)

系列目錄 Supervisor是什麼? Supervisor 是一個用 Python 寫的程序管理工具,可以很方便的用來啟動、重啟、關閉程序(不僅僅是 Python 程序)。除了對單個程序的控制,還可以同時啟動、關閉多個程序,比如很不幸的伺服器出問題導致所有應用程式都被殺死,此時可以用 supervisor

asp.net core 系列 4 路由(上)

fin sco 放置 style mvc 三種 aspnet 用戶 方式 一. 概述   介紹asp.net core路由時,我初步想了下,分幾篇來說明。 路由的知識點很多,參考了官方文檔提取出一些重要的知識點來說。 在ASP.NET Core中是使用路由中間件來