Log4net EventLogAppender日志事件ID

时间:2010-02-18 16:14:53

标签: log4net

有没有办法使用指定的每条消息的eventid将事件记录到Windows事件日志中?我正在使用log4net v 1.2.10。

5 个答案:

答案 0 :(得分:19)

根据我在EventLogAppender源代码中看到的内容,以下应该可以解决这个问题:

  

log4net.ThreadContext.Properties [“EventID”] = 5;

在编写日志消息之前只需调用它(如果没有为所有消息设置它,则应从属性中再次删除“EventID”。

N.B属性键区分大小写。

答案 1 :(得分:6)

当在System.Diagnostics中使用本机.net事件日志API时,WriteEntry方法允许设置eventID和类别。在这些API中:

  • eventID是32位int,但其值必须介于0到65535之间
  • 类别是16位int,但其值必须为正数。如果 事件源包括category resource file,事件查看器将 使用整数类别值来查找本地化的“任务类别” 串。否则,显示整数值。 categories must be numbered consecutively,以...开头 1号

Log4net支持编写EventID和类别,但它不是直截了当的。当log4net的EventLogAppender记录一个事件时,它会查看一个属性字典。 EventLogAppender将命名属性“EventID”和“Category”自动映射到事件日志中的相应值。我已经看到了一些很好的建议方法来使用log4net的EventLogAppender并在Windows事件日志中设置EventID和Category。

一个。使用log4net的appender过滤,可以添加EventID和Category属性的filter may be registered。此方法具有使用标准log4net包装器的好处,因此可以在不更改现有日志记录代码的情况下实现此方法。此方法的难点是必须创建一些机制来从记录的信息中计算EventID和Category。例如,过滤器可以查看异常源并将该源映射到Category值。

湾可以扩展Log4net,因此可以使用包含EventID和Category参数的自定义日志记录包装器。添加EventID在log4net示例“Extensibility - EventIDLogApp”中进行了演示,该示例包含在log4net源中。在扩展示例中,使用了一个新接口(IEventIDLog),它扩展了应用程序用于记录的标准ILog接口。这提供了包含eventId参数的新日志记录方法。在记录事件之前,新的日志记录方法将eventId添加到Properties字典中。

public void Info(int eventId, object message, System.Exception t)
{
       if (this.IsInfoEnabled)
       {
             LoggingEvent loggingEvent = new LoggingEvent(ThisDeclaringType, Logger.Repository, Logger.Name, Level.Info, message, t);
             loggingEvent.Properties["EventID"] = eventId;
             Logger.Log(loggingEvent);
       }
}

℃。 Log4net支持包含Properties字典的ThreadContext对象。应用程序可以在此字典中设置EventID和Category属性,然后当线程调用日志记录方法时,EventLogAppender将使用这些值。

log4net.ThreadContext.Properties["EventID"] = 5;

一些有用的参考资料:

答案 2 :(得分:5)

嗯,解决方案是构建扩展项目“log4net.Ext.EventID”并使用其类型:IEventIDLog,EventIDLogImpl和EventIDLogManager。

答案 3 :(得分:2)

另一种解决方案是按照此处所述添加自定义FilterEnhancing log4net exception logging (直接链接到Gist以防万一)

正如作者指出:

  

... EventLogAppender使用内联consts来检查它们。一旦添加它们,它们将被提到的EventLogAppender用于使用EventId和Category标记给定条目。

过滤器实现看起来就像(剥离要点)下面的代码一样,还有一个额外的好处,即如果你将GetEventId方法公开,你可以针对它编写一些测试

public class ExceptionBasedLogEnhancer : FilterSkeleton
{
    private const string EventLogKeyEventId = "EventID";

    public override FilterDecision Decide(LoggingEvent loggingEvent)
    {
        var ex = loggingEvent.ExceptionObject;
        if (ex != null)
        {
            loggingEvent.Properties[EventLogKeyEventId] = GetEventId(ex);
        }

        return FilterDecision.Neutral;
    }

    private static short GetEventId(Exception ex)
    {
        // more fancy implementation, like getting hash of ex properties 
        // can be provided, or mapping types of exceptions to eventids
        // return no more than short.MaxValue, otherwise the EventLog will throw
        return 0;
    }
}

答案 4 :(得分:0)

扩展ILog.Info()以获取事件ID:

public static class LogUtils
{
    public static void Info(this ILog logger, int eventId, object message)
    {
        log4net.ThreadContext.Properties["EventID"] = eventId;
        logger.Info(message);
        log4net.ThreadContext.Properties["EventID"] = 0; // back to default
    }
}

然后这样称呼:

using LogUtils;
private static readonly log4net.ILog _logger = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);

_logger.Info(3, "First shalt thou take out the Holy Pin, then shalt thou count to three.");