当前位置: 代码迷 >> C# >>  第五步:如何使用HY.Log.DLL
  详细解决方案

 第五步:如何使用HY.Log.DLL

热度:51   发布时间:2016-05-05 03:04:28.0
搭建一套自己实用的.net架构(2)【日志模块-log4net】

       先谈谈简单的模块,日志。在系统中日志模块是必须的,什么系统日志,操作日志,调试日志。这里用的是log4net

对log4net还不熟悉的小伙伴们赶快去搜索基础教程哦, 我这里就不温故了。

       那么有人要问了,log4net确实很强大,而且我们也会用。还要单独写一篇文章来介绍,有必要吗?

我简单的举两个场景:

1:log4net写入DB 还需要在 log4net中配置数据库连接字符串,   我想log4net 和 我的 connectionStrings 用1个配置不行吗?

2:log4net写入参数扩展问题,我配置文件想写入ip地址,那我代码还要定义一个ip的参数。 那我再扩展,还需要再定义,这改动量太大了,能不能只传一个实体类,让log4net自己去映射那?这样我就可以写一些通用的方法,好多项目都可以直接拿过来用,代码修改量也少了点。

有人觉得这都不是问题,高手请跳过。

我这里将日志模块单独封装了一个HY.Log,截图如下:

 看图有点乱,下面我给大家捋一捋(念lv  念成lu的去面壁思过  ):

 

第一步:实现自定义参数

我们要在PatternConverter文件夹中定义一些可扩展参数,这样就可以在log4net配置文件中随心使用了,哪截图中我实现了获取客户端ip、获取服务器端ip

或许服务器mac地址。

就拿ClientIpPatternConverter.cs来说需要继承log4net下  log4net.Layout.Pattern.PatternLayoutConverter类,来实现扩展。

using System.IO;using log4net.Core;using log4net.Layout.Pattern;namespace HY.Log.PatternConverter{    /// <summary>    /// B/S 客户端地址扩展    /// </summary>    internal class ClientIpPatternConverter : PatternLayoutConverter    {        protected override void Convert(TextWriter writer, LoggingEvent loggingEvent)        {            writer.Write(HY.Utilities.IPHelper.GetRemoteIPAddress());                   }    }}

 接着在分别实现 MAC、服务端IP、 以及其它你任何想扩展的参数。

 

ObjectPatternConverter.cs 这个类就比较特殊了。这个自定义参数其实是让你传入一个实体类,然后通过反射技术,让log4net通过配置文件的 配置自动映射要传入的值。

上面的类 是针对特定的通用功能扩展,这个类只需要定义一个即可。

using System.IO;using System.Reflection;using log4net.Core;using log4net.Layout.Pattern;namespace HY.Log.PatternConverter{    internal class ObjectPatternConverter : PatternLayoutConverter    {        protected override void Convert(TextWriter writer, LoggingEvent loggingEvent)        {            if (Option != null)            {                // Write the value for the specified key                WriteObject(writer, loggingEvent.Repository, LookupProperty(Option, loggingEvent));            }            else            {                // Write all the key value pairs                WriteDictionary(writer, loggingEvent.Repository, loggingEvent.GetProperties());            }        }        /// <summary>        /// 通过反射获取传入的日志对象的某个属性的值        /// </summary>        /// <param name="property"></param>        /// <param name="loggingEvent"></param>        /// <returns></returns>        private object LookupProperty(string property, LoggingEvent loggingEvent)        {            object propertyValue = string.Empty;            PropertyInfo propertyInfo = loggingEvent.MessageObject.GetType().GetProperty(property);            if (propertyInfo != null)                propertyValue = propertyInfo.GetValue(loggingEvent.MessageObject, null);            return propertyValue;        }    }}

 

 

 第二步:实现log4net自定义布局,将自定义参数进行注册

 CustomLayout.cs

using HY.Log.PatternConverter;using log4net.Layout;namespace HY.Log{    /// <summary>    /// 定义log日志布局的参数信息    /// </summary>    public class CustomLayout : PatternLayout    {        /// <summary>        /// 构造函数        /// </summary>        public CustomLayout()        {            #region 内部自定义            AddConverter("ServerIP", typeof(ServerIpPatternConverter));            AddConverter("ClientIP", typeof(ClientIpPatternConverter));            AddConverter("MAC", typeof(MacPatternConverter));            #endregion            #region 支持开发人员自定义            AddConverter("Object", typeof(ObjectPatternConverter));            #endregion        }    }}

代码将自定义的参数以 key value 的形式进行注册, 以后我们再log4net进行配置的时候 就要记住这些关键字了, 这都是你自己定义的。

你敢在代码中实现  AddConverter("XXOO", typeof(XXOOPatternConverter));  吗?

 

 

 

 第三步:定义自己框架的Log接口并实现它

没啥可说的,看代码吧。

LogMessage.cs   这个类其实就是写了一个传入的的自定义参数的实体类,你可以自己写。不过最好是继承这个类进行扩展。

using System;namespace HY.Log{    /// <summary>    /// 用于记录日志信息    /// </summary>    [Serializable]    public class LogMessage    {        /// <summary>        /// 日志信息        /// </summary>        public string Message { get; set; }    }}

 

 

ILog.cs

using System;namespace HY.Log{    public interface ILog    {        /// <summary>        /// 写入Debug日志,        /// </summary>        /// <param name="message">日志信息,占位符为 %Object{Message}</param>        void Debug(string message, Exception exception = null);        /// <summary>        /// 写入Debug日志        /// </summary>        /// <param name="messageEntity">日志实体信息, 占位符为 %Object{实体类的属性名称}</param>        void Debug(object messageEntity, Exception exception = null);        /// <summary>        /// 写入Info日志,        /// </summary>        /// <param name="message">日志信息,占位符为 %Object{Message}</param>        void Info(string message, Exception exception = null);        /// <summary>        /// 写入Info日志        /// </summary>        /// <param name="messageEntity">日志实体信息, 占位符为 %Object{实体类的属性名称}</param>        void Info(object messageEntity, Exception exception = null);        /// <summary>        /// 写入Warn日志,        /// </summary>        /// <param name="message">日志信息,占位符为 %Object{Message}</param>        void Warn(string message, Exception exception = null);        /// <summary>        /// 写入Warn日志        /// </summary>        /// <param name="messageEntity">日志实体信息, 占位符为 %Object{实体类的属性名称}</param>        void Warn(object messageEntity, Exception exception = null);        /// <summary>        /// 写入Error日志,        /// </summary>        /// <param name="message">日志信息,占位符为 %Object{Message}</param>        void Error(string message, Exception exception = null);        /// <summary>        /// 写入Error日志        /// </summary>        /// <param name="messageEntity">日志实体信息, 占位符为 %Object{实体类的属性名称}</param>        void Error(object messageEntity, Exception exception = null);        /// <summary>        /// 写入Fatal日志,        /// </summary>        /// <param name="message">日志信息,占位符为 %Object{Message}</param>        void Fatal(string message, Exception exception = null);        /// <summary>        /// 写入Fatal日志        /// </summary>        /// <param name="messageEntity">日志实体信息, 占位符为 %Object{实体类的属性名称}</param>        void Fatal(object messageEntity, Exception exception = null);    }}

 

NormalLog.cs

using System;using System.Collections.Generic;namespace HY.Log{    public class NormalLog : ILog    {        #region private        private static Dictionary<string, log4net.ILog> listILog = new Dictionary<string, log4net.ILog>();   //Log对象集合        private log4net.ILog iLog;  //当前日志对象的实例        #endregion        #region 构造函数        /// <summary>        /// 构造函数,传入Log4NET 的ILog对象        /// </summary>        /// <param name="logger"></param>        public NormalLog(log4net.ILog logger)        {            string LoggerName = logger.Logger.Name;     //logger 配置节名称            if (!listILog.ContainsKey(LoggerName))            {                lock (listILog)                {                    if (!listILog.ContainsKey(LoggerName))                    {                        listILog.Add(LoggerName, logger);                    }                    else                    {                        listILog[LoggerName] = logger;                    }                }            }            else if (listILog[LoggerName] == null)            {                listILog[LoggerName] = logger;            }            iLog = listILog[LoggerName];        }        public NormalLog(string loggerName)        {            log4net.ILog logger = log4net.LogManager.GetLogger(loggerName);            string LoggerName = logger.Logger.Name;     //logger 配置节名称            if (!listILog.ContainsKey(LoggerName))            {                listILog.Add(LoggerName, logger);            }            else if (listILog[LoggerName] == null)            {                listILog[LoggerName] = logger;            }            iLog = listILog[LoggerName];        }        #endregion        #region 写入日志        /// <summary>        /// 写入Debug日志,        /// </summary>        /// <param name="message">日志信息,占位符为 %Object{Message}</param>        public void Debug(string message, Exception exception = null)        {            LogMessage messageEntity = new LogMessage            {                Message = message            };            Debug(messageEntity, exception);        }        /// <summary>        /// 写入Debug日志        /// </summary>        /// <param name="messageEntity">日志实体信息, 占位符为 %Object{实体类的属性名称}</param>        public void Debug(object messageEntity, Exception exception = null)        {            if (iLog.IsDebugEnabled)            {                if (exception != null)                {                    iLog.Debug(messageEntity, exception);                }                else                {                    iLog.Debug(messageEntity);                }            }        }        /// <summary>        /// 写入Info日志,        /// </summary>        /// <param name="message">日志信息,占位符为 %Object{Message}</param>        public void Info(string message, Exception exception = null)        {            LogMessage messageEntity = new LogMessage            {                Message = message            };            Info(messageEntity, exception);        }        /// <summary>        /// 写入Info日志        /// </summary>        /// <param name="messageEntity">日志实体信息, 占位符为 %Object{实体类的属性名称}</param>        public void Info(object messageEntity, Exception exception = null)        {            if (iLog.IsInfoEnabled)            {                if (exception != null)                {                    iLog.Info(messageEntity, exception);                }                else                {                    iLog.Info(messageEntity);                }            }        }        /// <summary>        /// 写入Warn日志,        /// </summary>        /// <param name="message">日志信息,占位符为 %Object{Message}</param>        public void Warn(string message, Exception exception = null)        {            LogMessage messageEntity = new LogMessage            {                Message = message            };            Warn(messageEntity, exception);        }        /// <summary>        /// 写入Warn日志        /// </summary>        /// <param name="messageEntity">日志实体信息, 占位符为 %Object{实体类的属性名称}</param>        public void Warn(object messageEntity, Exception exception = null)        {            if (iLog.IsWarnEnabled)            {                if (exception != null)                {                    iLog.Warn(messageEntity, exception);                }                else                {                    iLog.Warn(messageEntity);                }            }        }        /// <summary>        /// 写入Error日志,        /// </summary>        /// <param name="message">日志信息,占位符为 %Object{Message}</param>        public void Error(string message, Exception exception = null)        {            LogMessage messageEntity = new LogMessage            {                Message = message            };            Error(messageEntity, exception);        }        /// <summary>        /// 写入Error日志        /// </summary>        /// <param name="messageEntity">日志实体信息, 占位符为 %Object{实体类的属性名称}</param>        public void Error(object messageEntity, Exception exception = null)        {            if (iLog.IsErrorEnabled)            {                if (exception != null)                {                    iLog.Error(messageEntity, exception);                }                else                {                    iLog.Error(messageEntity);                }            }        }        /// <summary>        /// 写入Fatal日志,        /// </summary>        /// <param name="message">日志信息,占位符为 %Object{Message}</param>        public void Fatal(string message, Exception exception = null)        {            LogMessage messageEntity = new LogMessage            {                Message = message            };            Fatal(messageEntity, exception);        }        /// <summary>        /// 写入Fatal日志        /// </summary>        /// <param name="messageEntity">日志实体信息, 占位符为 %Object{实体类的属性名称}</param>        public void Fatal(object messageEntity, Exception exception = null)        {            if (iLog.IsFatalEnabled)            {                if (exception != null)                {                    iLog.Fatal(messageEntity, exception);                }                else                {                    iLog.Fatal(messageEntity);                }            }        }        #endregion    }}

 

  第四步:写一下log模块的支持方法(这里有实现log4net配置和连接字符串共用一个配置的方法)

 

 LogManager.cs

这个类定义的了log4net模块的初始化,数据库连接设置……

using System;using System.IO;using log4net.Appender;using log4net.Config;using log4net.Repository.Hierarchy;namespace HY.Log{    public class LogManager    {        /// <summary>        /// 设置DB连接字符串        /// </summary>        /// <param name="conString">连接字符串</param>        /// <param name="loggerName">loggerName</param>        /// <param name="appenderName">appenderName</param>        public static void ConfigConnection(string conString, string loggerName, string appenderName = "ADONetAppender")        {            try            {                Hierarchy h = log4net.LogManager.GetRepository() as Hierarchy;                if (h != null)                {                    AdoNetAppender adoAppender = (AdoNetAppender)h.GetLogger(loggerName,                        h.LoggerFactory).GetAppender(appenderName);                    if (adoAppender != null)                    {                        adoAppender.ConnectionString = conString;                        adoAppender.ActivateOptions();                    }                }            }            catch (NullReferenceException) { }        }        /// <summary>        /// 初始化HY.Log,  Log配置文件需要写到 Web.config  OR  App.config        /// </summary>        public static void Init()        {            XmlConfigurator.Configure();        }        /// <summary>        /// 初始化HY.Log,         /// </summary>        /// <param name="configFileName">制定Log配置文件的文件绝对路径</param>        public static void Init(string configFileName)        {            XmlConfigurator.Configure(new FileInfo(configFileName));        }        /// <summary>        /// 检索Logger名称返回日志处理接口        /// </summary>        /// <param name="name">Logger名称</param>        /// <returns>日志接口</returns>        public static ILog GetLogger(string name)        {            var log4Logger = log4net.LogManager.GetLogger(name);            return new NormalLog(log4Logger);        }    }}

 

 第五步:如何使用HY.Log.DLL

上面的代码大家看到了,已经可以成功编译一个dll 文件了。


先来编辑一个log4net配置文件

<?xml version="1.0"?><configuration>  <!--Log4net Begin-->  <configSections>    <section name="log4net" type="log4net.Config.Log4NetConfigurationSectionHandler, log4net" />  </configSections>  <log4net>    <!--Log4net Begin,程序运行异常记录-->    <logger name="LogInfoDB">      <level value="ALL" />      <appender-ref ref="ADONetAppender" />    </logger>    <appender name="ADONetAppender" type="log4net.Appender.ADONetAppender">      <bufferSize value="1" />      <connectionType value="System.Data.SqlClient.SqlConnection, System.Data, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" />      <!--<connectionString value="Data Source=127.0.0.1;Database=test;uid=sa;pwd=test;Max Pool Size=300;Connect Timeout=15;" />-->      <commandText value="INSERT INTO HY_Log ([LogType],[ModelName],[Message],[Exception],[IP],[Log_Date],[UserID]) VALUES (@LogType,@ModelName, @Message, @Exception, @IP,@Log_Date,@UserID)" />      <parameter>        <parameterName value="@LogType" />        <dbType value="String" />        <size value="20" />        <layout type="HY.Log.CustomLayout">          <conversionPattern value="%Object{LogType}" />        </layout>      </parameter>      <parameter>        <parameterName value="@ModelName" />        <dbType value="String" />        <size value="110" />        <layout type="HY.Log.CustomLayout">          <conversionPattern value="%Object{ModelName}" />        </layout>      </parameter>      <parameter>        <parameterName value="@Message" />        <dbType value="String" />        <size value="2000" />        <layout type="HY.Log.CustomLayout">          <conversionPattern value="%Object{Message}" />        </layout>      </parameter>      <parameter>        <parameterName value="@Exception" />        <dbType value="String" />        <size value="8000" />        <layout type="HY.Log.CustomLayout">          <conversionPattern value="%Object{Exception}" />        </layout>      </parameter>      <parameter>        <parameterName value="@IP" />        <dbType value="String" />        <size value="20" />        <layout type="HY.Log.CustomLayout">          <conversionPattern value="%ClientIP" />        </layout>      </parameter>      <parameter>        <parameterName value="@Log_Date" />        <dbType value="DateTime" />        <layout type="log4net.Layout.RawTimeStampLayout" />      </parameter>      <parameter>        <parameterName value="@UserID" />        <dbType value="String" />        <size value="100" />        <layout type="HY.Log.CustomLayout">          <conversionPattern value="%Object{UserID}" />        </layout>      </parameter>    </appender>  </log4net>  <!--Log4net End--></configuration><!--%m(message):输出的日志消息,如ILog.Debug(…)输出的一条消息      %n(new line):换行      %d(datetime):输出当前语句运行的时刻      %r(run time):输出程序从运行到执行到当前语句时消耗的毫秒数      %t(thread id):当前语句所在的线程ID      %p(priority): 日志的当前优先级别,即DEBUG、INFO、WARN…等      %c(class):当前日志对象的名称,例如:      %f(file):输出语句所在的文件名。      %l(line):输出语句所在的行号。-->

 上面的配置文件是一个写入DB的配置

请注意如下配置节:

<layout type="HY.Log.CustomLayout">
<conversionPattern value="%Object{Exception}" />
<conversionPattern value="%Object{LogType}" />
<conversionPattern value="%ClientIP" />
这便是采用了自定义配置。


创建HY.ILog对象
public static ILog ilog = null;

HY.Log.LogManager.Init(HttpContext.Current.Server.MapPath(@"~/Config/log4net.config"));//加载配置文件
HY.Log.LogManager.ConfigConnection(ConfigurationManager.ConnectionStrings["Connection"].ToString(), "LogInfoDB");//修改连接字符串
ilog = LogManager.GetLogger("LogInfoText");     //获取Ilog对象 这里可以采用单例模式。代码就不贴了,


自定义实体类:
 [Serializable]    public class LogEntity    {        /// <summary>        /// 日志类型        /// </summary>        public LogType LogType { get; set; }        /// <summary>        /// 模块名称        /// </summary>        public string ModelName { get; set; }        /// <summary>        /// 信息        /// </summary>        public new string Message { get; set; }        /// <summary>        /// 异常信息        /// </summary>        public string Exception { get; set; }        public string UserID { get; set; }

 


LogEntity loginfo = new LogEntity();
loginfo.ModelName = "ModelName";
           loginfo.Message = "Message";
           loginfo.Exception = "Exception";
           loginfo.UserID = "UserID";
           loginfo.LogType = "LogType.Business";
ilog.Error(loginfo,ex);
 
 到这里就已经完了。  关于使用的代码比较粗糙,这块就需要根据你程序的具体需求来实现了。这里点到为止。  因为后续我们将会采用spring.net来注入。 将在后续的文章介绍。


各位如果有更好的建立请给我留言, 请各位不吝赐教。
 

 

相关文章:

搭建一套自己实用的.net架构(1)【概述】

搭建一套自己实用的.net架构(2)【日志模块-log4net】

  相关解决方案