问题
This is a base class, so I'm configuring an EventLogAppender entirely at runtime, like so:
Public MustInherit Class EventLogger
Public Sub Test(EventSource As String)
Dim oAppender As IAppender
oAppender = New EventLogAppender
With DirectCast(oAppender, EventLogAppender)
.ApplicationName = EventSource
.Category = 0 ' <========== Would like to set this value when logging
.EventId = 0
.Layout = New PatternLayout("%level: {0} %message%newline".ToFormat(EventSource))
.ActivateOptions()
End With
BasicConfigurator.Configure(oAppender)
Me.Logger = LogManager.GetLogger(Me.GetType)
Me.Logger.Info("Test")
End Sub
Private Logger As ILog
End Class
Public Module Extensions
<Extension>
Public Function ToFormat(Template As String, ParamArray Values As Object()) As String
Return String.Format(Template, Values)
End Function
End Module
It's easy enough to set the event category while building up the appender, but I'd like the category to correspond with the log level.
Is there a way to do this without having to build a special appender for each log level at the time the logger is called? That's sure to be a performance killer.
It doesn't look like it, but I could be wrong. It happened to me once before.
回答1:
OK, got it. Thanks to Stafford for providing the solution... add an IAppender
for each Category and set its filter accordingly. Performance isn't impacted because this only happens once.
Here's how:
Public Class EvAppender
Inherits EventLogAppender
Private Sub New(ApplicationName As String, Category As Categories)
Me.ApplicationName = ApplicationName
Me.Category = Category
Me.EventId = 0
Me.Layout = New PatternLayout("Level: %level%newlineSource: %logger.%M()%newlineMessage: %message%newline%exception")
Me.Name = "{0}Appender".ToFormat(Category.ToString)
Me.AddMapping(Me.GetMapping(Level.Debug))
Me.AddMapping(Me.GetMapping(Level.Info))
Me.AddMapping(Me.GetMapping(Level.Warn))
Me.AddMapping(Me.GetMapping(Level.Error))
Me.AddMapping(Me.GetMapping(Level.Fatal))
Me.AddFilter(New LevelRangeFilter With
{
.LevelMin = Me.LogLevel(Category),
.LevelMax = Me.LogLevel(Category)
})
Me.ActivateOptions()
End Sub
Public Shared Function Build(ApplicationName As String) As List(Of EvAppender)
Build = New List(Of EvAppender)
Build.Add(New EvAppender(ApplicationName, Categories.Debug))
Build.Add(New EvAppender(ApplicationName, Categories.Info))
Build.Add(New EvAppender(ApplicationName, Categories.Warn))
Build.Add(New EvAppender(ApplicationName, Categories.Error))
Build.Add(New EvAppender(ApplicationName, Categories.Fatal))
End Function
Private Function GetMapping(LogLevel As Level) As EventLogAppender.Level2EventLogEntryType
GetMapping = New EventLogAppender.Level2EventLogEntryType
GetMapping.Level = LogLevel
Select Case GetMapping.Level
Case Level.Debug : GetMapping.EventLogEntryType = EventLogEntryType.Information
Case Level.Info : GetMapping.EventLogEntryType = EventLogEntryType.Information
Case Level.Warn : GetMapping.EventLogEntryType = EventLogEntryType.Warning
Case Level.Error : GetMapping.EventLogEntryType = EventLogEntryType.Error
Case Level.Fatal : GetMapping.EventLogEntryType = EventLogEntryType.Error
End Select
End Function
Private Function GetLogLevel(Category As Categories) As Level
Select Case Category
Case Categories.Debug : LogLevel = Level.Debug
Case Categories.Info : LogLevel = Level.Info
Case Categories.Warn : LogLevel = Level.Warn
Case Categories.Error : LogLevel = Level.Error
Case Categories.Fatal : LogLevel = Level.Fatal
Case Else : LogLevel = Level.All
End Select
End Function
Private Enum Categories
Debug = 3
Info = 4
Warn = 6
[Error] = 7
Fatal = 11
End Enum
End Class
Use it like this:
BasicConfigurator.Configure(EvAppender.Build(ApplicationName).ToArray)
Logger = LogManager.GetLogger(ApplicationName)
来源:https://stackoverflow.com/questions/32295310/eventlogappender-can-we-set-the-event-category-at-runtime-without-recreating