您现在的位置: 365建站网 > 365文章 > .Net日志库Nlog的配置与调试记录日志的方法

.Net日志库Nlog的配置与调试记录日志的方法

文章来源:365jz.com     点击数:687    更新时间:2018-06-24 12:29   参与评论

NLog是一个简单灵活的.NET日志记录类库,NLog的API非常类似于log4net,且配置方式非常简单。通过使用NLog,我们可以在任何一种.NET语言中输出带有上下文的调试信息,根据项目需求配置署出格式和输出目标的规则。

NLog使用路由进行配置,但log4net却使用层次性的appender配置,这样就让NLog的配置文件非常容易阅读,并便于今后维护。

支持多种形式输出日志:文本文件 系统日志 数据库 控制台 邮箱 等

下载

通过Nuget安装NLog,你也可以同时安装NLog.Config,它会在项目目录下帮你建立一个配置文件NLog.config,不过不需要,我们直接手动建立一个,你也可以将配置的信息写入到 App.config/Web.config,我比较喜欢独立出来,不与其它配置掺和在一起。

 

配置

在项目根目录下新建一个NLog.config,基本目录结构:targets下面配置日志输出目标及相关参数,rules下面配置目标输出规则。

1
2
3
4
5
6
7
8
9
10
11
<?xml version="1.0" ?>
<nlog>
    <targets>
        <target></target>
        <target></target>
    </targets>
    <rules>
        <logger></logger>
        <logger></logger>
    </rules>
</nlog>

记得在NLog.config的属性中设置 Copy to Output Directory: Copy always

 

现在我们要将日志输出到文本文件,数据库,VS调试窗口,完整配置文件如下:

</>code

  1. <?xml version="1.0" ?><!--<nlog xmlns="http://www.nlog-project.org/schemas/NLog.xsd"
  2.       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  3.       autoReload="true"
  4.       internalLogLevel="Trace"
  5.       internalLogFile="D:\work\log.txt">--><nlog xmlns="http://www.nlog-project.org/schemas/NLog.xsd"
  6.       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  7.       autoReload="true">
  8.   
  9.   <targets>
  10.     
  11.     <!-- Log in a separate thread, possibly queueing up to
  12.         5000 messages. When the queue overflows, discard any
  13.         extra messages-->
  14.     <!-- write logs to file -->
  15.     <target name="file" xsi:type="AsyncWrapper" queueLimit="5000" overflowAction="Discard">
  16.       <target xsi:type="File" fileName="${basedir}/logs/${shortdate}.log" layout="${longdate} ${level:uppercase=true} ${event-context:item=Action} ${message} ${event-context:item=Amount} ${stacktrace}" />      
  17.     </target>
  18.     <!-- write log message to database -->
  19.     <target name="db" xsi:type="AsyncWrapper" queueLimit="5000" overflowAction="Discard">
  20.       <target type="Database" dbProvider="mssql" connectionString="Data Source=.\SQLEXPRESS;Initial Catalog=EFinance;Persist Security Info=True;User ID=sa;Password=123456;">
  21.         <commandText>
  22.           INSERT INTO Log(Timestamp,Level,Message,Action,Amount,StackTrace) VALUES(@time_stamp, @level, @message, @action, @amount, @stacktrace);        </commandText>
  23.         <!-- database connection parameters -->
  24.         <parameter name="@time_stamp" layout="${date}" />
  25.         <parameter name="@level" layout="${level:uppercase=true}" />
  26.         <parameter name="@message" layout="${message}" />
  27.         <parameter name="@action" layout="${event-context:item=Action}" />
  28.         <parameter name="@amount" layout="${event-context:item=Amount}" />
  29.         <parameter name="@stacktrace" layout="${stacktrace}" />
  30.       </target>
  31.     </target>
  32.     <!--write log message to Visual Studio Output-->
  33.     <target name="debugger" xsi:type="Debugger" layout="NLog: ${date:format=HH\:mm\:ss} | ${level:uppercase=true:padding=-5} | ${message}" />
  34.   </targets>
  35.   <rules>
  36.     <!--TRACE,DEBUG,INFO,WARN,ERROR,FATAL-->
  37.     <logger name="*" minlevel="Trace" writeTo="debugger" />
  38.     <!--INFO,WARN,ERROR,FATAL-->
  39.     <logger name="*" minlevel="Info" writeTo="db" />
  40.     <!--DEBUG,INFO,WARN,ERROR,FATAL-->
  41.     <logger name="*" minlevel="Debug" writeTo="file" />    
  42.   </rules></nlog>


  • 如在根节点(nlog)配置 internalLogLevel, internalLogFile,可以查看NLog输出日志时的内部信息,比如你配置文件有错误,很有帮助,不过项目发布后还是关闭比较好,以免影响效率;

  • 在target外面罩了一个 <target>并且xsi:type为 AsyncWrapper,即表示这条 target 将异步输出,这里我将文件和数据库日志异步输出;

  • db target内指定了数据库连接字符串 connectionString,SQL语句,SQL参数,还可以指定数据库/表创建和删除的脚本(推荐看NLog源码示例,这里不介绍),同时我们自定义了2个参数 action和amount;

  • target参数里有些是NLog内置参数,比如message,level,date,longdate,exception,stacktrace等,NLog在输出时会自动赋值;

  • layout设置了每条日志的格式;

  • 在rules节点,我们分别指定了三个target输出日志的级别,NLog用于输出日志的级别包括:Trace,Debug,Info,Warn,Error,Fatal,可以设置 minlevel设置最小级别,也可以用 levels定义你所有需要的级别(多个用逗号分隔)。

 

封装

简单两句就可以使用NLog了:

NLog.Logger logger = Nlog.LogManager.GetCurrentClassLogger();
logger.Fatal("发生致命错误");
logger.Warn("警告信息");

 

但是这样只能记录了NLog的内置字段,我们定义的 Amount, Action都不能写入,接下来我们来封装一个Logger:


</>code

  1. public class Logger
  2.     {
  3.         NLog.Logger _logger;        private Logger(NLog.Logger logger)
  4.         {
  5.             _logger = logger;
  6.         }        public Logger(string name) : this(LogManager.GetLogger(name))
  7.         {
  8.         }        public static Logger Default { get; private set; }        static Logger()
  9.         {
  10.             Default = new Logger(NLog.LogManager.GetCurrentClassLogger());
  11.         }        #region Debug        public void Debug(string msg, params object[] args)
  12.         {
  13.             _logger.Debug(msg, args);
  14.         }        
  15.         public void Debug(string msg, Exception err)
  16.         {
  17.             _logger.Debug(err, msg);
  18.         }        
  19.         #endregion
  20.         #region Info        public void Info(string msg, params object[] args)
  21.         {
  22.             _logger.Info(msg, args);
  23.         }        public void Info(string msg, Exception err)
  24.         {
  25.             _logger.Info(err, msg);
  26.         }        #endregion
  27.         #region Warn        public void Warn(string msg, params object[] args)
  28.         {
  29.             _logger.Warn(msg, args);
  30.         }        public void Warn(string msg, Exception err)
  31.         {
  32.             _logger.Warn(err, msg);
  33.         }        #endregion
  34.         #region Trace        public void Trace(string msg, params object[] args)
  35.         {
  36.             _logger.Trace(msg, args);
  37.         }        public void Trace(string msg, Exception err)
  38.         {
  39.             _logger.Trace(err, msg);
  40.         }        #endregion
  41.         #region Error        public void Error(string msg, params object[] args)
  42.         {
  43.             _logger.Error(msg, args);
  44.         }        public void Error(string msg, Exception err)
  45.         {
  46.             _logger.Error(err, msg);
  47.         }        #endregion
  48.         #region Fatal        public void Fatal(string msg, params object[] args)
  49.         {
  50.             _logger.Fatal(msg, args);
  51.         }        public void Fatal(string msg, Exception err)
  52.         {
  53.             _logger.Fatal(err, msg);
  54.         }        #endregion
  55.         #region Custom        public void Process(Models.Log log)
  56.         {            var level = LogLevel.Info;            if (log.Level == Models.EFLogLevel.Trace)
  57.                 level = LogLevel.Trace;            else if (log.Level == Models.EFLogLevel.Debug)
  58.                 level = LogLevel.Debug;            else if (log.Level == Models.EFLogLevel.Info)
  59.                 level = LogLevel.Info;            else if (log.Level == Models.EFLogLevel.Warn)
  60.                 level = LogLevel.Warn;            else if (log.Level == Models.EFLogLevel.Error)
  61.                 level = LogLevel.Error;            else if (log.Level == Models.EFLogLevel.Fatal)
  62.                 level = LogLevel.Fatal;            var ei = new MyLogEventInfo(level, _logger.Name, log.Message);
  63.             ei.TimeStamp = log.Timestamp;
  64.             ei.Properties["Action"] = log.Action;
  65.             ei.Properties["Amount"] = log.Amount;
  66.             _logger.Log(level, ei);
  67.         }        #endregion
  68.         /// <summary>
  69.         /// Flush any pending log messages (in case of asynchronous targets).        /// </summary>
  70.         /// <param name="timeoutMilliseconds">Maximum time to allow for the flush. Any messages after that time will be discarded.</param>
  71.         public void Flush(int? timeoutMilliseconds = null)
  72.         {            if (timeoutMilliseconds != null)
  73.                 NLog.LogManager.Flush(timeoutMilliseconds.Value);
  74.             NLog.LogManager.Flush();
  75.         }
  76.     }    public class MyLogEventInfo : LogEventInfo
  77.     {        public MyLogEventInfo() { }        public MyLogEventInfo(LogLevel level, string loggerName, string message) : base(level, loggerName, message)
  78.         { }        public override string ToString()
  79.         {            //Message format            //Log Event: Logger='XXX' Level=Info Message='XXX' SequenceID=5
  80.             return FormattedMessage;
  81.         }
  82.     }



</>code

  1. public class Log : IEntityBase<long>
  2.     {        public long Id { get; set; }        /// <summary>
  3.         /// 日志级别 Trace|Debug|Info|Warn|Error|Fatal        /// </summary>
  4.         public string Level { get; set; }        
  5.         public string Message { get; set; }
  6.         public string Action { get; set; }
  7.         public string Amount { get; set; }        public string StackTrace { get; set; }
  8.         public DateTime Timestamp { get; set; }        private Log() { }        public Log(string level, string message, string action = null, string amount = null)
  9.         {            this.Level = level;            this.Message = message;            this.Action = action;            
  10.             this.Amount = amount;
  11.         }
  12.     }


  • Models.Log是我们项目里的日志对象,它对应一个数据表Log,NLog将日志数据写入到这个表;

  • Process(Models.Log)是我们处理自定义对象的日志方法,用LogEventInfo来写入;

  • 重写 LogEventInfo.ToString() 是因为 LogEventInfo的Message格式是“Log Event: Logger='XXX' Level=Info Message='XXX' SequenceID=5”,不便于查阅,我们只需要我们设置的Message。

 

使用:

下面是测试方法,我们一共输出9条日志,这9条日志将输出到哪个目标,由配置文件中的Rules/logger决定


</>code

  1. Logger.Default.Trace("Hello World! Trace");
  2. Logger.Default.Info("Hello World! Info");
  3. Logger.Default.Warn("Hello World! Warn");
  4. Logger.Default.Debug("Hello World! Debug");
  5. Logger.Default.Error("Hello World! Error");
  6. Logger.Default.Fatal("Hello World! Fatal");
  7. Logger.Default.Process(new Models.Log(Models.EFLogLevel.Info, "Hello World! Info", "TEST", "100.00"));
  8. Logger.Default.Process(new Models.Log(Models.EFLogLevel.Debug, "Hello World! Debug", "TEST", "100.00"));
  9. Logger.Default.Process(new Models.Log(Models.EFLogLevel.Error, "Hello World! Error", "TEST", "100.00"));

</>code

  1. Logger.Default.Flush();


因为我们在Target中设置了异步,所以如果我们想当场看到输出结果,就需要使用Flush()方法,实际输出日志时就不需要了。

 

结果:

查看日志记录:


如对本文有疑问,请提交到交流论坛,广大热心网友会为你解答!! 点击进入论坛

发表评论 (687人查看0条评论)
请自觉遵守互联网相关的政策法规,严禁发布色情、暴力、反动的言论。
昵称:
最新评论
------分隔线----------------------------

快速入口

· 365软件
· 杰创官网
· 建站工具
· 网站大全

其它栏目

· 建站教程
· 365学习

业务咨询

· 技术支持
· 服务时间:9:00-18:00
365建站网二维码

Powered by 365建站网 RSS地图 HTML地图

copyright © 2013-2024 版权所有 鄂ICP备17013400号