> 1. Introducing an appender that can fire WMI events creates > a dependency on the System.Management assembly. Further, > adding a standard WMI event class that can be fired requires > installation of the assembly (via InstallUtil.exe or MSI for > instance) as well as creates a dependency on the > System.Configuration.Install assembly.
Indeed, the WMI appender should not be packaged in the log4net assembly. Log4net config parser can load types from external assemblies using standard .net assembly qualified type names. > 2. What is the relationship between the standard and custom events? > Should custom events be derived from or aggregate a standard > event so that they will contain the standard logging > information? If a custom event does neither, then it would > likely not contain standard information like date/time, > thread id, application name, etc. Another alternative might > be to raise two events (custom and standard), but this would > likely be hard to correlate and understand from a monitoring > perspective. I was also thinking along these lines. The user creating the custom WMI object should have the choice. If they extend the base type that log4net knows about then the appender should add the standard logging data to the object before delivering it to WMI. If the user chooses not to extend the known base type then none of the standard logging data can be included in the object. Type extension or aggregation (identified by an interface) are both viable possibilities. I agree that raising two separate, but coincident, events would do more harm than good. > At this point, I think this would be best attempted as a > standard extension to log4net rather than trying to bake it > in. Do you have standard for how something like this should > be done? I would like to go ahead an prototype this a little further. Up to now we have tried to shoehorn as much functionality as possible into the main log4net assembly, with different builds for different platforms. This has led to some problems for applications that ship on multiple platforms. We need to evaluate the implications of splitting all the platform specific code into separate assemblies. This would give us a single portable core assembly, and a number of separate assemblies containing appenders. As a starting point I would suggest building a new assembly log4net.Appender.WmiAppender.dll containing the log4net.Appender.WmiAppender type. Nicko > > - Tom > > -----Original Message----- > From: Nicko Cadell [mailto:[EMAIL PROTECTED] > Sent: Thursday, January 20, 2005 9:14 AM > To: Log4NET Dev > Subject: RE: WMI Appender - More ramblings > > I should point out that I have very little experience with > using WMI to manage application reporting, especially in a > larger environment. > > If the user wants to log additional data then it is > reasonable to use an extension or for them to pass a custom > object as the message. > If you want to log a specific set of additional data via WMI > then it is reasonable to create a custom object with the data > and pass that to log4net. > > There are many situations where the user does not want to log > additional data, but just wants to publish it via WMI. In > this case I don't see why the calling app should need to know > about WMI or WMIing an object. Also there is a requirement to > WMI enable an existing application. For example, an > administrator may want application errors notified via WMI so > that IT staff may take appropriate action. > > In general appenders should make use of additional data if it > is supplied, but not rely on it, they should have a > reasonable default behaviour when that data is not available. > > For the WMI appender reasonable behaviour seems to be: > If the calling app passes in a custom object that can be > passed to WMI then this object should be fired directly. > If the message object is not compatible with WMI then the > appender should create some standard event that can be > published via WMI. > > This means that the calling app has fine control if they need > it, but in the general case it is possible to use WMI for > other types of event. > This is similar to the EventLogAppender which will publish > the event to the event log with or without the Event Id. > > Is that the right way to go? > > Nicko > > > -----Original Message----- > > From: Whitner, Tom [mailto:[EMAIL PROTECTED] > > Sent: 18 January 2005 21:40 > > To: Log4NET Dev > > Subject: RE: WMI Appender - More ramblings > > > > Yeah, this really is a challenge. Sooner or later > something needs to > > be aware of WMI. With respect to some of the questions you > raise, it > > is interesting to note that Microsoft themselves don't have a great > > solution either. They attempted to produce a somewhat standardized > > event schema with their EIF offering, but EIF is not really > > recommended any longer. In PAG's latest effort Enterprise Library, > > they take the approach of a single WMI Event class which > essentially > > mirrors log4net's LoggingEvent class in principle. Either > way, both > > the WMI Event producer and consumer must be aware of the WMI event > > schema. This probably means that you can't dynamically define WMI > > Events that are useful to anyone else. I think there is value in > > allowing different event classes to be fired. From a WMI Event > > consumer perspective, you'd probably want to receive as few > events as > > possible (filtering can be done via WMI infrastructure > based on event > > type) rather than receiving all events and then filtering based on > > event data. > > > > We are seeing a similar problem with the Event Id for the Windows > > Event log. The solutions that I have seen so far require > you to place > > an additional layer on top of log4net in order to pass data through > > it. > > Here again, I thought that passing a specialized object through > > log4net targeted at a particular appender might solve the > problem more > > elegantly. In either case, the client is aware that it > must pass an > > Event Id. The basic issue seems to be that certain > appenders provide > > functionality that is not represented in the basic logging > interface. > > > > The more I think about this, the more it seems reasonable for the > > client code to know about the extra information that it is > attempting > > to log. > > It is, in fact, the originator of the logging request. If a > > particular appender can not support a certain piece of > data, so be it. > > What would happen to any standard object if it were passed > to log4net. > > I assume that it would either call > > ToString() or an appropriate layout would be used. Either of these > > methods will work with WMI Event objects. In fact, I have used the > > ConsoleAppender and XmlLayout in testing the code I sent earlier. > > They log the WMI Event classes just fine. > > > > -----Original Message----- > > From: Nicko Cadell [mailto:[EMAIL PROTECTED] > > Sent: Tuesday, January 18, 2005 1:42 PM > > To: Log4NET Dev > > Subject: RE: WMI Appender > > > > 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."); > > > } > > > } > > > } > > > } > > > > > > > > > > > >
