Tom, Thanks for sharing the code and ideas. I think WMI is an area where we could do a lot more integration work.
I think that your approach is valid, but does still run into the same problems. Basically using your appender the caller has to construct their WMIable object and pass it to log4net. If the event is delivered to the appender then Instrumentation.Fire is called with the message object. Log4net is being used only as a configurable switch. The message object is not necessarily compatible with other appenders - this could be overcome with custom ObjectRenderers. The biggest drawback is that the appender does not work with any other type of message data, therefore it cannot be use in conjunction with exiting applications that have logging. There are a number of possible approaches that need to be considered: * There is the method that you have proposed where the caller has to generate an WMI aware object, pack it with the right data, and then log it. * Another approach is to have a single WMI aware type within the appender. For each event the appender creates a new (or maybe reuses) one of these object, populates it with all the data from the logging event, then fires it. This means that the layout of the WMI event will be the same for all users and event types. Depending on the way WMI is used this may not be appropriate. * Yet another approach is to have the appender accept any message, then pass it to a 3rd party factory object that will convert the logging event into a WMI compatible object. The appender would need to be configured with the type of the 3rd party converter object. This would give the flexibility required, but it does require custom code to get the base case working. * An ideal solution would be to specify the format of the WMI message in the config for the appender. The appender would perform the mapping from the logging event into the WMI message similarly to the way in which the AsoNetAppender uses the PatternLayout to setup the stored procedure parameters. The difficulty with this is that it can't use the Instrumentation.Fire method to raise the event, we would need to get in at a lower level where the WMI message exists as data rather than as an object. Are there any WMI experts out there who would know if an app should fire different types of object for different events? Are there standard WMI schemas that the application needs to conform to? In the long term I would prefer a solution that used a 3rd party factory to convert the event into a WMI object, rather than one that required the user to change all their logging calls to pass WMI objects. What are your thoughts on this? Nicko > -----Original Message----- > From: Whitner, Tom [mailto:[EMAIL PROTECTED] > Sent: 18 January 2005 17:17 > To: [email protected] > Subject: WMI Appender > > > I have been experimenting with WMI and log4net. I > noticed that work on the WMI Appender is postponed. "Because > of the way that a managed WMI schema must be registered with > the system (using assembly attributes) there seems little > scope for a generic appender for WMI. The immediate plan is > to look at generating a sample appender that does WMI." > > I have created a generic appender class that "Fires" > WMI Events and does not require registering as mentioned > previously. The WMI Events themselves must be published, but > they exist in client/consumer code not within log4net. > Essentially, this class looks at the original object that was > logged (loggingEvent.MessageObject) and using reflection, > determines if it is a WMI Instrumentation class. If it is, > it fires it. I have included the code below for review. Is > this a viable approach to providing WMI functionality to > log4net? I am concerned that my approach may violate > principles that I am not aware of. BTW, I am aware that > there are improvements that must be made such as caching and > exception handling. This was intended to demonstrate the concept. > > Thanks, > Tom Whitner > > /// <summary> > /// A log4net appender that fires WMI Events /// </summary> > public class WMIAppender : AppenderSkeleton { > /// <summary> > /// Default Constructor > /// </summary> > public WMIAppender() > { > } > > /// <summary> > /// "Appends" WMI events by firing them. > /// </summary> > /// <param name="loggingEvent">The logging event to > append.</param> > /// <remarks>Non-Wmi events will not be fired.</remarks> > protected override void Append(LoggingEvent loggingEvent) > { > if (IsWmiEvent(loggingEvent.MessageObject)) > { > > // TODO: Add exception handling in > case schema > // was not published. > > Instrumentation.Fire(loggingEvent.MessageObject); > } > } > > /// <summary> > /// Verifies that <see cref="Append(LoggingEvent)"/> > should occur. > /// </summary> > /// <returns></returns> > protected override bool PreAppendCheck() > { > // PreAppendCheck() should return false for > non-WMI event objects. > // However, if does not have access to the > loggingEvent. > // Therefore, the check must currently be > done in Append(). > return base.PreAppendCheck (); > } > > /// <summary> > /// Determine if the specified object is a WMI Event. > /// </summary> > /// <param name="o">The object to test.</param> > /// <returns></returns> > protected bool IsWmiEvent(object o) > { > // TODO: Lookup class in cache; return and > exit if found. > > // This attribute may only occur once. > > object[] attributes = > o.GetType().GetCustomAttributes(typeof(InstrumentationClassAtt > ribute), true); > > switch (attributes.Length) > { > case 0: > { > // no attribute present = non > wmi class > return false; > } > case 1: > { > bool isWmiEvent = false; > > // we have one attribute. > Now test for instumentation type. > // only events can be fired. > InstrumentationClassAttribute > ica = (InstrumentationClassAttribute)attributes[0]; > if (ica.InstrumentationType > == InstrumentationType.Event) > { > isWmiEvent = true; > } > > // TODO: Cache results for next time. > > return isWmiEvent; > } > default: > { > // by definition, this > attrbiute can only appear once. > throw new > ApplicationException("Multiple InstrumentationClassAttributes > attached."); > } > } > } > } > >
