NLog自定义日志级别值

时间:2011-07-18 20:15:17

标签: c# nlog

我有一个数据库我正在尝试编写我的消息并希望使用$ {level}布局,但我需要将其转换为int值以引用我自己的存储日志级别的表。是否有可能在配置中将级别转换为我的枚举?还有其他想法吗?

3 个答案:

答案 0 :(得分:1)

我没有检查过这个,但我怀疑你应该能够为nLog编写自己的布局渲染器(插件)来做你想做的事情。 nLog非常可插拔:)

布局渲染器的外观(未经测试......)的快速示例,

[LayoutRenderer("intLevel", UsingLogEventInfo = true)] public class IntLevel : LayoutRenderer { protected override int GetEstimatedBufferSize(LogEventInfo logEvent) { return 1; }

protected override void Append(StringBuilder builder, LogEventInfo logEvent)
{
    switch(logEvent.Level.LowercaseName)
    {
        case "trace":
            builder.Append(0);
            break;
        case "debug":
            builder.Append(1);
            break;
        case "info":
            builder.Append(2);
            break;
        case "warn":
            builder.Append(3);
            break;
        case "error":
            builder.Append(4);
            break;
        case "fatal":
            builder.Append(5);
            break;
        default:
            builder.Append(-1);
            break;
    }
}

protected override void Append(StringBuilder builder, LogEventInfo logEvent) { switch(logEvent.Level.LowercaseName) { case "trace": builder.Append(0); break; case "debug": builder.Append(1); break; case "info": builder.Append(2); break; case "warn": builder.Append(3); break; case "error": builder.Append(4); break; case "fatal": builder.Append(5); break; default: builder.Append(-1); break; } }

答案 1 :(得分:1)

试试这个解决方案:

[LayoutRenderer("levelInt")]
public class NlogLevelToIntLayoutRenderer : LayoutRenderer
{
    protected override void Append(StringBuilder builder, LogEventInfo logEvent)
    {
        builder.Append(logEvent.Level.Ordinal);
    }
}

答案 2 :(得分:0)

这是一个经过测试的布局渲染器,它将日志级别记录为整数。我获得日志级别的方式可能有点过分,但我正在经历一个linq阶段; - )

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

using NLog;
using NLog.LayoutRenderers;

namespace MyNLogExtensions.NLog
{
  [LayoutRenderer("LogLevelOrdinal")]
  class LogLevelOrdinalLayoutRenderer : LayoutRenderer
  {
    IDictionary<LogLevel, int> ordinals;

    public override void  Initialize()
    {
      base.Initialize();

      ordinals = GetLogLevels()
                  .OrderBy(level => level)
                  .Select((level, index) => new { Level = level, Ordinal = index })
                  .ToDictionary( x => x.Level, x => x.Ordinal);
    }

    protected override void Append(StringBuilder builder, LogEventInfo logEvent)
    {
      int level = 0;

      if (!ordinals.TryGetValue(logEvent.Level, out level)) level = 99;

      builder.Append(level);
    }

    protected override int GetEstimatedBufferSize(LogEventInfo logEvent)
    {
      return 1;
    }

    //
    // LogLevel is a static class with a static member for each of the different log levels.
    // The LogLevel ordinal is not exposed publically (i.e. an ordinal indicating the relative
    // "importance" of a LogLevel value).
    // The implementation of LogLevel.GetHashCode actually does return the ordinal, but it doesn't
    // seem right to rely on that implementation detail.
    // In the end, this LayoutRenderer is really just to allow for producing a numeric value to represent
    // a particular log level value's "position" relative to the other lob levels.  As such, 
    // We can just get all of the known log level values, order them (they are sortable), and assign our
    // own ordinal based on the position of the log level value in the resulting sorted list.
    //
    // This helper function exposes the known log level values as IEnumerable<LogLevel> so that we can
    // easily use LINQ to build a dictionary to map LogLevel to ordinal.
    //
    internal IEnumerable<LogLevel> GetLogLevels()
    {
      yield return LogLevel.Trace;
      yield return LogLevel.Debug;
      yield return LogLevel.Info;
      yield return LogLevel.Warn;
      yield return LogLevel.Error;
      yield return LogLevel.Fatal;
    }

  }
}