WCF : Unable to have dynamic value for the Logging Application Blocks' Log File name

Topics: Logging Application Block
Apr 17, 2014 at 7:39 AM
I have integrated the Logging Application Block with the WCF application wherein I want to create the Log files. The WCF has a method which accepts "ID" parameter. I want to have the LogFile name with "EventLog_123.log" format, where 123 is the value of the ID received. For this purpose, I set the Environment variable as Environment.SetEnvironmentVariable("ID", strID); in my code. Web.config has the entry like "EventLog_%ID%.log"

The log file which is getting created is not getting appended with the ID value, it just creates the Log file with the name "EventLog_"

What is the correct place where this variable value should be set? Kindly suggest.

Thanks,

Ent lib ver 5 is used
Apr 20, 2014 at 7:52 PM
Enterprise Library does handle expansion of environment variables for file based listeners. However, variable expansion occurs during creation of the trace listener which occurs during block initialization so you cannot set an environment variable on every request.

Keep in mind that the trace listener is a singleton so there is only one trace listener instance for each trace listener defined. One way to do what you want using Enterprise Library would be to programmatically create a LogWriter pointing to the appropriate file:
    public static class MyLogWriterFactory
    {
        private static ConcurrentDictionary<string, LogWriter> logWriters =
            new ConcurrentDictionary<string, LogWriter>();

        public static LogWriter Create(string id)
        {
            return logWriters.GetOrAdd(id,
                (c) =>
                {
                    var builder = new ConfigurationSourceBuilder();

                    builder.ConfigureLogging()
                            .WithOptions
                                .DoNotRevertImpersonation()
                            .LogToCategoryNamed("General")
                                .WithOptions
                                .ToSourceLevels(SourceLevels.Information)
                                .SendTo.FlatFile("Trace File")
                                .FormatWith(new FormatterBuilder()
                                    .TextFormatterNamed("Text Formatter")
                                    .UsingTemplate("{message}    Timestamp: {timestamp}"))
                                    .ToFile(String.Format("EventLog_{0}.log", id));

                    var configSource = new DictionaryConfigurationSource();
                    builder.UpdateConfigurationWithReplace(configSource);

                    var factory = new LogWriterFactory(configSource);

                    return factory.Create();
                });
        }
    }

    class Program
    {
        static void Main(string[] args)
        {
            Do(123);
            Do(22);
        }
        static void Do(int id)
        {
            MyLogWriterFactory.Create(id.ToString()).Write("Test", "General");
        }
    }

In the above, a ConcurrentDictionary is used to keep a reference to the LogWriter based on the ID.

So that should address what you asking to do. However, here are some reasons not do it:
  • This approach will be relatively slow. It is expensive to configure and create a LogWriter.
  • This approach could consume a large amount of memory. There will be a LogWriter in memory for each value of ID that was sent to the service. If thousands of requests with different IDs are passed in this would result in many LogWriters in memory. This could be mitigated by disposing and removing the LogWriter at the end of the request but that will take a bit more cycles.
~~
Randy Levy
entlib.support@live.com
Enterprise Library support engineer
Support How-to
Apr 25, 2014 at 11:52 AM
Hi Randy,

Thanks a lot for your valuable reply.
With this code, will it append the log if the logFile exist already? If not, could you please tell me how to achieve the same?

Thanks,
Apr 25, 2014 at 1:42 PM
Yes, the code will keep a LogWriter per ID and append to any existing files.

~~
Randy Levy
entlib.support@live.com
Enterprise Library support engineer
Support How-to