日志ILog(文件日志/控制台日志/控件日志/网络日志)
日志組件是NewLife系列組件最早最基礎,同時也是流血流淚最多的一個模塊,它的底蘊定能感動每一個用戶!
沒有日志的應用系統是不完整的。系統遇到啥問題,翻日志看看當時上下文,實在分析不出問題,修改代碼再打幾個日志……這是每一個程序員的日常寫照。
不少同學喜歡調試程序,但是聽過“薛定諤的貓”這個故事的人不多。有時候程序跑起來沒問題,調試就有問題;有時候跑起來有問題,調試就沒有問題。就像是薛定諤的貓,測不準原理,調試觀察本身干涉了程序運行。這個時候就需要看日志。
單片機嵌入式設備、安卓移動應用、Linux嵌入式應用,雖然都可以在線調試,但也會有許多不方便的地方。如果能夠配合使用日志,將會事半功倍。
Nuget包:NewLife.Core
源碼地址:
https://github.com/NewLifeX/X/tree/master/NewLife.Core/Log
Get Started
新建控制臺項目 ConsoleApp1 ,放到 D:\Test,其它目錄也可以
從Nuget引用 NewLife.Core ,安裝最新版本。
打開Program.cs的Main函數,寫入一下代碼
XTrace.UseConsole();XTrace.WriteLine("Hello NewLife!");點擊XTrace左邊圖標,可選“using NewLife.Log;”自動添加命名空間引用。
點擊上方綠色啟動三角符號,或者按下F5,啟動應用程序。
可以看到打開一個控制臺窗口,并輸入一行日志
13:15:06.270 1 N - Hello NewLife!這就是我們前面代碼輸出的內容:XTrace.WriteLine("Hello NewLife!");
這也是最簡單最常見的日志用法:XTrace.WriteLine
XTrace是靜態跟蹤類,WriteLine等日志輸出方法,本質上是調用實現了ILog接口的XTrace.Log。
日志接口ILog
ILog是日志輸出標準接口
/// <summary>寫日志</summary> /// <param name="level">日志級別</param> /// <param name="format">格式化字符串</param> /// <param name="args">格式化參數</param> void Write(LogLevel level, String format, params Object?[] args);/// <summary>調試日志</summary> /// <param name="format">格式化字符串</param> /// <param name="args">格式化參數</param> void Debug(String format, params Object?[] args);/// <summary>信息日志</summary> /// <param name="format">格式化字符串</param> /// <param name="args">格式化參數</param> void Info(String format, params Object?[] args);/// <summary>警告日志</summary> /// <param name="format">格式化字符串</param> /// <param name="args">格式化參數</param> void Warn(String format, params Object?[] args);/// <summary>錯誤日志</summary> /// <param name="format">格式化字符串</param> /// <param name="args">格式化參數</param> void Error(String format, params Object?[] args);/// <summary>嚴重錯誤日志</summary> /// <param name="format">格式化字符串</param> /// <param name="args">格式化參數</param> void Fatal(String format, params Object?[] args);/// <summary>是否啟用日志</summary> Boolean Enable { get; set; }/// <summary>日志等級,只輸出大于等于該級別的日志,默認Info</summary> LogLevel Level { get; set; }Write核心方法,很少使用,一般都使用 Info/Debug/Warn/Error/Fatal 等接口,最終都是調用Write,只是日志等級不同。
日志對象可以獨立控制是否啟用,以及日志等級Level。
已有日志等級:
/// <summary>日志等級</summary> public enum LogLevel : System.Byte {/// <summary>打開所有日志記錄</summary>All = 0,/// <summary>最低調試。細粒度信息事件對調試應用程序非常有幫助</summary>Debug,/// <summary>普通消息。在粗粒度級別上突出強調應用程序的運行過程</summary>Info,/// <summary>警告</summary>Warn,/// <summary>錯誤</summary>Error,/// <summary>嚴重錯誤</summary>Fatal,/// <summary>關閉所有日志記錄</summary>Off = 0xFF }文件日志
文本文件日志是最重要的日志,也是XTrace.Log的默認實現。
文本文件日志是把日志逐行輸出到文本文件中,每天一個文件。
如果想要獨立存儲某個模塊的日志,可以實例化一個專屬的TextFileLog對象。推薦使用Create創建。
/// <summary>每個目錄的日志實例應該只有一個,所以采用靜態創建</summary> /// <param name="path">日志目錄或日志文件路徑</param> /// <param name="fileFormat"></param> /// <returns></returns> public static TextFileLog Create(String path, String fileFormat = null);/// <summary>每個目錄的日志實例應該只有一個,所以采用靜態創建</summary> /// <param name="path">日志目錄或日志文件路徑</param> /// <returns></returns> public static TextFileLog CreateFile(String path);文件日志內部有隊列、延遲關閉等復雜邏輯,強烈建議使用單例,Create可確保單例實現。
文本文件日志主要特性:
每天一個文件,例如 2021_06_25.log
每個文件最大10M,(可在core.config中配置LogFileMaxBytes),超過后產生新的日志文件,例如 2021_06_25_2.log
日志目錄為Log子目錄,(可配置LogPath)
日志目錄中最多只保存最新100個日志文件,(可配置LogFileBackups)
日志等級,可配置LogLevel,默認Info,大于等于該等級才輸出日志到文件
日志文件格式,可配置LogFileFormat,默認 {0:yyyy_MM_dd}.log,也可以按照日志等級區分目錄,例如 {1}/{0:yyyy_MM_dd}.log
日志寫入使用隊列實現,避免影響應用層性能
如果連續5秒沒有日志寫入,則自動關閉日志文件句柄,此時用戶可以根據需要移動或刪除日志文件
這里的10M和100個,最大日志占用1G,可以有效的避免異常信息寫爆磁盤!(說多都是淚……)
來看看上面Demo的日志文件
#Software: ConsoleApp1 #ProcessID: 38144 x64 #AppDomain: ConsoleApp1 #FileName: D:\Test\ConsoleApp1\ConsoleApp1\bin\Debug\net5.0\ConsoleApp1.exe #BaseDirectory: D:\Test\ConsoleApp1\ConsoleApp1\bin\Debug\net5.0\ #TempPath: C:\Users\Stone\AppData\Local\Temp\ #CommandLine: D:\Test\ConsoleApp1\ConsoleApp1\bin\Debug\net5.0\ConsoleApp1.dll #ApplicationType: Console #CLR: 5.0.7, .NET 5.0.7 #OS: Microsoft Windows NT 10.0.19042.0, X6/Stone #CPU: 8 #GC: IsServerGC=False, LatencyMode=Interactive #ThreadPool: Min=32/32, Max=32767/1000, Available=32766/1000 #Date: 2021-06-25 #字段: 時間 線程ID 線程池Y/網頁W/普通N/定時T 線程名/任務ID 消息內容 #Fields: Time ThreadID Kind Name Message 13:42:42.463 1 N - NewLife.Core v8.10.2021.0604 Build 2021-06-07 09:05:06 .NETCoreApp,Version=v5.0 13:42:42.465 1 N - X組件核心庫 ?2002-2021 NewLife 13:42:42.466 1 N - ConsoleApp1 v1.0.0 Build 2000-01-01 .NETCoreApp,Version=v5.0 13:42:42.466 1 N - ConsoleApp1 13:42:42.466 1 N - Hello NewLife!可以看到,日志文件非常完善,還有一個很完整的日志頭。
文本日志文件格式,參考了多款微軟產品,頭部井號#隔開的行是注釋行,用于說明情況。
通過日志頭,可以了解到一下信息:
軟件名ConsoleApp1,取自進程名
進程Id,是否64位進程
應用程序域,這個現在沒有太多意義了
執行文件名,全路徑
基準目錄,全路徑。這個非常重要,很多人的控制臺程序正常,改為系統服務以后異常,很大可能性就是因為這個基準目錄變成了操作系統目錄。
臨時目錄,X組件有時候需要使用臨時目錄
命令行參數
應用類型,.NETCore里面基本上都是Console了,有點難以區分WinForm和Web
.NET版本,CLR版本
操作系統、CPU等
GC設置
線程池設置值。
日志字段格式介紹
字段格式:
時間,時分秒和毫秒。這里的毫秒特別重要,可以精確知道各個操作執行耗時情況
線程Id,如果每個日志所屬線程不加以區分,在多線程環境下就會一團糟
線程類型,線程池Y、網頁W、普通N、定時T
線程名/任務Id
日志內容
由此可見,日志組件特別適用于分析多線程問題。
設計如此詳盡的日志頭,主要為了能夠準確記錄程序的執行上下文環境,特別對于客戶端應用來說尤為重要!
控制臺日志
前面例程中,Main函數開頭有一行 XTrace.UseConsole() ,意思是使用控制臺日志。如果沒有這一行,XTrace.WriteLine默認只會寫入文本文件日志。加上后,同時寫文件和控制臺。
控制臺日志ConsoleLog沒有日志頭,其它跟文本文件日志一樣,輸出時間、線程信息和日志內容。
控制臺日志多了個彩色顯示,不同線程以不同顏色區分,便于快速區分同一個線程的日志。受制于控制臺顏色樣本不足,某些情況下不同線程可能使用相同的顏色。內置10種顏色,線程Id對顏色個數取余。
除了WinForm和早期ASP.Net,否則一般都使用 XTrace.UseControle() 把日志同步輸出到控制臺。對應用性能有嚴格要求時,可以注意這一行關閉控制臺日志。
切記!!!控制臺日志不宜過多,否則會嚴重影響應用性能,因為控制臺數據內部帶有鎖需要排隊。
控件日志
對于WinForm應用來說,希望能夠把日志輸出到某個富文本框之中。控件日志TextControlLog為此而生!
XTrace中有擴展方法 UseWinFormControl :
/// <summary>在WinForm控件上輸出日志,主要考慮非UI線程操作</summary> /// <remarks>不是常用功能,為了避免干擾常用功能,保持UseWinForm開頭</remarks> /// <param name="control">要綁定日志輸出的WinForm控件</param> /// <param name="useFileLog">是否同時使用文件日志,默認使用</param> /// <param name="maxLines">最大行數</param> public static void UseWinFormControl(this Control control, Boolean useFileLog = true, Int32 maxLines = 1000)在碼神工具 NewLife.XCoder 的網絡調試工具中,FrmMain_Load 有以下代碼:
txtReceive.UseWinFormControl();這里的txtReceive是富文本框RichTextBox,負責數據接收區,同時用于顯示日志。
因此,UseWinFormControl 用于把日志重定向到富文本框,第二參數useFileLog指定繼續寫文件日志。
網絡日志
NewLife.Core 組件也支持Android和iOS開發(基于Xamarin),由于設備上的日志很不好實時查看,因而設計了網絡日志。NetworkLog通過UDP協議把日志發送到局域網某個目標地址。
配置文件core.config中指定NetworkLog配置項,例如 udp://10.0.0.3:514 ,也可以使用廣播地址 udp://255.255.255.255:514 。然后在開發機 10.0.0.3 上開一個碼神工具,網絡工具監聽UDP514端口即可接收日志。
嵌入式Linux應用開發也可以使用同樣辦法。
網絡日志降低了我們對移動應用和嵌入式應用的調試依賴。
星塵日志中心
網絡日志還有一個隱藏技能,core.config 的 NetworkLog 填寫http地址時,支持星塵日志中心。例如 http://star.newlifex.com:6600/log。
網絡日志內部使用隊列緩沖數據,按批發送到星塵服務端,服務端分表分庫存儲。
總結
以上是生活随笔為你收集整理的日志ILog(文件日志/控制台日志/控件日志/网络日志)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: [翻译]Go与C#的比较,第二篇:垃圾回
- 下一篇: .NET 容器环境下创建应用 dump