Custom EventListener

Topics: Semantic Logging Application Block
Mar 8, 2013 at 3:47 AM
I would like to make a custom EventListener that writes to the console for simple debugging purposes. The EventListeners.ConsoleEventListener is a little too verbose for my current needs and I would like to compress it down to a single line. I am a bit confused about how to make use of the Message attribute so my payload arguments get formatted into the Message string. Do I need to parse the Message string myself or can I make use of String.Format or something similar?

Also I'm assuming that I need to add my own timestamp as the EventWrittenEventArgs doesn't seem to include one?

Many thanks.
Mar 8, 2013 at 1:08 PM
I think all that you need is a custom formatter. Actually, the default EventTextFormatter looks like it supports writing to a single line when the EventLevel of the logged Event is less than or equal to the value specified in the formatter's Detailed property. So as long as the EventSource does not have any entries with a Level = EventLevel.Critical you could just do something like this:
            var formatter = new EventTextFormatter() { Detailed = EventLevel.Critical };

            var consoleListener = new ConsoleEventListener(formatter);
I think it would be nice for RTM if it was possible to just toggle single line vs. multiline with a property instead of relying on the internal implementation.

Now if that is still too verbose you can create a formatter that implements IEventTextFormatter:
    /// <summary>
    /// A <see cref="IEventTextFormatter"/> implementation that writes out formatted text on a single line.
    /// </summary>
    /// <remarks>This class is not thread-safe.</remarks>
    public class SingleLineEventTextFormatter : IEventTextFormatter
    {
        private string dateTimeFormat;

        /// <summary>
        /// Initializes a new instance of the <see cref="EventTextFormatter" /> class.
        /// </summary>
        public SingleLineEventTextFormatter() : base()
        {
        }

        /// <summary>
        /// Gets or sets the date time format used for timestamp value.
        /// </summary>
        /// <value>The date time format.</value>
        public string DateTimeFormat
        {
            get
            {
                return this.dateTimeFormat;
            }

            set
            {
                ValidDateTimeFormat(value, "DateTimeFormat");
                this.dateTimeFormat = value;
            }
        }

        /// <summary>
        /// Validate the date time format.
        /// </summary>
        /// <param name="format">The format.</param>
        /// <param name="argumentName">Name of the argument.</param>
        public static void ValidDateTimeFormat(string format, string argumentName)
        {
            try
            {
                DateTime.Now.ToString(format);
            }
            catch (FormatException e)
            {
                throw new ArgumentException(argumentName, "The date time format is invalid.", e);
            }
        }

        /// <summary>
        /// Writes the event.
        /// </summary>
        /// <param name="eventEntry">The <see cref="EventEntry" /> instance containing the event data.</param>
        /// <param name="writer">The writer.</param>
        void IEventTextFormatter.WriteEvent(EventEntry eventEntry, TextWriter writer)
        {
                writer.WriteLine(
                    "EventId : {0}, Level : {1}, Message : {2}, Payload: {3}, EventName : {4}, Timestamp : {5}",
                    eventEntry.EventId,
                    eventEntry.Schema.Level,
                    eventEntry.FormattedMessage,
                    FormatPayload(eventEntry),
                    eventEntry.Schema.EventName,
                    eventEntry.GetFormattedTimestamp(this.DateTimeFormat));
        }

        private static string FormatPayload(EventEntry entry)
        {
            var eventSchema = entry.Schema;
            var sb = new StringBuilder();

            for (int i = 0; i < entry.Payload.Count; i++)
            {
                try
                {
                    sb.AppendFormat("[{0} : {1}] ", eventSchema.Payload[i], entry.Payload[i]);
                }
                catch (Exception e)
                {
                    // TODO: Log a message but don't throw (unless you want logging to fail)
                }
            }

            return sb.ToString();
        }
    }
~~
Randy Levy
entlib.support@live.com
Enterprise Library support engineer
Support How-to
Mar 9, 2013 at 9:51 AM
Hi Randy,

Your suggestions worked perfectly. I have opted for writing my own TextFormatter.

Many thanks for your assistance.

Peter