您的位置:首页 > 数据库

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);

            }

        }测试通过. 

问题总结,刚开始测试,一直没有写入数据库,查了很多园子中的.主要是配置文件写的不规范.....由于也是第一次写,可能会很乱.还请给我多多指点.
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  log4net 数据库