將Log資料存放到資料庫(MS SQL Server)中
在上一篇文章「使用NLog - Advanced .NET Logging (1)」裡面,我們是把Log資料給存放到文字檔中,
文章範例程式中的NLog.Config,有兩個target type是使用了File而另一個是使用EventLog,
其實NLog的taget有預設提供了多達25種,但不見得每個都有機會去使用到,
而且你還可以依據NLog提供的API,讓你可以建立你自己想要的target,
除了已經介紹的File與EventLog外,最常用的也是最多人想要使用的就是「Database」。
以下就將會介紹如何修改target設定,把Log資料存放到資料庫中。
本篇文章將會以MS SQL Server為存放的裝置。
NLog Documentation - Database target
http://nlog-project.org/wiki/Database_target
我們先看看NLog所提供的設定範例:
<?xml version="1.0" ?>
<nlog autoReload="true">
<targets>
<target name="database" type="Database">
<dbprovider>mssql</dbprovider>
<!-- database connection parameters -->
<!-- alternatively you could provide a single 'connectionstring' parameter -->
<dbhost>.</dbhost>
<dbdatabase>NLogDatabase</dbdatabase>
<dbusername>nloguser</dbusername>
<dbpassword>nlogpassword</dbpassword>
<commandText>
insert into LogTable(time_stamp,level,logger,message) values(@time_stamp, @level, @logger, @message);
</commandText>
<parameter name="@time_stamp" layout="${date}" />
<parameter name="@level" layout="${level}" />
<parameter name="@logger" layout="${logger}" />
<parameter name="@message" layout="${message}" />
</target>
</targets>
<rules>
<logger name="*" minlevel="Debug" appendTo="database" />
</rules>
</nlog>
以下是NLog所提供的LogTable Schema:
預設事先建立DB「NLogDatabase」以及Table「LogTable」,DB名稱以及Table名稱都可以修改為自己想要的名稱,
修改後也請務必記得要去修改Database target的資料。
use master;
go
create database NLogDatabase
/*
on primary (name='NLogDatabase
filename='***insert_path_here***\NLogDatabase.mdf',
size=10MB)
log on (name='NLogDatabase_log',
filename='***insert_path_here***\NLogDatabase_log.ldf',
size=10MB)
*/
go
exec sp_addlogin 'nloguser','nlogpassword',NLogDatabase
go
use NLogDatabase;
go
create table LogTable
(
sequence_id integer not null primary key identity(1,1),
time_stamp datetime not null,
level varchar(5) not null,
logger varchar(80) not null,
message varchar(4095) not null,
)
go
exec sp_grantdbaccess 'nloguser','nloguser'
go
grant insert,select on LogTable to nloguser
go
將上面的NLog.Config設定複製貼上你的NLog.Config,然後執行T-SQL指令後,先別急著去執行你的網站,
先說明一下NLog的Database target設定,
dbProvider:
預設使用MS SQL Server的話,可以是「mssql」也可以是「sqlserver」「microsoft」「msde」,
如果你是使用其他類型的資料庫,就需要你所使用的資料庫的database provider名稱,例如NLog文件就這樣寫著:
The parameter name should be a provider invariant name as registered in machine.config or app.config. Common values are:
(Note that provider invariant names are not supported on .NET Compact Framework). Alternatively the parameter value can be be a fully qualified name of the provider connection type (class implementing IDbConnection) or one of the following tokens:
- System.Data.SqlClient -
- System.Data.SqlServerCe.3.5 -
- System.Data.OracleClient - (deprecated in .NET Framework 4)
- Oracle.DataAccess.Client -
- System.Data.SQLite -
- Npgsql -
- MySql.Data.MySqlClient -
- sqlserver, mssql, microsoft or msde - SQL Server Data Provider
- oledb - OLEDB Data Provider
- odbc - ODBC Data Provider
假如你的資料庫是使用Oracle Native的話,那麼dbProvider就會是:
dbProvider="System.Data.OracleClient.OracleConnection,System.Data.OracleClient, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"
dbhost, dbdatabase, dbusername, dbpassword:
dbhost:你所使用的資料庫位置,可以輸入host名稱,但是不能接受IP
dbdatabase:DB名稱
dbusername:DB使用者名稱
dbpassword:DB使用者密碼
其實上面的NLog.Config中已經說明,你也可以使用「connectionString」的方式輸入資料庫連線,取代上面四個屬性,
<!-- database connection parameters -->
<!-- alternatively you could provide a single 'connectionstring' parameter -->
使用個別屬性設定:
<dbhost>localhost</dbhost><dbdatabase>NLogDatabase</dbdatabase><dbusername>nloguser</dbusername><dbpassword>nlogpassword</dbpassword>
使用connectionString屬性:
這邊的Data Source也無法指定IP
<connectionString>Data Source=localhost;Initial Catalog=NLogDatabase;Persist Security Info=True;User ID=nloguser;Password=nlogpassword;MultipleActiveResultSets=True;</connectionString>
commandText, parameter:
commandText:就要把資料寫入資料庫的指令碼(SQL Statement),而這個部分需要與parameter來配合。
parameter:參數,這邊的參數名稱是要給commandText的Values使用,而資料的內容則是需要搭配layout renderers。
<commandText>insert into LogTable(time_stamp,level,logger,message) values(@time_stamp, @level, @logger, @message);</commandText><parameter name="@time_stamp" layout="${date}" /><parameter name="@level" layout="${level}" /><parameter name="@logger" layout="${logger}" /><parameter name="@message" layout="${message}" />
在commandText的SQL Statement裡面,Values的四個parameter是對應資料表LogTable的四個欄位,
而四個parameter則分別以Layout Renderers定義的格式帶入,
看我們在LogTable中的欄位騎定義是什麼,再去選擇要放入的資料內容,
參考:NLog Documentation – Layout Renderers
像上面的四個parameter所使用的layout分別是:
${date}:目前記錄的日期與時間
${level}:Log資料的等級
${logger}:logger的名稱
${message}:Log的訊息內容
將資料庫連線設定修改好並重新建置方案之後,直接執行網站來看看,
以下就是實際存入資料庫的內容:
而這是有記錄到自訂Fatal訊息的內容:
所以,要存哪些Log資料內容到資料庫裡面,是可以讓我們自己去決定的,可以依據實際的狀況來決定。
如果說我們要自訂Table、Column,自己定義要存放哪些資料,需要注意幾點:
1. 正確的授與資料庫使用者操作權限
如果你一開始是用NLog範例所提供的Create_nlog_database.sql來建立DB與Table的話,
因為預設建立的使用者 nloguser 對 LogTable 只被Grant Select 與Insert 兩種操作,
如要另外建立Table來記錄資料的話,也讓 nloguser (或是另外建立的user) Grant Select 與 Insert 就可以。
2. 使用正確的方式記錄Log
程式中的try…catch…,使用logger來記錄exception的方法可以改用以下的方法:
- TraceException()
- DebugException()
- InfoException()
- WarnException()
- ErrorException()
- FatalException()
- LogException() – takes log level as a parameter
3. 加強對於${exception} layout的認識
${exception} 可以增加一些條件格式,可以很清楚的知道要記錄Exception的哪些資料,
例如:${exception:format=type} 這可以記錄到Exception的類別。
例如:${exception:stacktrace} 會記錄Exception內的stacktrace資訊。
參考:
NLog Documentation - Exception layout renderer
以下是調整後的Database target設定內容:
在Table [ NLog ] 中,我還多增加了一個 [ Detail ] 欄位,用來記錄Exception的完整訊息。
<target name="database" type="Database"><dbprovider>mssql</dbprovider><connectionString>Data Source=localhost;Initial Catalog=NLogDatabase;Persist Security Info=True;User ID=nloguser;Password=nlogpassword;MultipleActiveResultSets=True;</connectionString><commandText>insert into NLog (time_stamp, level, host, type, source, logger, message, stacktrace, Detail) Values(@time_stamp, @level, @host, @type, @source, @logger, @message, @stacktrace, @detail);</commandText><parameter name="@time_stamp" layout="${date}" /><parameter name="@level" layout="${level}" /><parameter name="@host" layout="${machinename}" /><parameter name="@type" layout="${exception:format=type}" /><parameter name="@source" layout="${callsite:className=true}" /><parameter name="@logger" layout="${logger}" /><parameter name="@message" layout="${message}" /><parameter name="@stacktrace" layout="${exception:stacktrace}" /><parameter name="@detail" layout="${exception:format=tostring}" /></target>
而實際執行網站後,在資料庫的Table [ NLog ] 中的記錄:
大致上NLog使用Database Target的基本設定方式就介紹到這裡,其實Database Taget或是Target還有很多地方可以在加以說明,
所以下一篇文章中會再針對Database Target的一些進階設定做說明。
參考連結:
NLog Documentation – Configuration file
NLog Documentation – Database target
NLog Documentation – Layout renderers
NLog Documentation – Exception layout render
NLog Documentation – Exception logging enhancements
NLog Documentation – How to property log exceptions?
以上
Dear m大:
回覆刪除請教一下您在NLogDB內新增的欄位型態及長度大小怎麼開
可否給個建議
謝謝
我在本文裡有提供 LogTable Schema,每個欄位的資料型態與長度大小都有載明。
刪除或者是在以下 NLog 的 GitHub 中也有提供,
https://github.com/jkowalski/NLog/tree/master/examples/targets/Configuration%20File/Database/MSSQL
如果說是要這篇文章最後的進階 NLog LogTable Schema 的話,在 twMVC 官網中的活動記錄「2012_06_14 攻略 ASP.NET MVC ─ 從無到有 與 偵測監控」http://mvc.tw/Event/2012/6/14
網頁下面的範例程式「ASP.NET MVC 偵錯與監控 範例下載」則是有提供。
謝謝大大
回覆刪除看完這系列的文章
受益良多
很高興能夠幫助到你。^_^
刪除請問 文中的
回覆刪除dbhost:你所使用的資料庫位置,可以輸入host名稱,但是不能接受IP
但我輪入IP卻是可以連線的耶
Hello
刪除因為這篇文章已經快五年了,這五年的技術有所更迭與套件功能更新,
所以與你目前所使用的最新版本內容會有所差異,這部分還需要以官網所公布的技術文件為主。