Rolling file by a function

Topics: Logging Application Block
Oct 29, 2012 at 11:43 AM

Hi,

How do I get the the trace listener instance by a given category name?

Thanks.

Oct 31, 2012 at 12:58 AM

Do you mean the actual instance used internally to write?  If so, then the answer is yes.  The trace listeners are held internally so you can access the objects but you will have to cast the objects appropriately at runtime to extract the information.

For example with a FlatFileTraceListener you can access the trace listener for the category "General" using 

logWriter.TraceSources["General"].Listeners[0]

 (assuming the first configured trace listener is the one we are interested in).  But that will not get use the internal trace listener.  We will have to cast to a ReconfigurableTraceListenerWrapper to obtain the internal trace listener:

((Microsoft.Practices.EnterpriseLibrary.Logging.TraceListeners.ReconfigurableTraceListenerWrapper)logWriter.TraceSources["General"].Listeners[0]).InnerTraceListener

But even then if you want to get at specific FlatFileTraceListener data then you have to cast again:

var innerTraceListener = ((Microsoft.Practices.EnterpriseLibrary.Logging.TraceListeners.ReconfigurableTraceListenerWrapper)logWriter.TraceSources["General"].Listeners[0]).InnerTraceListener;
var flatFileTraceListener = innerTraceListener as FlatFileTraceListener;

Of course, that assumes that you know what trace listeners you will be dealing with.  In general, you would have to handle a variety of combinations.

At this point you are quite far down into the internals of Enterprise Library so I would question if you really need to be doing this.

--
Randy Levy
Enterprise Library support engineer
entlib.support@live.com 

Oct 31, 2012 at 9:23 AM

Hi,

I wanted to create the ability to roll the file by demand, not by a day or an hour...

So I thought if I had the trace listener that points on the file, I would somehow be able to roll the file.

In second thoughts, I think it is not so wise to do so...

Thanks.

 

Nov 1, 2012 at 4:56 AM

OK, I see what are you trying to do.  You can do this but like I said it's fairly tightly coupled to the internals of Enterprise Library.  Also, if you do go with this approach you will have to maintain your own synchronization code.  This is because Enterprise Library Logging is thread-safe but in order to roll we are bypassing the internal locking mechanisms so all logging operations will have to performed using your own synchronization.

LogWriter logWriter;
lock (locker)
{
    logWriter = EnterpriseLibraryContainer.Current.GetInstance<LogWriter>();
    logWriter.Write("Test", "General");
}

lock (locker)
{
    logWriter = EnterpriseLibraryContainer.Current.GetInstance<LogWriter>();
    var logSource = logWriter.TraceSources.Where(ts => ts.Key == "General").FirstOrDefault().Value;

    if (logSource != null)
    {
        // Get Listener
        var listener = logSource.Listeners.FirstOrDefault(l => l.Name == "Rolling Flat File Trace Listener");

        // Cast to get access to internal listener
        var reconfigurableListener = listener as ReconfigurableTraceListenerWrapper;

        if (listener != null)
        {
            // Get the rolling listener
            var rollingListener = reconfigurableListener.InnerTraceListener as RollingFlatFileTraceListener;

            if (rollingListener != null)
            {
                rollingListener.RollingHelper.PerformRoll(DateTime.Now);
            }
        }
    }
}

lock (locker)
{
    logWriter = EnterpriseLibraryContainer.Current.GetInstance<LogWriter>();
    logWriter.Write("Test 2", "General");
}

As a caveat, I haven't tested this for thread-safety (although it's extremely coarse grained so is probably OK at the expense of performance).

If you wanted to remove the tight coupling and synchronization issues you could implement your own RollingFlatFileTraceListener (you can grab an implementation off the Samples Page as a starting point) and provide a static method that will perform a roll as well as manage it's own synchronization (so the hassles aren't actually removed -- just abstracted :) ).  You'll also have to ensure the object is in a valid state to roll the file (e.g. an instance may not even be created).  Actually you may need to use a Multiton pattern because you could have an arbitrary number of RollingFlatFileTraceListeners created.  You may also have to manage removing listeners.
Then the code would look like:

var logWriter = EnterpriseLibraryContainer.Current.GetInstance<LogWriter>();
logWriter.Write("Test", "General");

var rollingInstance = MyRollingFlatFileTraceListenerDispenser.GetInstance("MyRollingFlatFileTraceListener");
if (rollingInstance != null)
{
    rollingInstance.PerformRoll();
}
logWriter.Write("Test", "General");

Which is probably closer to what you want.
The major downside is the custom work you have to do, the relative complexity, and having to know the configured name of the categories and trace listeners is also a bit of a code smell.
--
Randy Levy
Enterprise Library support engineer
entlib.support@live.com