C#使用log4net結(jié)合sqlite數(shù)據(jù)庫實現(xiàn)記錄日志
0 前言
為什么要把日志存到數(shù)據(jù)庫里?
因為結(jié)構(gòu)化的數(shù)據(jù)庫存儲的日志信息,可以寫專門的軟件讀取歷史日志信息,通過各種條件篩選,可操作性極大增強,有這方面需求的開發(fā)人員可以考慮。
為什么選擇SQLite?
輕量級數(shù)據(jù)庫,免安裝,數(shù)據(jù)庫的常用的基本功能都有,可以隨程序遷移到不同的電腦上使用。
1 安裝包
兩個包:
- log4net
- System.Data.SQLite
第二個包也可以使用Microsoft.Data.Sqlite
,查到的資料顯示如果環(huán)境使用的是 .NET Core 或 .NET 5+,建議使用Microsoft.Data.Sqlite
。但是我并沒有測試第二個包,可能使用上有區(qū)別。
2 下載Sqlite
如果本地沒有sqlite環(huán)境的話,需要先下載。官網(wǎng)下載鏈接
進去之后直接找各自環(huán)境對應的版本,如果是windows環(huán)境的話,直接下載下圖中標記的tool,中間那個下載鏈接是下載sqlite3.dll
,不過我并不清楚如何使用,有知道的大佬可以在評論區(qū)交流一下。
tool解壓之后有如下幾個文件,雙擊打開sqlite3.exe即可。
3 Sqlite常用命令
打開是一個命令行界面,可以使用.help查看常用的命令及解釋。
.help
創(chuàng)建數(shù)據(jù)庫文件使用.open xxx
,這條語句,如果發(fā)現(xiàn)數(shù)據(jù)庫文件存在,就會直接打開,如果不存在,就會先創(chuàng)建再打開。
.open test.db
在目錄內(nèi)可以看到創(chuàng)建的數(shù)據(jù)庫文件。(劃重點,這個文件拷到程序中就可以直接使用sqlite數(shù)據(jù)庫,充分體現(xiàn)了輕量級的魅力)
.databases
可以查詢所有數(shù)據(jù)庫文件
.tables
可以查詢所有表(我還未創(chuàng)建,所以目前還沒有表)
sql語句請自行查詢相關(guān)資料。
查詢的數(shù)據(jù)以標準格式顯示。
.header on .mode column SELECT * FROM COMPANY;
當然sqlite也有可視化的軟件,但是我目前沒用到,所以沒有下載安裝,需要的話可以自行查詢。
4 創(chuàng)建日志相關(guān)基本表
使用命令創(chuàng)建日志表,包含id(使用自增,當然可以換成uuid或者其它形式)、日期、線程號、級別(info、error這些)、記錄者、具體記錄的信息、異常信息。具體內(nèi)容要對應log4net的配置。
CREATE TABLE Log ( Id INTEGER PRIMARY KEY AUTOINCREMENT, Date DATETIME, Thread VARCHAR(255), Level VARCHAR(50), Logger VARCHAR(255), Message TEXT, Exception TEXT );
5 log4net配置
更換數(shù)據(jù)庫連接。sql語句的內(nèi)容一定要對應數(shù)據(jù)庫基本表的字段。
<configuration> <configSections> <section name="log4net" type="log4net.Config.Log4NetConfigurationSectionHandler, log4net" /> </configSections> <log4net> <appender name="AdoNetAppender" type="log4net.Appender.AdoNetAppender"> <bufferSize value="1" /> <connectionType value="System.Data.SQLite.SQLiteConnection, System.Data.SQLite" /> <connectionString value="Data Source=./database/logs.db;Version=3;" /> <commandText value="INSERT INTO Log (Date, Thread, Level, Logger, Message, Exception) VALUES (@log_date, @thread, @log_level, @logger, @message, @exception)" /> <parameter> <parameterName value="@log_date" /> <dbType value="DateTime" /> <layout type="log4net.Layout.RawTimeStampLayout" /> </parameter> <parameter> <parameterName value="@thread" /> <dbType value="String" /> <size value="255" /> <layout type="log4net.Layout.PatternLayout"> <conversionPattern value="%thread" /> </layout> </parameter> <parameter> <parameterName value="@log_level" /> <dbType value="String" /> <size value="50" /> <layout type="log4net.Layout.PatternLayout"> <conversionPattern value="%level" /> </layout> </parameter> <parameter> <parameterName value="@logger" /> <dbType value="String" /> <size value="255" /> <layout type="log4net.Layout.PatternLayout"> <conversionPattern value="%logger" /> </layout> </parameter> <parameter> <parameterName value="@message" /> <dbType value="String" /> <size value="4000" /> <layout type="log4net.Layout.PatternLayout"> <conversionPattern value="%message" /> </layout> </parameter> <parameter> <parameterName value="@exception" /> <dbType value="String" /> <size value="2000" /> <layout type="log4net.Layout.ExceptionLayout" /> </parameter> </appender> <root> <level value="ALL" /> <appender-ref ref="AdoNetAppender" /> </root> </log4net> </configuration>
6 日志記錄
把生成的db文件拷到程序里,這個文件就是記錄文件的數(shù)據(jù)庫了,其它的都不重要。當然,如果想查看數(shù)據(jù)庫的話,也可以把sqlite3.exe拷過來。
讀取log4net的配置建議寫在AssemblyInfo.cs,這樣程序啟動時會默認加載配置文件。
//Log4net配置[assembly: log4net.Config.XmlConfigurator(ConfigFile = "log4net.config", Watch = true)]
具體程序如下:
private static readonly ILog log = LogManager.GetLogger(typeof(Form1)); log.Info("這是一條info語句"); log.Warn("這是一條warn語句"); log.Error("這是一條錯誤語句", new Exception("測試異常"));
查看日志是否正常寫入數(shù)據(jù)庫。
7 使用C#程序查詢sqlite
程序如下(不過感覺GetString(index)這種方式有點別扭吧,有沒有GetString(key)的這種形式,歡迎大佬們補充)
// 構(gòu)建連接字符串 string connectionString = "Data Source=./database/SoftWareBaseLog.db;Version=3;"; // 創(chuàng)建 SQLite 連接 using (var connection = new SQLiteConnection(connectionString)) { connection.Open(); // 創(chuàng)建 SQL 命令 string sql = "SELECT Message FROM Log where Level='ERROR'"; using (var command = new SQLiteCommand(sql, connection)) { // 執(zhí)行命令并讀取數(shù)據(jù) using (var reader = command.ExecuteReader()) { while (reader.Read()) { string msg = reader.GetString(0); Console.WriteLine(msg); } } } }
8 實時顯示日志
現(xiàn)在所有日志都寫到數(shù)據(jù)庫里了,那要是還想實時顯示到界面上,當然也有很多方式實現(xiàn),不過我這里建議實時顯示可以使用log4net的自有功能。
比如我想使用winform中的listbox來實時顯示日志,可以建立一個Appender(附加),繼承于log4net的AppenderSkeleton
,這是一個抽象類,有一個抽象方法。
具體的,可以參考以下程序,這里會顯示所有的日志,如果需要過濾的話,可以在這個基礎(chǔ)上改。另外,一定一定一定要給this.Layout賦值,這是日志在界面上的顯示方式,如果沒有寫的話,就會收獲一個報錯:“A layout must be set”,去網(wǎng)上搜這條內(nèi)容,不一定能找到解決方案。
public class ListBoxAppender : AppenderSkeleton { private ListBox _ListBox; public ListBoxAppender(ListBox box) { _ListBox = box; this.Layout = new PatternLayout("%date [%thread] %-5level %logger - %message%newline"); } protected override void Append(LoggingEvent loggingEvent) { // 獲取日志信息 string logMessage = RenderLoggingEvent(loggingEvent); // 更新 UI 控件 if (_ListBox.InvokeRequired) { _ListBox.Invoke(new Action(() => AppendText(logMessage))); } else { AppendText(logMessage); } } private void AppendText(string text) { _ListBox.Items.Add(text); } }
只需要給log4net配置一次就可以使用,這樣,每次調(diào)用日志記錄,界面上的lbxLog控件就可以一直顯示最新的日志信息。
// 添加自定義 Appender var listBoxAppender = new ListBoxAppender(lbxLog); log4net.Config.BasicConfigurator.Configure(listBoxAppender);
但是,我并不建議使用log4net直接操作控件顯示日志信息,在多線程短時間寫較多日志的情況下,可能會導致軟件卡死,更佳的方式是增加緩存機制。
以上就是C#使用log4net結(jié)合sqlite數(shù)據(jù)庫實現(xiàn)記錄日志的詳細內(nèi)容,更多關(guān)于C# log4net結(jié)合sqlite記錄日志的資料請關(guān)注腳本之家其它相關(guān)文章!