log4net 应该如何在应用程序中正确地为 "EventLogAppender" 设置 "source"...?

How should log4net CORRECTLY set the "source" for an "EventLogAppender" within the application...?

我有一个应用程序,包含多个部分。

我一直在使用 log4net 来记录事件,我希望这些事件有一个与它们来自的应用程序中的 WHERE 相匹配的 SOURCE(你知道 "SOURCE" 暗示)。所以我在 "Applications and Services Logs" 下有一个日志,并按照您的预期设置了 log4net。

在 log4net 配置中有一个元素 "applicationName",根据文档指定 "The name of the log where messages will be stored."

文档中的示例显示

<applicationName value="MyApp" />

Log4Net 使用 "applicationName" 中的值来记录事件。根据 log4net 源代码中的文档 "ApplicationName property should be used to distinguish events"。

所以假设 LogName 设置正确,我希望在事件查看器中的 "Applications and Services Logs" 下看到我的 "LogName",然后我只需要设置 applicationName 以获得正确的源。但是,applicationName 似乎只在配置中设置...但这意味着所有事件都记录在同一源下:

应该如何设置源名称...?有其他方法可以做到这一点吗?

我没有找到答案,所以我下载了 log4net 的源代码并决定弄明白。

以下代码片段在 log4net 中设置 ApplicationName

    private static void SetEventSource(string sourceName)
    {
        var repository = LogManager.GetRepository();
        if (repository != null)
        {
            var appender = repository.GetAppenders().Where(x => x.Name == "eventLogAppender").FirstOrDefault();
            if (appender is log4net.Appender.EventLogAppender)
            {
                var eventAppender = (log4net.Appender.EventLogAppender)appender;
                eventAppender.ApplicationName = sourceName;
                eventAppender.ActivateOptions();
            }
        }
    }

我有一个 "LoggingSources" 的枚举,所以我只是在应用程序启动时循环它以确保日志源存在。

    public static void ConfigureWindowsEvents()
    {
        // Create event log sources for each of our Logging types
        var loggingEvents = Enum.GetValues(typeof(LoggingSources));
        foreach (var item in loggingSources)
        {
            string source = item.ToString();

            if (!EventLog.SourceExists(source))
            {
                EventLog.CreateEventSource(source, EVENT_LOG_NAME);
            }
        }
    }

然后当我记录事件时,我设置源和事件 ID

    public static void SetThreadContextAndLog(LoggingSources eventId, Action logAction)
    {
        if (logAction != null)
        {
            log4net.ThreadContext.Properties[EVENT_ID_KEY] = (int)eventId;
            try
            {
                SetEventSource(eventId.ToString());
                logAction(); 
            }
            finally
            {
                log4net.ThreadContext.Properties[EVENT_ID_KEY] = DEFAULT_EVENT_ID;
            }
        }
    }

调用方法如下...

    public static void LogEvent(LoggingSources pEvent, string pMessage, EventLogEntryType pEventType)
    {
        SetThreadContextAndLog(pEvent, () =>
        {
            if (pEventType == EventLogEntryType.Warning)
            {
                Log.Warn(pMessage);
            }
        });
    }

这会导致正确设置源和事件 ID...

这有点麻烦,但我看不到在不创建自定义 Appender 的情况下设置日志源的更简洁的方法...