Title: 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(InstrumentationClassAttribute), 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.");
                        }
                }
        }
}

Reply via email to