Log4net 自定义错误输出
2015-01-08 10:48
357 查看
最近再做一个项目,需要跟踪错误日志。之前一直保存在txt文件中,但是由于部署服务器我们没有访问的权限。很无奈,必须得把错误日志写入数据库(还必须得加入自定义错误,比如是哪一个数据库)。由于之前没有使用过,所有参考了园子中很多大神的作品。。。不知为何,没有调通一个。觉定参考大神的作品自己写。。代码如下。
1.自定义错误模型
/// <summary>
/// 自定义错误信息模型
/// </summary>
public class LogMessage
{
/// <summary>
/// 错误类名
/// </summary>
public string ErrorClass { get; set; }
/// <summary>
/// 错误方法名
/// </summary>
public string ErrorFunction { get; set; }
/// <summary>
/// 堆栈信息
/// </summary>
public string ExceptionInfo { get; set; }
/// <summary>
/// 数据库连接串
/// </summary>
public string DbConString
{
get;
set;
}
}
2部分说明,由于log4net 中 异常信息message如果你传入一个对象的时候,日志输出后会变成它的全命名,无法查看当前的错误的堆栈信息,所以定义了ExceptionInfo .
/// <summary>
/// 异常信息模型转换
/// </summary>
internal sealed class ExceptionInfoPatternConverter : PatternLayoutConverter
{
override protected void Convert(TextWriter writer, LoggingEvent loggingEvent)
{
var logMessage = loggingEvent.MessageObject as LogMessage;
if (logMessage != null)
writer.Write(logMessage.ExceptionInfo);
}
}
该类继承自log4net 的PatternLayoutConverter,这儿也不打理解,看其中的方法,应该是和写入信息有关.
3. 添加布局
/// <summary>
/// 自定义输出布局
/// </summary>
public class CustomLayout : log4net.Layout.PatternLayout
{
public CustomLayout()
{
AddConverter("ErrorClass", typeof(ErrorClassPatternConverter));
AddConverter("ErrorFunction", typeof(ErrorFunctionPatternConverter));
AddConverter("ExceptionInfo", typeof(ExceptionInfoPatternConverter));
AddConverter("DbConString", typeof(DbConStringPatternConverter));
}
}
4.以下是我对日志写入的方法的封装
/// <summary>
/// 日志写入帮助类
/// </summary>
public class LogRecord
{
#region 日志以及字段
private static log4net.ILog _log = null;
private static LogMessage _message = new LogMessage();
public static string LoggerName = string.Empty;
private static ILog Log
{
get
{
//todo 读取配置文件
//string path = "d:\app.config";
//log4net.Config.XmlConfigurator.Configure(new FileInfo(path));
// log4net.Config.XmlConfigurator.Configure();
if (_log == null)
{
//从配置文件中读取Logger对象
//WebLogger 里面的配置信息是用来将日志录入到数据库的
_log = log4net.LogManager.GetLogger(LoggerName);
}
else
{
if (_log.Logger.Name != LoggerName)
{
_log = log4net.LogManager.GetLogger(LoggerName);
}
}
return _log;
}
}
#endregion
#region 日志方法
/// <summary>
/// 调试
/// </summary>
private static void Debug()
{
if (Log.IsDebugEnabled)
{
Log.Debug(_message);
}
}
/// <summary>
/// 记录一般日志
/// </summary>
private static void Info()
{
if (Log.IsInfoEnabled)
{
//log.Info("Jerry");
Log.Info(_message);
}
}
/// <summary>
/// 记录警告
/// </summary>
private static void Warn()
{
if (Log.IsWarnEnabled)
{
Log.Warn(_message);
}
}
/// <summary>
/// 错误
/// </summary>
private static void Error()
{
if (Log.IsErrorEnabled)
{
Log.Error(_message);
}
}
/// <summary>
/// 严重错误
/// </summary>
private static void Fatal()
{
if (Log.IsFatalEnabled)
{
Log.Fatal(_message);
}
}
#endregion
#region 保存日志的方法 重载
/// <summary>
/// 需要写日志的地方调用此方法
/// </summary>
/// <param name="logMessage"></param>
/// <param name="level">自定义级别</param>
/// <param name="waytype"></param>
public static void SaveMessage(LogMessage logMessage, LevelType level, WriteWayType waytype = WriteWayType.Oracle)
{
_message = logMessage;
LoggerName = waytype.ToString();
Execute(level);
}
/// <summary>
/// 保存日志信息
/// </summary>
/// <param name="className">类名</param>
/// <param name="msg">异常(提示)信息</param>
/// <param name="waytype"></param>
/// <param name="level">日志级别 默认Error</param>
4000
public static void SaveMessage(string className, string msg, WriteWayType waytype = WriteWayType.Oracle, LevelType level = LevelType.Error)
{
_message.ErrorClass = className;
_message.ExceptionInfo = msg;
LoggerName = waytype.ToString();
Execute(level);
}
/// <summary>
/// 保存日志信息
/// </summary>
/// <param name="className">类名</param>
/// <param name="funtionName">方法名称</param>
/// <param name="msg">异常(提示)信息</param>
/// <param name="waytype"></param>
/// <param name="level">日志级别 默认Error</param>
public static void SaveMessage(string className, string funtionName, string msg, WriteWayType waytype = WriteWayType.Oracle, LevelType level = LevelType.Error)
{
_message.ErrorClass = className;
_message.ErrorFunction = funtionName;
_message.ExceptionInfo = msg;
LoggerName = waytype.ToString();
Execute(level);
}
/// <summary>
/// 保存日志信息
/// </summary>
/// <param name="className">类名</param>
/// <param name="funtionName">方法名称</param>
/// <param name="msg">异常(提示)信息</param>
/// <param name="dbConString">数据库连接字符串</param>
/// <param name="waytype">默认写入数据库</param>
/// <param name="level">日志级别 默认Error</param>
public static void SaveMessage(string className, string funtionName, string msg, string dbConString, WriteWayType waytype = WriteWayType.Oracle, LevelType level = LevelType.Error)
{
_message.ErrorClass = className;
_message.ErrorFunction = funtionName;
_message.ExceptionInfo = msg;
_message.DbConString = dbConString;
LoggerName = waytype.ToString();
Execute(level);
}
#endregion
#region 执行方法
/// <summary>
/// 执行不同类别的方法
/// </summary>
/// <param name="level"></param>
static void Execute(LevelType level)
{
switch (level)
{
case LevelType.Debug:
Debug();
break;
case LevelType.Info:
Info();
break;
case LevelType.Warn:
Warn();
break;
case LevelType.Error:
Error();
break;
case LevelType.Fatal:
Fatal();
break;
default: break;
}
}
#endregion
}
5.log4net 的配置 (我所使用的)一是直接写入引用改组件的配置文件中.2,在当前类库中添加配置文件app.config.
再这我使用的是第二种,原因是再部署的时候在项目配置中以防更改配置文件引发错误.但是在生成后直接引用会抛出异常.没有找到配置信息.解决方法是在当前类库项目下的AssemblyInfo.cs文件中添加[assembly: log4net.Config.XmlConfigurator(ConfigFileExtension = "config", Watch = true)] .会在你的类库生成时生成一个"类库名+dll.config"的配置文件.只要将其放在引用项目下即可.配置如下
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<configSections>
<section name="log4net" type="log4net.Config.Log4NetConfigurationSectionHandler,log4net"/>
</configSections>
<log4net>
<root>
<level value="INFO"></level>
</root>
<logger name="File">
<appender-ref ref="RollingFileAppender"/>
<level value="ALL"/>
</logger>
<logger name="Oracle">
<level value="ALL"/>
<appender-ref ref="ADONetAppender_Oracle"/>
</logger>
<!--Oracle数据库-->
<appender name="ADONetAppender_Oracle" type="log4net.Appender.ADONetAppender">
<!--缓存-->
<bufferSize value="1"/>
<!-- SQL数据源 ,本地安装SQL客户端-->
<connectionType value="System.Data.OracleClient.OracleConnection, System.Data.OracleClient
,Version=2.0.0.0, Culture=neutral, PublicKeyToken=B77A5C561934E089"/>
<!-- SQL连接字符串-->
<connectionString value="Oracle连接字符串" />
<!--sql语句-->
<commandText value="INSERT INTO log_record_tb(id,RecordTime,thread,RECORDLEVEL,ERRORCLASS,ERRORFUNCTION,Message,DbConString)
VALUES (seq_log_record_tb.nextval,:log_date,:thread,:log_level,:ERRORCLASS,:ErrorFunction,:ExceptionInfo,:DbConString)"/>
<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=":ErrorClass" />
<dbType value="String" />
<size value="200"/>
<layout type="LogRecordBySwt.CustomLayout">
<conversionPattern value="%ErrorClass" />
</layout>
</parameter>
<parameter>
<parameterName value=":ErrorFunction" />
<dbType value="String" />
<size value="200"/>
<layout type="LogRecordBySwt.CustomLayout">
<conversionPattern value="%ErrorFunction" />
</layout>
</parameter>
<parameter>
<parameterName value=":ExceptionInfo" />
<dbType value="String" />
<size value="4000"/>
<layout type="LogRecordBySwt.CustomLayout">
<conversionPattern value="%ExceptionInfo" />
</layout>
</parameter>
<parameter>
<parameterName value=":DbConString" />
<dbType value="String" />
<size value="200"/>
<layout type="LogRecordBySwt.CustomLayout">
<conversionPattern value="%DbConString" />
</layout>
</parameter>
</appender>
<!--文本文件-->
<appender name="RollingFileAppender" 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="yyyy\\yyyyMM\\yyyyMMdd'.txt'" />
<param name="RollingStyle" value="Date" />
<layout type="LogRecordBySwt.CustomLayout">
<param name="ConversionPattern" value="[日志时间:%d]%n[线程ID:[%t]][日志级别:%-5p]%n[出错类:%ErrorClass][出错方法:%ErrorFunction]%n[异常信息:%ExceptionInfo]%n[数据库连接串:%DbConString]%n%n" />
</layout>
</appender>
</log4net>
<startup>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.0"/>
</startup>
</configuration>
6.最后新建测试项目
static void Main(string[] args)
{
var ds = new DataSet();
try
{
if (ds.Tables[0] == null)
{
}
}
catch (Exception ex)
{
LogRecord.SaveMessage("Program"
, "main"
, ex.Message + ex.StackTrace
, WriteWayType.Oracle
, LevelType.Info);
}
}测试通过.
问题总结,刚开始测试,一直没有写入数据库,查了很多园子中的.主要是配置文件写的不规范.....由于也是第一次写,可能会很乱.还请给我多多指点.
1.自定义错误模型
/// <summary>
/// 自定义错误信息模型
/// </summary>
public class LogMessage
{
/// <summary>
/// 错误类名
/// </summary>
public string ErrorClass { get; set; }
/// <summary>
/// 错误方法名
/// </summary>
public string ErrorFunction { get; set; }
/// <summary>
/// 堆栈信息
/// </summary>
public string ExceptionInfo { get; set; }
/// <summary>
/// 数据库连接串
/// </summary>
public string DbConString
{
get;
set;
}
}
2部分说明,由于log4net 中 异常信息message如果你传入一个对象的时候,日志输出后会变成它的全命名,无法查看当前的错误的堆栈信息,所以定义了ExceptionInfo .
/// <summary>
/// 异常信息模型转换
/// </summary>
internal sealed class ExceptionInfoPatternConverter : PatternLayoutConverter
{
override protected void Convert(TextWriter writer, LoggingEvent loggingEvent)
{
var logMessage = loggingEvent.MessageObject as LogMessage;
if (logMessage != null)
writer.Write(logMessage.ExceptionInfo);
}
}
该类继承自log4net 的PatternLayoutConverter,这儿也不打理解,看其中的方法,应该是和写入信息有关.
3. 添加布局
/// <summary>
/// 自定义输出布局
/// </summary>
public class CustomLayout : log4net.Layout.PatternLayout
{
public CustomLayout()
{
AddConverter("ErrorClass", typeof(ErrorClassPatternConverter));
AddConverter("ErrorFunction", typeof(ErrorFunctionPatternConverter));
AddConverter("ExceptionInfo", typeof(ExceptionInfoPatternConverter));
AddConverter("DbConString", typeof(DbConStringPatternConverter));
}
}
4.以下是我对日志写入的方法的封装
/// <summary>
/// 日志写入帮助类
/// </summary>
public class LogRecord
{
#region 日志以及字段
private static log4net.ILog _log = null;
private static LogMessage _message = new LogMessage();
public static string LoggerName = string.Empty;
private static ILog Log
{
get
{
//todo 读取配置文件
//string path = "d:\app.config";
//log4net.Config.XmlConfigurator.Configure(new FileInfo(path));
// log4net.Config.XmlConfigurator.Configure();
if (_log == null)
{
//从配置文件中读取Logger对象
//WebLogger 里面的配置信息是用来将日志录入到数据库的
_log = log4net.LogManager.GetLogger(LoggerName);
}
else
{
if (_log.Logger.Name != LoggerName)
{
_log = log4net.LogManager.GetLogger(LoggerName);
}
}
return _log;
}
}
#endregion
#region 日志方法
/// <summary>
/// 调试
/// </summary>
private static void Debug()
{
if (Log.IsDebugEnabled)
{
Log.Debug(_message);
}
}
/// <summary>
/// 记录一般日志
/// </summary>
private static void Info()
{
if (Log.IsInfoEnabled)
{
//log.Info("Jerry");
Log.Info(_message);
}
}
/// <summary>
/// 记录警告
/// </summary>
private static void Warn()
{
if (Log.IsWarnEnabled)
{
Log.Warn(_message);
}
}
/// <summary>
/// 错误
/// </summary>
private static void Error()
{
if (Log.IsErrorEnabled)
{
Log.Error(_message);
}
}
/// <summary>
/// 严重错误
/// </summary>
private static void Fatal()
{
if (Log.IsFatalEnabled)
{
Log.Fatal(_message);
}
}
#endregion
#region 保存日志的方法 重载
/// <summary>
/// 需要写日志的地方调用此方法
/// </summary>
/// <param name="logMessage"></param>
/// <param name="level">自定义级别</param>
/// <param name="waytype"></param>
public static void SaveMessage(LogMessage logMessage, LevelType level, WriteWayType waytype = WriteWayType.Oracle)
{
_message = logMessage;
LoggerName = waytype.ToString();
Execute(level);
}
/// <summary>
/// 保存日志信息
/// </summary>
/// <param name="className">类名</param>
/// <param name="msg">异常(提示)信息</param>
/// <param name="waytype"></param>
/// <param name="level">日志级别 默认Error</param>
4000
public static void SaveMessage(string className, string msg, WriteWayType waytype = WriteWayType.Oracle, LevelType level = LevelType.Error)
{
_message.ErrorClass = className;
_message.ExceptionInfo = msg;
LoggerName = waytype.ToString();
Execute(level);
}
/// <summary>
/// 保存日志信息
/// </summary>
/// <param name="className">类名</param>
/// <param name="funtionName">方法名称</param>
/// <param name="msg">异常(提示)信息</param>
/// <param name="waytype"></param>
/// <param name="level">日志级别 默认Error</param>
public static void SaveMessage(string className, string funtionName, string msg, WriteWayType waytype = WriteWayType.Oracle, LevelType level = LevelType.Error)
{
_message.ErrorClass = className;
_message.ErrorFunction = funtionName;
_message.ExceptionInfo = msg;
LoggerName = waytype.ToString();
Execute(level);
}
/// <summary>
/// 保存日志信息
/// </summary>
/// <param name="className">类名</param>
/// <param name="funtionName">方法名称</param>
/// <param name="msg">异常(提示)信息</param>
/// <param name="dbConString">数据库连接字符串</param>
/// <param name="waytype">默认写入数据库</param>
/// <param name="level">日志级别 默认Error</param>
public static void SaveMessage(string className, string funtionName, string msg, string dbConString, WriteWayType waytype = WriteWayType.Oracle, LevelType level = LevelType.Error)
{
_message.ErrorClass = className;
_message.ErrorFunction = funtionName;
_message.ExceptionInfo = msg;
_message.DbConString = dbConString;
LoggerName = waytype.ToString();
Execute(level);
}
#endregion
#region 执行方法
/// <summary>
/// 执行不同类别的方法
/// </summary>
/// <param name="level"></param>
static void Execute(LevelType level)
{
switch (level)
{
case LevelType.Debug:
Debug();
break;
case LevelType.Info:
Info();
break;
case LevelType.Warn:
Warn();
break;
case LevelType.Error:
Error();
break;
case LevelType.Fatal:
Fatal();
break;
default: break;
}
}
#endregion
}
5.log4net 的配置 (我所使用的)一是直接写入引用改组件的配置文件中.2,在当前类库中添加配置文件app.config.
再这我使用的是第二种,原因是再部署的时候在项目配置中以防更改配置文件引发错误.但是在生成后直接引用会抛出异常.没有找到配置信息.解决方法是在当前类库项目下的AssemblyInfo.cs文件中添加[assembly: log4net.Config.XmlConfigurator(ConfigFileExtension = "config", Watch = true)] .会在你的类库生成时生成一个"类库名+dll.config"的配置文件.只要将其放在引用项目下即可.配置如下
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<configSections>
<section name="log4net" type="log4net.Config.Log4NetConfigurationSectionHandler,log4net"/>
</configSections>
<log4net>
<root>
<level value="INFO"></level>
</root>
<logger name="File">
<appender-ref ref="RollingFileAppender"/>
<level value="ALL"/>
</logger>
<logger name="Oracle">
<level value="ALL"/>
<appender-ref ref="ADONetAppender_Oracle"/>
</logger>
<!--Oracle数据库-->
<appender name="ADONetAppender_Oracle" type="log4net.Appender.ADONetAppender">
<!--缓存-->
<bufferSize value="1"/>
<!-- SQL数据源 ,本地安装SQL客户端-->
<connectionType value="System.Data.OracleClient.OracleConnection, System.Data.OracleClient
,Version=2.0.0.0, Culture=neutral, PublicKeyToken=B77A5C561934E089"/>
<!-- SQL连接字符串-->
<connectionString value="Oracle连接字符串" />
<!--sql语句-->
<commandText value="INSERT INTO log_record_tb(id,RecordTime,thread,RECORDLEVEL,ERRORCLASS,ERRORFUNCTION,Message,DbConString)
VALUES (seq_log_record_tb.nextval,:log_date,:thread,:log_level,:ERRORCLASS,:ErrorFunction,:ExceptionInfo,:DbConString)"/>
<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=":ErrorClass" />
<dbType value="String" />
<size value="200"/>
<layout type="LogRecordBySwt.CustomLayout">
<conversionPattern value="%ErrorClass" />
</layout>
</parameter>
<parameter>
<parameterName value=":ErrorFunction" />
<dbType value="String" />
<size value="200"/>
<layout type="LogRecordBySwt.CustomLayout">
<conversionPattern value="%ErrorFunction" />
</layout>
</parameter>
<parameter>
<parameterName value=":ExceptionInfo" />
<dbType value="String" />
<size value="4000"/>
<layout type="LogRecordBySwt.CustomLayout">
<conversionPattern value="%ExceptionInfo" />
</layout>
</parameter>
<parameter>
<parameterName value=":DbConString" />
<dbType value="String" />
<size value="200"/>
<layout type="LogRecordBySwt.CustomLayout">
<conversionPattern value="%DbConString" />
</layout>
</parameter>
</appender>
<!--文本文件-->
<appender name="RollingFileAppender" 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="yyyy\\yyyyMM\\yyyyMMdd'.txt'" />
<param name="RollingStyle" value="Date" />
<layout type="LogRecordBySwt.CustomLayout">
<param name="ConversionPattern" value="[日志时间:%d]%n[线程ID:[%t]][日志级别:%-5p]%n[出错类:%ErrorClass][出错方法:%ErrorFunction]%n[异常信息:%ExceptionInfo]%n[数据库连接串:%DbConString]%n%n" />
</layout>
</appender>
</log4net>
<startup>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.0"/>
</startup>
</configuration>
6.最后新建测试项目
static void Main(string[] args)
{
var ds = new DataSet();
try
{
if (ds.Tables[0] == null)
{
}
}
catch (Exception ex)
{
LogRecord.SaveMessage("Program"
, "main"
, ex.Message + ex.StackTrace
, WriteWayType.Oracle
, LevelType.Info);
}
}测试通过.
问题总结,刚开始测试,一直没有写入数据库,查了很多园子中的.主要是配置文件写的不规范.....由于也是第一次写,可能会很乱.还请给我多多指点.
相关文章推荐
- Log4Net自定义属性输出
- asp.net mvc输出自定义404等错误页面,非302跳转。
- log4net自定义错误日志实例
- asp.net mvc输出自定义404等错误页面,非302跳转
- 1、ThinkPHP源码学习-致命错误捕获及自定义错误输出
- Laravel实现自定义错误输出内容的方法
- C# log4net输出发生错误的行号
- laravel自定义错误输出的内容
- Spring MVC自定义统一异常处理类,并且在控制台中输出错误日志
- log4net输出错误行号配置
- Spring MVC自定义统一异常处理类,并且在控制台中输出错误日志
- Spring MVC自定义统一异常处理类,并且在控制台中输出错误日志
- Golang 如何定义一个接口类型的切片,它可以用来存储混合类型的数据,又如何自定义错误信息输出,以及如何定义变参函数,还有字符串多种拼接方式
- JSP中统一错误信息输出
- 重定向标准输入,输出以及错误流
- 自定义错误页面
- C#WinForm下自定义错误消息
- 关于自定义实体集合绑定datagrid控件在进行编辑时出现错误"向原始数据存储区提交行时出错"的原因.
- 用err.raise自定义错误信息
- 输出自定义的日期