Asp.net core logging 日志


1 基本概念

    Dotnet core 一個重要的特征是 Dependency injection ,中文一般是依賴注入,可以簡單理解為一個集合,在應用程序啟動時,定義各種具體的實現類型並將其放到集合中;在應用程序運行時,從集合中取出之前放入的類型。

    Logging 的實現就采用這種方式,寫日志分為兩步:創建寫日志的對象;用創建的對象寫日志。ILoggerProvider 創建寫日志的對象 ILogger ,即在應用程序啟動時,把實現了 ILoggerProvider 接口的類型放到集合中,在應用程序運行期間,需要寫日志,先去集合中取 ILoggerProvider ,使用其創建 ILogger 對象,然后就可以寫日志了。

1.1 ILogger

    寫日志的定義:

        void Log<TState>(LogLevel logLevel, EventId eventId, TState state, Exception exception, Func<TState, Exception, string> formatter);

    除了 logLevel 有點熟,其它都感覺無用,只是我們並沒有直接使用,並不是其真的無用。

1.2 ILoggerProvider

創建寫日志對接定義:

        ILogger CreateLogger(string categoryName);

    通過定義可以知道,所有的 ILogger 對象都有 categoryName 屬性。屬性值不能為 Null。

    到這里其實可以寫日志了,也僅只是寫日志而已,還有兩個比較重要的問題:1 寫的日志在哪里可以看?2 如何管理寫日志?

    問題1 是由 ILoggerProvider 接口的實現來決定,官方的實現有:Console 、Debug 、EventSource 、EventLog 、TraceSource 、Azure App Service,還有一些第三方實現,如此我們自己也是可以實現的。

    例如 ConsoleLoggerProvider 是將日志在命令行中打印出來,如果是控制台程序或者是 self host 啟動 web 程序便可以在命令行中看到打印的日志信息。

    問題2由 log Level、EventId、Logger Provider、Log filtering、Log category、Log scopes 合作解決。好像是很復雜,其實比較簡單。

1.3 Log Level

    定義如下,數值越大級別越高。:

Trace = 0

Debug = 1

Information = 2

Warning = 3

Error = 4

Critical = 5

None = 6

    例如:

_logger.LogWarning(LoggingEvents.GetItemNotFound, "GetById({ID}) NOT FOUND", id);

    日志的 logLevel 是 Warning ,eventId 是的 GetItemNotFound,內容是“GetById({ID}) NOT FOUND”,這個對應接口定義中 formatter 的返回值 string。

2 log filtering 說明

    為了說明日志過濾,先說明下日志的整體框架,在應用程序啟動時,可以注冊多個不同的 ILoggerProvider 實現,而在寫日志時,只調用一次寫,但所有注冊的 ILoggerProvider 都能收到寫的日志,這背后是由框架實現的。具體的簡單點說,我們調用 log()后,它再遍歷所有注冊的 ILoggerProvider ,再分別調用它們的 log()方法。

    這樣在一個正常的系統中會有多個 ILoggerProvider 實現,而每個 ILoggerProvider 創建的 ILogger 又有一個類別 category;也就是說在調用log()寫日志時,ILogger 對象具有 Provider 和 Category,這點很重要!

    而過濾便是針對 Provider 和 Category 設置的。

2.1 過濾類型

    可以為某個 Provider 的某個 Category 設置一條過濾規則,也可以針對所有的Provider 和所有的Category 設置一條過濾規則。

    這樣過濾規則的類型也就可以如下所示:

表1:

 

Provider 限定

Provider 不限定

Category 限定

1

3

Category 不限定

2

4

2.2 過濾規則

(1)minimum level

    最低級別的意思是框架只會將高於(包括等於)此級別的日志傳遞給 Provider,進而 Provider 調用 log()方法處理日志。

(2)Filter functions

Func<string, LogLevel, bool> categoryLevelFilter

    這是委托簽名,入參是類別 Category 名稱和寫日志的級別,返回是 bool 類型,也就是說可以根據類別和消息級別來決定是否寫日志。

2.3 最佳過濾規則

    至此,我可以可以添加一條過濾規則,其簽名如下:

LoggerFilterRule(string providerName, string categoryName, LogLevel? logLevel, Func<string, string, LogLevel, bool> filter)

    比如:.AddFilter<ConsoleLoggerProvider>("System", LogLevel.Critical) 便等同於:

LoggerFilterRule("ConsoleLoggerProvider", "System", LogLevel.Critical,null)

    如果我們添加了多條過濾規則,但每個 Provider 只能對應一條過濾規則,這時應當使用以下規則:

(1)1>2>3>4 (參考表1)

(2)同一等級后注冊高於先注冊

(3)無可用過濾規則,則不過濾

    補充,在設置過濾規則時可以同時設置 minimum level 和 Filter functions,先執行minimum level,如有必要再執行 Filter functions。

    在匹配類別 Category 時,不是字符串相同比較,是字符串前綴包含即可。

    正常的系統,對象間關系簡單示意如下:

 

圖1

 

3 配置示例

    設置過濾規則有兩種方式:代碼和配置文件

3.1 代碼

ILoggingBuilder AddFilter<T>(this ILoggingBuilder builder, string category, LogLevel level)

    還有一些類似的簽名,T 是 Provider 類型,可選, category 必選。可以實現表1中:1、2、3類型設置,4類型沒有找到(應該是沒有提供)

3.2 配置文件

{

  "Logging": {

    "LogLevel": {

      "Default": "Trace",

      "Microsoft": "Critical"

    },

    "Console": {

      "LogLevel": {

        "Default": "Debug",

        "System": "Warning"

      }

    }

  }

}

    這是一實例配置,從上往下定義了4個過來規則,其對應的表1中的級別分別是:4、3、2、1

4 實踐一下

(1)注冊 Provider

(2)注冊 Filter

(3)獲取 ILogger

(4)寫日志

我沒有貼代碼,請參考下面的git中的SampleApp。

5 參考

https://docs.microsoft.com/en-us/aspnet/core/fundamentals/logging/?view=aspnetcore-2.1

https://github.com/aspnet/Logging

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM