0%

原文:http://www.cnblogs.com/felixnet/p/5498759.html

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

下载

通过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调试窗口,完整配置文件如下:

复制代码

复制代码

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

<logger name=“*“ minlevel=“Trace” writeTo=“debugger” />

<logger name=“*“ minlevel=“Info” writeTo=“db” />

<logger name=“*“ minlevel=“Debug” writeTo=“file” />
</rules>
</nlog>

复制代码

复制代码

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

复制代码

复制代码

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 {
public long Id { get; set; }
///


/// 日志级别 Trace|Debug|Info|Warn|Error|Fatal
///

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是我们项目里的日志对象,它对应一个数据表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决定

复制代码

复制代码

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()方法,实际输出日志时就不需要了。

结果:

查看日志记录: