Пользовательский NLog LogLevels или несколько регистраторов на класс? - PullRequest
5 голосов
/ 06 октября 2010

Как я могу отделить мою normal регистрацию / аудит от моей регистрации / аудита безопасности?Журнал событий Windows делает это различие с событиями приложения и событиями безопасности.

Если бы я мог создать пользовательский уровень LogLevel, например, LogLevel.AuditSuccess или LogLevel.AuditFailure, то я мог бы установить правила моего файла конфигурации равными этим и вывестиэти события.Например,

<logger name="*" levels="AuditSuccess,AuditFailure" writeTo="target1"/>
<logger name="*" levels="DEBUG,INFO" writeTo="target1"/>

Тогда я мог бы просто использовать 1 таблицу, записать «Уровень» в столбце и иметь возможность искать и сортировать мои данные, используя эту информацию столбца.(Я не думаю, что мы можем создать пользовательский уровень LogLevel.)

Один из обходных путей, который я придумала, - это использование 2 регистраторов на класс - при этом каждый регистратор сохраняется в другой цели.Тем не менее, это кажется излишним, особенно если мне нужно добавить дополнительные похожие типы целей.

<logger name="myNamespace.*" levels="INFO,ERROR" writeTo="target1"/>
<logger name="mySecurityLogger" levels="INFO,ERROR" writeTo="target2"/>

public class MyClass {
    private static Logger _logger = LogManager.GetCurrentClassLogger();
    private statac Logger _loggerSecurity = LogManager.GetLogger("mySecurityLogger");
    ...
}

С этим я могу создать две цели базы данных - каждая с другой таблицей - и затем создать 1 правилодля каждой цели назначения.

Есть предложения?

Ответы [ 2 ]

6 голосов
/ 08 октября 2010

Возможно, это не то, что вам нужно, но потерпите меня ...

Вы можете обернуть NLog так, чтобы вы могли регистрироваться с помощью своих собственных "регистраторов". Взгляните на Common.Logging для .NET или SLF , чтобы найти примеры того, как обернуть NLog (они являются полными абстракциями журналирования, поэтому они более сложны, чем то, что вам нужно, но Вы могли бы подобрать несколько хороших идей). Также см. здесь (вероятно, следует посмотреть здесь в первую очередь, если вы считаете, что вас может заинтересовать просто обертывание или создание подкласса NLog Logger), чтобы найти примеры того, как правильно обернуть (или создать подкласс) NLog (обратите внимание, что ключ передать тип вашего упакованного / вложенного регистратора в метод журнала NLog).

Итак, у вас может быть что-то вроде этого (сокращенно):

//Wrapped logger that you could create once in a class and use to log both 
//"normal" messages and "audit" messages.  NLog log level is determined by the 
//logger configuration for the class.
public class MyLogger
{
  private Logger logger; //NLog logger

  public MyLogger(string name)
  {
    logger = LogManager.GetLogger(name);
  }

  public void Info(string message)
  {
    if (!logger.IsInfoEnabled) return;

    Write(LogLevel.Info, LogLevel.Info.ToString(), message);
  }

  public void AuditSuccess(string message)
  { 
    if (!logger.IsInfoEnabled) return;

    Write(LogLevel.Info, "AuditSuccess", message);
  }

  private void Write(LogLevel level, string customLevel, string message)
  {
    LogEventInfo le = new LogEventInfo(level, logger.Name, message);
    le.Context["CustomLogLevel"] = customLevel;
    logger.Log(typeof(MyLogger), le);
  }
}

Это даст вам методы ведения журнала, соответствующие вашим пользовательским уровням. Это также даст вам возможность вывести пользовательский столбец, содержащий ваш «пользовательский уровень» ( с использованием средства визуализации контекста события ). Это не дает вам возможность включать или выключать вход в систему на уровне «AuditSuccess». Он все еще должен контролироваться встроенными уровнями.

В качестве альтернативы, вы можете включить два регистратора в ваш упакованный класс и использовать один для встроенных уровней, а другой для пользовательских уровней. Ваша обертка может выглядеть так:

//Wrapped logger that you could create once in a class and use to log both "normal"
//and "audit" messages.  NLog log level for each type of message is controllable
//separately since the logger wrapper actually wraps two logger.
public class MyLogger
{
  private Logger logger; //NLog logger
  private Logger auditLogger;

  public MyLogger(string name)
  {
    logger = LogManager.GetLogger(name);
    auditLogger = LogManager.GetLogger("AuditLogger");
  }

  public void Info(string message)
  {
    if (!logger.IsInfoEnabled) return;

    Write(logger, LogLevel.Info, LogLevel.Info.ToString(), messsage);
  }

  public void AuditSuccess(string message)
  { 
    if (!auditLogger.IsInfoEnabled) return;

    Write(auditLogger, LogLevel.Info, "AuditSuccess", message);
  }

  private void Write(Logger log, LogLevel level, string customLevel, string message)
  {
    LogEventInfo le = new LogEventInfo(level, log.Name, message);
    le.Context["CustomLogLevel"] = customLevel;
    log.Log(typeof(MyLogger), le);
  }
}

Вы по-прежнему будете иметь те же ограничения, что перечислены выше, но вы можете по крайней мере контролировать ведение журнала аудита / безопасности отдельно от "обычного" ведения журнала.

В любом случае вы можете отправить выходные данные всех регистраторов в одну и ту же базу данных и просто выполнять запросы в столбце «пользовательского уровня», а не в столбце «уровня». В зависимости от того, сколько у вас «категорий» безопасности / аудита, вы можете даже создать конкретную иерархию, чтобы вы могли использовать преимущества иерархий регистратора в файле конфигурации NLog:

Безопасность Security.Audit Security.Audit.Success Security.Audit.Failure Security.Login Security.Login.Success Security.Login.Failure Здоровье Health.Heartbeat Health.Whatever

Тогда вы можете «включить» Security или Security.Audit или . . Отказ (не уверен, работает ли последний или нет).

Надеюсь, это поможет.

3 голосов
/ 08 октября 2010

Не могли бы вы использовать два регистратора с разными именами в своем классе, вывести на одну и ту же цель и использовать $ {logger} средство визуализации макета *1002* в качестве значения поля?

Честно говоря, если эти события так важны в области приложения, возможно, запись их через каркас журналирования является неправильным способом сделать это. Возможно, это должно быть более четко смоделированное понятие в вашем приложении. Конечно, если вам необходимо хранить данные о событиях в том же месте, что и другие сообщения журнала, у вас может не быть этого выбора.

В противном случае я склонен отклоняться от пользовательских уровней ведения журнала, так как они никогда не доказывали, стоит ли добавлять их.

...