Значение настраиваемого уровня журнала NLog

У меня есть база данных, в которую я пытаюсь писать сообщения, и я хотел бы использовать макет $ {level}, но мне нужно преобразовать его в значение int для ссылки на мою собственную таблицу, в которой хранятся уровни ведения журнала. Возможно ли, чтобы уровень был приведен к моему перечислению в конфигурации? Есть другие идеи?


person Benny    schedule 18.07.2011    source источник


Ответы (3)


Я не проверял это, но подозреваю, что вы сможете просто написать свой собственный модуль рендеринга макета (плагин), чтобы 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;
        }
    }
}
person Viktor    schedule 18.07.2011

Попробуйте это решение:

[LayoutRenderer("levelInt")]
public class NlogLevelToIntLayoutRenderer : LayoutRenderer
{
    protected override void Append(StringBuilder builder, LogEventInfo logEvent)
    {
        builder.Append(logEvent.Level.Ordinal);
    }
}
person YD1m    schedule 05.09.2014
comment
Работает как шарм. Не забудьте ConfigurationItemFactory.Default.LayoutRenderers.RegisterDefinition перед использованием LayoutRenderer. - person niaher; 10.09.2014

Вот протестированный модуль рендеринга макета, который регистрирует уровень журнала как целое число. То, как я получаю уровни журнала, вероятно, немного за бортом, но я проходил фазу 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;
    }

  }
}
person wageoghe    schedule 18.07.2011
comment
Не могу заставить упрощенную версию работать на меня, поскольку LogLevel - это класс, а не перечисление. Может это разница между v1.0 и v2.0, я до сих пор использую v1.0. - person Viktor; 19.07.2011
comment
@Viktor - Ты прав! Я слишком упростил без тестирования. Я забыл, что LogLevel - это класс, а не перечисление. Я удалю упрощение, чтобы никто не запутался. - person wageoghe; 19.07.2011