C#C# 使用NLog记录日志

NLog是2个记下日志组件,和log4net一样被广泛使用,它可以将日志保存到文本文件、CSV、控制台、VS调试窗口、数据库等。近期刚用到这些组件,觉得不错,水1篇。

 

下载

经过Nuget安装NLog,你也能够而且安装NLog.Config,它会在品种目录下帮您建立1个安顿文件NLog.config,可是不必要,大家直接手动建立一个,你也得以将配置的音信写入到
App.config/Web.config,小编相比喜欢独立出来,不与别的配置掺和在一块儿。

C# 1

 

配置

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

<?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

C# 2

 

未来大家要将日志输出到文本文件,数据库,VS调节和测试窗口,完整配置文件如下:

<?xml version="1.0" ?>

<!--<nlog xmlns="http://www.nlog-project.org/schemas/NLog.xsd"
      xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
      autoReload="true"
      internalLogLevel="Trace"
      internalLogFile="D:\work\log.txt">-->

<nlog xmlns="http://www.nlog-project.org/schemas/NLog.xsd"
      xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
      autoReload="true">

  <targets>

    <!-- Log in a separate thread, possibly queueing up to
        5000 messages. When the queue overflows, discard any
        extra messages-->

    <!-- write logs to file -->
    <target name="file" xsi:type="AsyncWrapper" queueLimit="5000" overflowAction="Discard">
      <target xsi:type="File" fileName="${basedir}/logs/${shortdate}.log" layout="${longdate} ${level:uppercase=true} ${event-context:item=Action} ${message} ${event-context:item=Amount} ${stacktrace}" />      
    </target>

    <!-- write log message to database -->
    <target name="db" xsi:type="AsyncWrapper" queueLimit="5000" overflowAction="Discard">
      <target type="Database" dbProvider="mssql" connectionString="Data Source=.\SQLEXPRESS;Initial Catalog=EFinance;Persist Security Info=True;User ID=sa;Password=123456;">

        <commandText>
          INSERT INTO Log(Timestamp,Level,Message,Action,Amount,StackTrace) VALUES(@time_stamp, @level, @message, @action, @amount, @stacktrace);
        </commandText>

        <!-- database connection parameters -->
        <parameter name="@time_stamp" layout="${date}" />
        <parameter name="@level" layout="${level:uppercase=true}" />
        <parameter name="@message" layout="${message}" />
        <parameter name="@action" layout="${event-context:item=Action}" />
        <parameter name="@amount" layout="${event-context:item=Amount}" />
        <parameter name="@stacktrace" layout="${stacktrace}" />
      </target>
    </target>

    <!--write log message to Visual Studio Output-->
    <target name="debugger" xsi:type="Debugger" layout="NLog: ${date:format=HH\:mm\:ss} | ${level:uppercase=true:padding=-5} | ${message}" />
  </targets>

  <rules>
    <!--TRACE,DEBUG,INFO,WARN,ERROR,FATAL-->
    <logger name="*" minlevel="Trace" writeTo="debugger" />
    <!--INFO,WARN,ERROR,FATAL-->
    <logger name="*" minlevel="Info" writeTo="db" />
    <!--DEBUG,INFO,WARN,ERROR,FATAL-->
    <logger name="*" minlevel="Debug" writeTo="file" />    
  </rules>
</nlog>
  • 如在根节点(nlog)配置 internalLogLevel,
    internalLogFile,能够查阅NLog输出日志时的中间音信,比如您安顿文件有荒唐,很有赞助,不过项目揭露后也许关闭比较好,避防影响功效;
  • 在target外面罩了二个 <target>并且xsi:type为
    AsyncWrapper,即意味着这条 target
    将异步输出,那里笔者将文件和数据库日志异步输出;
  • db target内钦点了数据库连接字符串
    connectionString,SQL语句,SQL参数,还足以内定数据库/表创建和删除的剧本(推荐看NLog源码示例,那里不介绍),同时大家自定义了三个参数
    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:

public class Logger
    {
        NLog.Logger _logger;

        private Logger(NLog.Logger logger)
        {
            _logger = logger;
        }

        public Logger(string name) : this(LogManager.GetLogger(name))
        {

        }

        public static Logger Default { get; private set; }
        static Logger()
        {
            Default = new Logger(NLog.LogManager.GetCurrentClassLogger());
        }

        #region Debug
        public void Debug(string msg, params object[] args)
        {
            _logger.Debug(msg, args);
        }        

        public void Debug(string msg, Exception err)
        {
            _logger.Debug(err, msg);
        }        
        #endregion

        #region Info
        public void Info(string msg, params object[] args)
        {
            _logger.Info(msg, args);
        }

        public void Info(string msg, Exception err)
        {
            _logger.Info(err, msg);
        }
        #endregion

        #region Warn
        public void Warn(string msg, params object[] args)
        {
            _logger.Warn(msg, args);
        }

        public void Warn(string msg, Exception err)
        {
            _logger.Warn(err, msg);
        }
        #endregion

        #region Trace
        public void Trace(string msg, params object[] args)
        {
            _logger.Trace(msg, args);
        }

        public void Trace(string msg, Exception err)
        {
            _logger.Trace(err, msg);
        }
        #endregion

        #region Error
        public void Error(string msg, params object[] args)
        {
            _logger.Error(msg, args);
        }

        public void Error(string msg, Exception err)
        {
            _logger.Error(err, msg);
        }
        #endregion

        #region Fatal
        public void Fatal(string msg, params object[] args)
        {
            _logger.Fatal(msg, args);
        }

        public void Fatal(string msg, Exception err)
        {
            _logger.Fatal(err, msg);
        }
        #endregion

        #region Custom

        public void Process(Models.Log log)
        {
            var level = LogLevel.Info;
            if (log.Level == Models.EFLogLevel.Trace)
                level = LogLevel.Trace;
            else if (log.Level == Models.EFLogLevel.Debug)
                level = LogLevel.Debug;
            else if (log.Level == Models.EFLogLevel.Info)
                level = LogLevel.Info;
            else if (log.Level == Models.EFLogLevel.Warn)
                level = LogLevel.Warn;
            else if (log.Level == Models.EFLogLevel.Error)
                level = LogLevel.Error;
            else if (log.Level == Models.EFLogLevel.Fatal)
                level = LogLevel.Fatal;

            var ei = new MyLogEventInfo(level, _logger.Name, log.Message);
            ei.TimeStamp = log.Timestamp;
            ei.Properties["Action"] = log.Action;
            ei.Properties["Amount"] = log.Amount;

            _logger.Log(level, ei);
        }

        #endregion

        /// <summary>
        /// Flush any pending log messages (in case of asynchronous targets).
        /// </summary>
        /// <param name="timeoutMilliseconds">Maximum time to allow for the flush. Any messages after that time will be discarded.</param>
        public void Flush(int? timeoutMilliseconds = null)
        {
            if (timeoutMilliseconds != null)
                NLog.LogManager.Flush(timeoutMilliseconds.Value);

            NLog.LogManager.Flush();
        }
    }

    public class MyLogEventInfo : LogEventInfo
    {
        public MyLogEventInfo() { }
        public MyLogEventInfo(LogLevel level, string loggerName, string message) : base(level, loggerName, message)
        { }

        public override string ToString()
        {
            //Message format
            //Log Event: Logger='XXX' Level=Info Message='XXX' SequenceID=5
            return FormattedMessage;
        }
    }

public class Log : IEntityBase<long>
    {
        public long Id { get; set; }
        /// <summary>
        /// 日志级别 Trace|Debug|Info|Warn|Error|Fatal
        /// </summary>
        public string Level { get; set; }        
        public string Message { get; set; }
        public string Action { get; set; }
        public string Amount { get; set; }
        public string StackTrace { get; set; }
        public DateTime Timestamp { get; set; }

        private Log() { }
        public Log(string level, string message, string action = null, string amount = null)
        {
            this.Level = level;
            this.Message = message;
            this.Action = action;            
            this.Amount = amount;
        }
    }
  • Models.Log是大家项目里的日记对象,它对应3个数额表Log,NLog将日志数据写入到这一个表;
  • Process(Models.Log)是我们处理自定义对象的日志方法,用Log伊夫ntInfo来写入;
  • 重写 LogEventInfo.ToString() 是因为
    LogEventInfo的Message格式是“Log Event: Logger=’XXX’ Level=Info
    Message=’XXX’
    SequenceID=5
    ”,不便于查阅,大家只须要大家设置的Message。

 

使用:

下边是测试方法,我们壹起输出九条日志,那九条日志将出口到哪个指标,由安插文件中的Rules/logger决定

Logger.Default.Trace("Hello World! Trace");
Logger.Default.Info("Hello World! Info");
Logger.Default.Warn("Hello World! Warn");
Logger.Default.Debug("Hello World! Debug");
Logger.Default.Error("Hello World! Error");
Logger.Default.Fatal("Hello World! Fatal");

Logger.Default.Process(new Models.Log(Models.EFLogLevel.Info, "Hello World! Info", "TEST", "100.00"));
Logger.Default.Process(new Models.Log(Models.EFLogLevel.Debug, "Hello World! Debug", "TEST", "100.00"));
Logger.Default.Process(new Models.Log(Models.EFLogLevel.Error, "Hello World! Error", "TEST", "100.00"));

Logger.Default.Flush();

因为我们在Target中设置了异步,所以假设大家想当场看到输出结果,就供给动用Flush()方法,实际出口日志时就不须求了。

 

结果:

查看日志记录:

C# 3

C# 4

 

相关文章