我有一个包含多个部分的应用程序.
我在整个过程中都使用log4net记录事件,并且我希望这些事件具有与它们来自的应用程序中的WHERE匹配的SOURCE(您知道像“ SOURCE”所示).因此,我在“应用程序和服务日志”下有一个日志,并按照您的期望设置了log4net.
在log4net配置中,有一个元素“ applicationName”,根据文档说明,该元素指定“将在其中存储消息的日志的名称”.
文档中的示例显示
<applicationName value="MyApp" />
Log4Net使用“ applicationName”中的值记录事件.根据log4net源代码中的文档,“应使用ApplicationName属性来区分事件”.
因此,假设LogName设置正确,我希望在事件查看器的“应用程序和服务日志”下看到我的“ 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和事件ID …
这有点麻烦,但我看不到不创建自定义Appender即可更简单地设置日志源的方法…