Chui Tey
Chui Tey

Reputation: 5554

EnterpriseLibrary CustomTraceListener not respecting TextFormatter

I've a CustomTraceListener that logs to a ring buffer:

namespace Sample
{
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using Cognoware.Collections.Generic;
    using Microsoft.Practices.EnterpriseLibrary.Common.Configuration;
    using Microsoft.Practices.EnterpriseLibrary.Logging.Configuration;
    using Microsoft.Practices.EnterpriseLibrary.Logging.TraceListeners;

    [ConfigurationElementType(typeof(CustomTraceListenerData))]
    public class CircularTraceListener: CustomTraceListener
    {
        private static RingBuffer<string> _ringBuffer = new RingBuffer<string>(200);
        private string tmp = String.Empty;
        public override void Write(string message)
        {
            tmp += message;
        }

        public override void WriteLine(string message)
        {
            _ringBuffer.Add(tmp + message);
            tmp = String.Empty;
        }

        public IEnumerable<string> Messages
        {
            get
            {
                return _ringBuffer.AsEnumerable<string>();
            }
        }
    }
}

And it generally works, however I couldn't configure it to use a custom Text Format. In the configuration below I configured two trace listeners, one to a Flat File, the other to my custom listener. The former logs correctly using the "Brief formatter", while the latter fails and uses the default format. Why?

<loggingConfiguration name="" tracingEnabled="true" defaultCategory="General">
    <listeners>
        <add listenerDataType="Microsoft.Practices.EnterpriseLibrary.Logging.Configuration.CustomTraceListenerData, Microsoft.Practices.EnterpriseLibrary.Logging, Culture=neutral, PublicKeyToken=31bf3856ad364e35"
            type="Sample.CircularTraceListener, CircularTraceListener, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null"
            name="CircularTraceListener" formatter="Brief Formatter" />
        <add name="Flat File Trace Listener" type="Microsoft.Practices.EnterpriseLibrary.Logging.TraceListeners.FlatFileTraceListener, Microsoft.Practices.EnterpriseLibrary.Logging, Version=5.0.414.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"
            listenerDataType="Microsoft.Practices.EnterpriseLibrary.Logging.Configuration.FlatFileTraceListenerData, Microsoft.Practices.EnterpriseLibrary.Logging, Version=5.0.414.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"
            fileName="trace.log" formatter="Brief Formatter" /> 
    </listeners>
    <formatters>
        <add type="Microsoft.Practices.EnterpriseLibrary.Logging.Formatters.TextFormatter, Microsoft.Practices.EnterpriseLibrary.Logging, Culture=neutral, PublicKeyToken=31bf3856ad364e35"
            template="{timestamp}  {message} {title} {dictionary({key} - {value}{newline})}"
            name="Brief Formatter" />
    </formatters>
    <categorySources>
        <add switchValue="All" name="General">
            <listeners>
                <add name="CircularTraceListener" />
                <add name="Flat File Trace Listener" />
            </listeners>
        </add>
    </categorySources>
</loggingConfiguration>

Upvotes: 0

Views: 1595

Answers (2)

Chui Tey
Chui Tey

Reputation: 5554

Chris Tavares is correct. The solution is as follows:

  1. Override the TraceData() method,
  2. obtain an instance of the formatter
  3. call formatter.Format,
  4. pass it to WriteLine()

Here's a sample:

namespace Sample1
{
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using Cognoware.Collections.Generic;
    using Microsoft.Practices.EnterpriseLibrary.Common.Configuration;
    using Microsoft.Practices.EnterpriseLibrary.Logging.Configuration;
    using Microsoft.Practices.EnterpriseLibrary.Logging.TraceListeners;
    using System.Diagnostics;
    using Microsoft.Practices.EnterpriseLibrary.Logging;

    [ConfigurationElementType(typeof(CustomTraceListenerData))]
    public class CircularTraceListener: CustomTraceListener
    {
        private string tmp = String.Empty;
        public override void Write(string message)
        {
            tmp += message;
        }

        public override void WriteLine(string message)
        {
            tmp += message;
        }

        public override void TraceData(TraceEventCache eventCache, string source, TraceEventType eventType, int id, object data)
        {
            if ((this.Filter == null) || this.Filter.ShouldTrace(eventCache, source, eventType, id, null, null, data, null))
            {
                if (data is LogEntry)
                {
                    if (this.Formatter != null)
                    {
                        WriteLine(this.Formatter.Format(data as LogEntry));
                    }
                    else
                    {
                        base.TraceData(eventCache, source, eventType, id, data);
                    }
                }
                else
                {
                    base.TraceData(eventCache, source, eventType, id, data);
                }
            }
        }
    }
}

Upvotes: 3

Chris Tavares
Chris Tavares

Reputation: 30401

You don't get the formatters for free - you'll need to write your trace listener so that it gets an instance of the formatter and actually calls it.

Upvotes: 2

Related Questions