⑴ 如何利用log4Net自定義屬性配置功能記錄完整的日誌信息
如何利用log4Net自定義屬性配置功能記錄完整的日誌信息
log4Net作為專業的log記錄控制項,對於它的強大功能大家一定不陌生。下面我將詳細介紹如何利用其自定義屬性,讓日誌信息更完整。
一,創建測試工程,log4Net組件可以自己從網上下載,也可通過Nuget進行安裝。
二,創建日誌模型及資料庫表,因為我們的日誌信息可以輸出為文本,也可以輸出到資料庫。
三,添加MyLayout,MyPatternConverter類擴展PatternLayout。
四,添加Log4Net.config文件,進行輸入方式定義。
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<configSections>
<section name="log4net" type="log4net.Config.,log4net"/>
</configSections>
<log4net>
<!-- ConversionPattern 解釋
%m(message):輸出的日誌消息,如ILog.Debug(…)輸出的一條消息
%n(new line):換行
%d(datetime):輸出當前語句運行的時刻
%r(run time):輸出程序從運行到執行到當前語句時消耗的毫秒數
%t(thread id):當前語句所在的線程ID
%p(priority): 日誌的當前優先順序別,即DEBUG、INFO、WARN…等
%c(class):當前日誌對象的名稱
%L:輸出語句所在的行號
%F:輸出語句所在的文件名
%-數字:表示該項的最小長度,如果不夠,則用空格填充
-->
<!--定義輸出到控制台命令行中-->
<logger name="myLogger">
<level value="ALL"/>
<appender-ref ref="ConsoleAppender" />
</logger>
<!--定義輸出到控制台命令行中-->
<appender name="ConsoleAppender" type="log4net.Appender.ConsoleAppender">
<layout type="Log4NetTest.MyLayout">
<param name="ConversionPattern" value="日誌時間:%d %n日誌級別:%-5p %n用 戶 ID:%Property{UserID} %n用戶姓名:%Property{UserName} %n日誌信息:%Property{Message} %n異常信息:%exception %n%n" />
</layout>
</appender>
<!--定義輸出到windows事件中-->
<appender name="WindowsAppender" type="log4net.Appender.EventLogAppender">
<layout type="Log4NetTest.MyLayout">
<param name="ConversionPattern" value="日誌時間:%d %n日誌級別:%-5p %n用 戶 ID:%Property{UserID} %n用戶姓名:%Property{UserName} %n日誌信息:%Property{Message} %n異常信息:%exception %n%n" />
</layout>
</appender>
<!--定義輸出到文件中-->
<appender name="TextAppender" type="log4net.Appender.RollingFileAppender">
<param name="File" value="Log\\" />
<param name="AppendToFile" value="true" />
<param name="MaxFileSize" value="10240" />
<param name="MaxSizeRollBackups" value="100" />
<param name="StaticLogFileName" value="false" />
<param name="DatePattern" value="yyyyMMdd" />
<param name="RollingStyle" value="Date" />
<layout type="Log4NetTest.MyLayout">
<param name="ConversionPattern" value="日誌時間:%d %n日誌級別:%-5p %n用 戶 ID:%Property{UserID} %n用戶姓名:%Property{UserName} %n日誌信息:%Property{Message} %n異常信息:%exception %n%n" />
</layout>
</appender>
<!--定義輸出到資料庫-->
<appender name="DataBaseAppender" type="log4net.Appender.AdoNetAppender">
<!--日誌緩存寫入條數-->
<bufferSize value="1" />
<!--日誌資料庫連接串-->
<connectionType value="System.Data.SqlClient.SqlConnection, System.Data, Version=1.0.3300.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" />
<connectionString value="data source=.\SQL2008;initial catalog=Demo;integrated security=false;persist security info=True;User ID=sa;Password=1qaz" />
<!--日誌資料庫腳本-->
<commandText value="INSERT INTO LogInfo ([LogDate],[LogLevel],[UserId],[UserName],[Message],[Exception]) VALUES (@LogDate, @LogLevel,@UserId,@UserName, @Message, @Exception)" />
<!--日誌時間LogDate -->
<parameter>
<parameterName value="@LogDate" />
<dbType value="String" />
<size value="30" />
<layout type="log4net.Layout.PatternLayout">
<conversionPattern value="%date{yyyy-MM-dd HH:mm:ss}" />
</layout>
</parameter>
<!--日誌類型LogLevel -->
<parameter>
<parameterName value="@LogLevel" />
<dbType value="String" />
<size value="10" />
<layout type="log4net.Layout.PatternLayout">
<conversionPattern value="%level" />
</layout>
</parameter>
<!--自定義UserId -->
<parameter>
<parameterName value="@UserId" />
<dbType value="String" />
<size value="20" />
<layout type="Log4NetTest.MyLayout">
<conversionPattern value="%Property{UserID}" />
</layout>
</parameter>
<!--自定義UserName -->
<parameter>
<parameterName value="@UserName" />
<dbType value="String" />
<size value="50" />
<layout type="Log4NetTest.MyLayout">
<conversionPattern value="%Property{UserName}" />
</layout>
</parameter>
<!--自定義Message -->
<parameter>
<parameterName value="@Message" />
<dbType value="String" />
<size value="200" />
<layout type="Log4NetTest.MyLayout">
<conversionPattern value="%Property{Message}" />
</layout>
</parameter>
<!--異常信息Exception -->
<parameter>
<parameterName value="@Exception" />
<dbType value="String" />
<size value="4000" />
<layout type="log4net.Layout.ExceptionLayout" />
</parameter>
</appender>
</log4net>
</configuration>
五,添加LogHelper.cs類進行各自信息的寫入操作。
using System;
using System.Diagnostics;
using System.IO;
using System.Windows.Forms;
using log4net;
[assembly: log4net.Config.XmlConfigurator(Watch = true)]
namespace Log4NetTest
{
public class LogHelper
{
/// <summary>
/// LoggerName
/// </summary>
public static string LoggerName = string.Empty;
/// <summary>
/// 用戶ID
/// </summary>
public static string UserID = string.Empty;
/// <summary>
/// 用戶名稱
/// </summary>
public static string UserName = string.Empty;
private static ILog iLog;
private static LogEntity logEntity;
/// <summary>
/// 介面
/// </summary>
private static ILog log
{
get
{
string path = Application.StartupPath + @"\Log4Net.config";
log4net.Config.XmlConfigurator.Configure(new FileInfo(path));
if (iLog == null)
{
iLog = log4net.LogManager.GetLogger(LoggerName);
}
else
{
if (iLog.Logger.Name != LoggerName)
{
iLog = log4net.LogManager.GetLogger(LoggerName);
}
}
return iLog;
}
}
/// <summary>
/// 構造消息實體
/// </summary>
/// <param name="message"></param>
/// <returns></returns>
private static LogEntity BuildMessageMode(string message)
{
if (logEntity == null)
{
logEntity = new LogEntity();
logEntity.UserID = UserID;
logEntity.UserName = UserName;
logEntity.Message = message;
}
else
logEntity.Message = message;
return logEntity;
}
/// <summary>
/// 調試
/// </summary>
/// <param name="message">消息</param>
public static void Debug(string message)
{
if (log.IsDebugEnabled)
log.Debug(BuildMessageMode(message));
}
/// <summary>
/// 調試
/// </summary>
/// <param name="message">消息</param>
/// <param name="exception">異常</param>
public static void Debug(string message, Exception ex)
{
if (log.IsDebugEnabled)
log.Debug(BuildMessageMode(message), ex);
}
/// <summary>
/// 信息
/// </summary>
/// <param name="message">消息</param>
public static void Info(string message)
{
if (log.IsInfoEnabled)
log.Info(BuildMessageMode(message));
}
/// <summary>
/// 信息
/// </summary>
/// <param name="message">消息</param>
/// <param name="exception">異常</param>
public static void Info(string message, Exception ex)
{
if (log.IsInfoEnabled)
log.Info(BuildMessageMode(message), ex);
}
/// <summary>
/// 一般錯誤
/// </summary>
/// <param name="message">消息</param>
public static void Error(string message)
{
if (log.IsErrorEnabled)
log.Error(BuildMessageMode(message));
}
/// <summary>
/// 一般錯誤
/// </summary>
/// <param name="message">消息</param>
/// <param name="exception">異常</param>
public static void Error(string message, Exception exception)
{
if (log.IsErrorEnabled)
log.Error(BuildMessageMode(message), exception);
}
/// <summary>
/// 警告
/// </summary>
/// <param name="message">消息</param>
public static void Warn(string message)
{
if (log.IsWarnEnabled)
log.Warn(BuildMessageMode(message));
}
/// <summary>
/// 警告
/// </summary>
/// <param name="message">消息</param>
/// <param name="exception">異常</param>
public static void Warn(string message, Exception ex)
{
if (log.IsWarnEnabled)
log.Warn(BuildMessageMode(message), ex);
}
/// <summary>
/// 嚴重
/// </summary>
/// <param name="message">消息</param>
public static void Fatal(string message)
{
if (log.IsFatalEnabled)
log.Fatal(BuildMessageMode(message));
}
/// <summary>
/// 嚴重
/// </summary>
/// <param name="message">消息</param>
/// <param name="exception">異常</param>
public static void Fatal(string message, Exception ex)
{
if (log.IsFatalEnabled)
log.Fatal(BuildMessageMode(message), ex);
}
}
}
六,進行日誌效果測試,只要通過修改Log4Net.config,就可實現各種方式的輸入。
輸出到控制台:
<logger name="myLogger">
<level value="ALL"/>
<appender-ref ref="ConsoleAppender" />
</logger>
輸出到文件:
<logger name="myLogger">
<level value="ALL"/>
<appender-ref ref="TextAppender" />
</logger>
輸出到資料庫:
<logger name="myLogger">
<level value="ALL"/>
<appender-ref ref="DataBaseAppender" />
</logger>
⑵ log4net配置文件解析
<log net>
<root>
<level value= ALL />
<appender ref ref= rollingFile />
</root>
<appender name= rollingFile type= log net Appender RollingFileAppender log net >
<param name= File value= log txt />
<param name= AppendToFile value= false />
<param name= RollingStyle value= Date />
<param name= DatePattern value= yyyy MM dd />
<param name= StaticLogFileName value= true />
<layout type= log net Layout PatternLayout log net >
<param name= ConversionPattern value= %d [%t] % p %c %m%n />
<param name= Header value= header />
<param name= Footer value= footer />
</layout>
</appender>
<appender name= consoleApp type= log net Appender ConsoleAppender log net >
<layout type= log net Layout PatternLayout log net >
<param name= ConversionPattern value= %d [%t] % p %c %m%n />
</layout>
</appender>
<logger name= Log NetTest LogTest >
<level value= DEBUG />
<appender ref ref= rollingFile />
<appender ref ref= coloredConsoleApp />
<appender ref ref= SystemEvent />
</logger>
</log net>
log net配置節的XSD層次如下
<log net>
<root><level /><appender ref ref= /></root>
<appender name= type= Appender的完全限定類名 >
<param name= value= />
<layout type= log net Layout PatternLayout log net >
<param name= value= />
</layout>
</appender>
<logger>
<level value= />
<appender ref ref= />
</logger>
log net是log net配置節的根標記
root標記定義一個根級別的記錄者 log net的記錄者採用層級組織的 每一個LOGGER(ROOT也是一個LOGGER 只不過 他是祖先而已 別的方面 跟其他LOGGER一樣) 都可以定義Level
level定義記錄的日誌級別 就是說 你要記錄哪個級別以上的日誌 級別由高往低依次是:
None
Fatal
ERROR
WARN
DEBUG
INFO
ALL
級別的定義要注意 如果你定義DEBUG 那麼低於DEBUG級別以下的信息 將不會記入日誌 啥意思呢?就是說 就算你在程序里 用()來寫入一個日誌信息 可是你在配置中指定level為DEBUG 由於INFO級別低於DEBUG 所以 不會被記入日誌 這樣的處理非常靈活
Logger還有一個配置就是appender ref了 ref是參照的意思 log net的架構非常有意思 可擴展性非常高非常值得借鑒 他分為四個要素:
logger
appender
layout
filter
logger是負責日誌的記錄者
appender提供記錄的介質
layout負責把記入的內容格式化
filter負責把內容進行篩選
可以說 整個過程就是一個日誌流水線 每個成員負責其中的一個環節
logger發出記錄信息 appender接到信息 根據內部的layout配置對記錄信息格式化 根據filter決定此信息是否被過濾掉 最後 將其序列化
因此 logger的appender ref就是定義說 LOGGER要找誰去將內容寫入磁碟 流或其他介質 因此 十分重要吧
既然是ref引用 那肯定要定義這個被引用的appender對象了呀
每個appender都代表了一個輸出介質
name屬性指定其名稱 type則是log net Appender命名空間的一個類的名稱 意思是 指定使用哪種介質
log net支持的appender類型有十幾種 最常用的有rollingFileAppender AdoNetAppender EventLogAppender FileAppender 分別把日誌記入文件 系統日誌和資料庫
除此之外 appender內的其他參數都用param標記 以key/value形式定義於其內
這里有個小提示 每一個appender log net並沒有在文檔中提出他們需要哪些參數 那麼 我們怎麼知道呢?
原來 這些param的名稱 你可以直接查對應的appender類的屬性名即可 例如 使用EventLogAppender時 通過查看類的屬性 我們知道其有
LogName ApplicationName屬性 那麼 意味著 你可以直接在這個APPENDER的param里加入以下內容:
<param name= LogName value= Application />
<param name= ApplicationName value= log netTest />
定義了appender的NAME及TYPE屬性 以及使用param為其指定參數後 一個appender就建立了 你可以使用他的名字在LOGGER的<appender ref中去 引用它 那麼 引用它的LOGGER在寫入日誌時 就是寫到了APPENDER中定義的介質中去了
一個LOGGER可以引用多個APPENDER 其結果是 同一個日誌 被同時記錄到多個介質中去 便如 同時發郵件 寫入系統日誌 發送到遠程主機 不過 雖然可以這樣做 但是還是要小心 因為 會對性能有一定的影響 除非你需要 否則 不要亂用此功能
另外 appender中可以定義可選的layout
layout的定義非常有必要 如果你不想將來看到你的日誌會感覺頭暈的話 雖然log net幫你寫入日誌 但是 日誌信息的格式卻是我們使用者自行定義的layout的type參數指定使用哪個類的定義來格式化 常用的有XmlLayout SimpleLayout PatternLayout 這個當然要根據你的需要 以及你要產生的格式來選啦 如果你要輸出成XML文檔格式 你肯定不能用simplelayout吧
layout使用param以KEY/VALUE形式定義其參數
各個Layout類使用的參數當然不一樣啦 具體的 你可以去看各個Layout類的屬性
其中 PatternLayout可以使用ConversionPattern參數來指定一個格式化字元串
以及可以指定一個Header參數 做為日誌開頭的字元串 Footer來指定結尾字元串
這里有一個小技巧 日誌中開頭和結尾總想產生回車符吧 雖然logger在寫入一條日誌會自動回車 可是Header和FOOTER卻不會 咋辦?用 嗎?(我從別人的BLOG上看到過)經實踐 會原樣定改日誌 根本不會轉換 其實 我們可以用XML實體呀 使用&# ;&# ;就可以在指定位置插入一個回車換行符了
最後 像log net的文檔中說的那樣 如果你不想你的日誌文件變得很大 使讀寫的性能下降的話 建議你還是分級管理日誌 把粒度變小點 也就是說 除了定義ROOT外 最後 對每一個模塊或每一個實體 依據用途 目的 定義各自的LOGGER配置 這樣的好處是日誌被分散了 日誌文件增長就沒那麼快了 每一個LOGGER的結構跟ROOT是一模一樣的 這里不再敘述了 像前面說的那樣 如果你相讓日誌產生層級關系 你可以跟他們的NAME屬性像C#中的namespace那樣命名就可以了
要說明的是 LOGGER的定義是非必須的 只是一種建議罷了 Log net的配置中 除了必須定義一個ROOT和一個APPENDER外 其他的都是可選的
lishixin/Article/program/net/201311/11448
⑶ 在VSCode寫.netCore 踩坑記三(log4net日誌配置)
1、在vscode內輸入快捷鍵 ctrl + shift + P
選擇 「NuGet Packge Manager:add package」
安裝包:
2、創建一個helpers文件夾用於存放log類
復制以下兩個文件到項目上
1、log4net.config 文件存放在根目錄
2、LogHelper.cs 文件存放在 helpers 文件夾內
配置後當前目錄結構
修改 Program.cs 文件
---------------------------------------重點,重點來了-------------------------------------
build時.netcore不會幫你生成config配置文件(如果有辦法請指正),必須自行把log4net.config 復制到生成項目的根目錄上
⑷ log4net配置文件怎麼記錄ip跟錯誤頁地址
第一步:在項目中添加對log4net.dll的引用,這里引用版本是1.2.10.0。
第二步:程序啟動時讀取log4net的配置文件。
如果是CS程序,在根目錄的Program.cs中的Main方法中添加:
log4net.Config.XmlConfigurator.Configure();
如果是BS程序,在根目錄的Global.asax.cs(沒有新建一個)中的Application_Start方法中添加:
log4net.Config.XmlConfigurator.Configure();