自定义NLog日志级别或每个类多个日志记录器?

5

我该如何将我的“普通”日志/审计与安全日志/审计分开?Windows事件日志通过应用程序事件和安全事件进行区分。

如果我能创建自定义的日志级别,例如LogLevel.AuditSuccess或LogLevel.AuditFailure,那么我可以设置我的配置文件规则等于这些级别并输出这些事件。例如:

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

那么我只需要使用一个表格,在一列中记录“级别”,就可以使用这个列信息搜索和排序我的数据。 (我认为我们无法创建自定义日志级别。)

我想到的一个解决方法是每个类使用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");
    ...
}

我可以创建两个数据库目标,每个目标都有不同的表,然后为每个目标创建一个规则。

您有什么建议吗?

2个回答

6
这可能不是你想要的,但请耐心听我说...
您可以包装NLog,使您可以使用自己的“记录器”进行日志记录。查看 .NET的Common.LoggingSLF的示例,了解如何包装NLog(它们是完整的日志记录抽象,因此比您想要的更复杂,但您可能会获得一些好的想法)。另请参阅此处(如果您认为您可能有兴趣简单地包装或子类化NLog Logger,则应首先查看此处)以了解正确包装(或子类化)NLog的示例(请注意,关键是将您包装/子类化的记录器类型传递给NLog的Log方法)。
因此,您可能会有类似以下的东西(缩写):
//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 Security.Audit Security.Audit.Success Security.Audit.Failure Security.Login Security.Login.Success Security.Login.Failure Health Health.Heartbeat Health.Whatever

然后,您可以“启用”Security或Security.Audit或。 .Failure(不确定最后一个是否有效)。 希望这可以帮助您。

3

你能否在类中使用两个不同命名的记录器,输出到同一个目标,并将${logger} layout renderer用作字段值?

老实说,如果这些事件在应用程序域中如此重要,也许通过日志记录框架记录它们是错误的方式。也许在你的应用程序中应该有一个更明确的建模概念。当然,如果你需要将事件数据存储在与其他日志消息相同的位置,你可能没有选择。

否则,我倾向于避免自定义日志级别,因为它们从未证明增加它们的麻烦是值得的。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接