Geeks With Blogs

News


Alois Kraus blog

The following code sample shows how to configure the Enterprise Library Logging Block programatically without the help of ObjectBuilder. To create a working LogWriter instance with your own settings you need to create the following objects:
  • A Formatter which contains a valid message template
  • A LogSource which has a name (Category) contains a colleciton of Listeners (Sinks) along with the Formatter.
  • A collection LogSources with the category as key and the LogSource object as value
To use this logger you can call

  ConfigLessLogger.Error("Hello world of config by code.");
The error is written to the Windows Event Application Event Log:

Timestamp: 16.02.2006 23:33:41
Message: Hello World of dynamic object creation
Category: Errors

I have improved my original ConfigLessLogger sample with the very helpful comments from David Hayden who blogs about the Enterprise Library (mainly IConfigurationSource and Logging Block).

ConfigLessLoger.cs

using System;

using System.Collections.Generic;

using Microsoft.Practices.EnterpriseLibrary.Logging;

using Microsoft.Practices.EnterpriseLibrary.Common.Configuration;

using Microsoft.Practices.EnterpriseLibrary.Logging.Filters;

using Microsoft.Practices.EnterpriseLibrary.Logging.Formatters;

using Microsoft.Practices.EnterpriseLibrary.Logging.TraceListeners;

 

namespace MyApp.Logging

{

    public class ConfigLessLogger

    {

        private static LogWriter writer;              // Instance is created in static ctor which is thread safe

        const string EventLogSource = "Code Source"// Event Log Source name

        const string ErrorCategory = "Errors";        // We have only one message category: Errors

 

        static ConfigLessLogger()

        {

            writer = CreateLogWriterFromCode();  // static ctor is thread safe according to ECMA standard section 9.5.3

        }

 

        static private LogWriter CreateLogWriterFromCode()

        {

            // This is our message template for any Sink you add below in our case the Windows Event Log

            TextFormatter formatter = new TextFormatter("Timestamp: {timestamp}{newline}" +

                                                        "Message: {message}{newline}"    +

                                                        "Category: {category}{newline}"    );

 

            LogSource emptyTraceSource = new LogSource("none");

 

            LogSource errorsTraceSource = new LogSource(ErrorCategory, System.Diagnostics.SourceLevels.All);

            // Create for all Errors a Listener which writes the messages to the Windows Event Log

            // with the Event Log Source Property "Code Source". The message format is specified by

            // the TextFormatter which is in our case the template above.

            errorsTraceSource.Listeners.Add(new FormattedEventLogTraceListener(EventLogSource, formatter));

 

            IDictionary<string, LogSource> traceSources = new Dictionary<string, LogSource>();

            // Add to Category "Error" our EventLog Listener with the corresponding category in it.

            traceSources.Add(errorsTraceSource.Name, errorsTraceSource);

 

            return new LogWriter(new ILogFilter[0], // ICollection<ILogFilter> filters

                              traceSources,        // IDictionary<string, LogSource> traceSources

                              emptyTraceSource,    // LogSource allEventsTraceSource

                              emptyTraceSource,    // LogSource notProcessedTraceSource

                              errorsTraceSource,    // LogSource errorsTraceSource

                              ErrorCategory,        // string defaultCategory

                              false,                // bool tracingEnabled

                              true);                // bool logWarningsWhenNoCategoriesMatch

        }

 

        /// <summary>

        /// Write an Error message to the Windows Event Log with an message template specifed in code

        /// </summary>

        /// <param name="message">Error message to log</param>

        public static void Error(string message)

        {

            LogEntry ent = new LogEntry();

            ent.Categories.Add(ErrorCategory);  // To use another category use traceSources.Add("OtherCat", Listener);

            ent.Message = message;

            ent.Severity = System.Diagnostics.TraceEventType.Error;

            writer.Write(ent);

        }

    }

}


Posted on Thursday, February 16, 2006 9:39 PM Enterprise Library | Back to top


Comments on this post: Programatic Configuraton - Enterprise Library (v2.0) Logging Block

# re: Programatic Configuraton - Enterprise Library (v2.0) Logging Block
Requesting Gravatar...
Thanks so much for this great example!

I have a presentation on Enterprise Library 2.0 coming up and was in the process of figuring this out on my own.
Left by David Hayden on Feb 17, 2006 6:14 PM

# re: Programatic Configuraton - Enterprise Library (v2.0) Logging Block
Requesting Gravatar...
Thanks David. I have looked at your blog. Looks very nice. Perhaps I find my sample there again ;-)
Left by Alois Kraus on Feb 17, 2006 8:51 PM

# re: Programatic Configuraton - Enterprise Library (v2.0) Logging Block
Requesting Gravatar...
Alois,

You will :) A version I just finished writing after 2+ hours of struggling to understand what indeed is happening in your code :)

I didn't realize that in this statement:

traceSources.Add(errorsTraceSource.Name, errorsTraceSource);

the first parameter is actually a category name and designates that all messages sent with that category go to the specified LogSource. The way you have it coded made me think it was the name of the LogSource, since they are one and the same.

So, I can easily add another category of "Debug" and have it go to the same LogSource:

traceSources.Add("Debug", errorsTraceSource);

Your example finally made me understand the inner-workings of the Logging Application Block.


The only other thing I did in my code for kicks was associated with threading.

I put my code, which is similar to your code in CreateLogWriterFromCode() method, in a static constructor and removed the Writer property and CreateLogWriterFromCode() method altogether. It looks something like this:

public static class MyLogger
{
static LogWriter _writer;

static MyLogger()
{
// Create _writer here...
}

public static void Write(string message)
{
Write(message, "Error");
}

public static void Write(string message, string category)
{
LogEntry entry = new LogEntry();

entry.Categories.Add(category);
entry.Message = message;

_writer.Write(entry);
}
}


Can you think of any negative drawback about using the static constructor approach versus your approach?

Once again, thanks for the artice and congratulations on being awarded a P&P Champion. Well deserved I am sure.

Regards,

Dave
Left by David Hayden on Feb 17, 2006 10:43 PM

# re: Programatic Configuraton - Enterprise Library (v2.0) Logging Block
Requesting Gravatar...
Thanks David. I have looked into the some mailing lists to check if static ctors are thread safe. According to the ECMA standard section 9.5.3
http://jilc.sourceforge.net/ecma_p2_cil.shtml#_Toc524940486 the static ctor is called only once for the type before any other method or property is accessed. Your approach should work well and looks easier to me. There is always room for improvement ;-)

Yours,
Alois Kraus
Left by Alois Kraus on Feb 18, 2006 12:55 PM

# re: Programatic Configuraton - Enterprise Library (v2.0) Logging Block
Requesting Gravatar...
but how can the static constructor work correctly incase I have many trace Listeners ?

Left by Mohamed El-Zahaby on Feb 21, 2006 7:21 AM

# re: Programatic Configuraton - Enterprise Library (v2.0) Logging Block
Requesting Gravatar...
Hi Mohammed,
could you provide more info what race condition deadlock you expect when I create one or many listeners in the static ctor?

Yours,
Alois Kraus
Left by Alois Kraus on Feb 21, 2006 11:59 AM

# re: Programatic Configuraton - Enterprise Library (v2.0) Logging Block
Requesting Gravatar...
Incase if you I have a parameter to decide which logging target will be used ; file or windows event

this is the way I implemeneted it :
I added a new switch case in the write function

public static void Write(string message)
{
errorsTraceSource = new LogSource("Errors", SourceLevels.All);

LogEntry entry = new LogEntry();
entry.Categories.Add("Errors");
entry.Message = message;

switch (oLogTarget)
{
#region Logging into file
// Logging into FILE
case LogTarget.File:
try
{
errorsTraceSource.Listeners.Add(new FormattedTextWriterTraceListener(FileName, formatter));
LogSource emptyTraceSource = new LogSource("none");
IDictionary<string, LogSource> traceSources = new Dictionary<string, LogSource>();
traceSources.Add(errorsTraceSource.Name, errorsTraceSource);
writer = new LogWriter(new ILogFilter[0], // ICollection filters,
traceSources, // IDictionary traceSources,
emptyTraceSource, // LogSource allEventsTraceSource,
emptyTraceSource, // LogSource notProcessedTraceSource,
errorsTraceSource, // LogSource errorsTraceSource,
"Errors", // string defaultCategory,
false, // bool tracingEnabled,
true); // bool logWarningsWhenNoCategoriesMatch)
}
catch { }
break;
case LogTarget.EventViewer:
try
{
errorsTraceSource.Listeners.Add(new FormattedEventLogTraceListener(Source, formatter));
LogSource emptyTraceSource = new LogSource("none");
IDictionary<string, LogSource> traceSources = new Dictionary<string, LogSource>();
traceSources.Add(errorsTraceSource.Name, errorsTraceSource);
writer = new LogWriter(new ILogFilter[0], // ICollection filters,
traceSources, // IDictionary traceSources,
emptyTraceSource, // LogSource allEventsTraceSource,
emptyTraceSource, // LogSource notProcessedTraceSource,
errorsTraceSource, // LogSource errorsTraceSource,
"Errors", // string defaultCategory,
false, // bool tracingEnabled,
true); // bool logWarningsWhenNoCategoriesMatch)

entry.Severity = System.Diagnostics.TraceEventType.Error;
}
catch
{ }
break;
#endregion
}


writer.Write(entry);
}
Left by Mohamed El-Zahaby on Feb 21, 2006 12:23 PM

# re: Programatic Configuraton - Enterprise Library (v2.0) Logging Block
Requesting Gravatar...
Hmm,
I do not recommend to do it this way you have shown here. You should access the LogWriter instance which configuration determines via Category where the information is logged (you will need only one LogWriter instance not many). Your new parameter defeats the intention of the Logging block to make the log destination configurable. You can configure an arbitrary amount of log categories which contain one or many the Listeners. Your sample will result in bad performance and run time (locking) errors because the LogWriter object created in the previous log call will very likely not be disposed yet and hold files, databases, etc. open. If you need to hard code everything I am not sure if Entlib is the right choice for you. The programatic configuration was meant to supply a builtin default configuration if no external configuration is present. If you do not want to configure anything I would not use Entlib at all.

Yours,
Alois Kraus
Left by Alois Kraus on Feb 21, 2006 12:47 PM

# re: Programatic Configuraton - Enterprise Library (v2.0) Logging Block
Requesting Gravatar...
yes you are completely true. I will fix my code.
Left by Mohamed El-Zahaby on Feb 21, 2006 1:40 PM

# re: Programatic Configuraton - Enterprise Library (v2.0) Logging Block
Requesting Gravatar...
Thanks very much
I refernced you in this article
http://www.codeproject.com/useritems/Logging_Plug-in_Manager.asp
Left by Mohamed ElZahaby on Mar 21, 2006 3:13 AM

# re: Programatic Configuraton - Enterprise Library (v2.0) Logging Block
Requesting Gravatar...
Hi,
I am trying to log the errors in database programatically, can anyone help me out with that.

Thanks,
Rahul.
Left by rahul on Apr 13, 2006 5:49 AM

# Enterprise Library (v2.0) Logging Block
Requesting Gravatar...
Greetings - I am working on a C#.NET console app. I am using EL 2.0, and using the config tool, I cannot set it up to create and write to a new custom Windows event log. Writing to the "Application" event log works fine. When I execute, I am getting an event log entry that says my .exe is not listed as a source, when indeed it is. Has anyone come across this and found a solution - thank you.
Left by Brian on Jun 30, 2006 2:30 PM

# re: Programatic Configuraton - Enterprise Library (v2.0) Logging Block
Requesting Gravatar...
Hi Brian,

you should create the Event log sources via the EventLog.CreateEventSource API by yourself during the installation of your software package since you cannot be sure to have the required privileges to do this when you run under a low privileged account such as the aspnet user when you host then Enteprise Library inside IIS.

Yours,
Alois Kraus
Left by Alois Kraus on Jun 30, 2006 7:38 PM

# re: Programatic Configuraton - Enterprise Library (v2.0) Logging Block
Requesting Gravatar...
Hi - I am logging fine, but I have trouble with email sending. I want to send logs by mail and I can't find any documentation or examples about it. I have configured an EmailTraceListener but can't figure out how to use this configuration with the EmailMessage class. Do anyone has links of code samples, tutorials or knows how to do this? ... thanks
Left by Aaron on Aug 02, 2006 4:40 PM

# re: Programatic Configuraton - Enterprise Library (v2.0) Logging Block
Requesting Gravatar...
Hi,

This may be a newbie question, but how would I read the config parts of the app.config that refer to logging/application blocks? In the manner that you would use an appsettings reader to read the <appSettings> section of the config file?

What I want to do, is use the logging and exception blocks, but I also want to read bits of the config in other sections of my code.

I was looking for something like appblockConfig Reader.GetPolicySection.getkeyvalue(strkey) or somesuch.

Any thoughts?
Left by Will on Sep 28, 2006 1:12 PM

# re: Programatic Configuraton - Enterprise Library (v2.0) Logging Block
Requesting Gravatar...
In response to Aaron ...

Look at Davids blog.. http://davidhayden.com/blog/dave/archive/2006/02/15/2802.aspx

I used this, but where he mentions flat files - you set up an email trace listener. Use the config tool that ships with the framework!
Left by Will on Sep 28, 2006 1:14 PM

# re: Programatic Configuraton - Enterprise Library (v2.0) Logging Block
Requesting Gravatar...
Hello,

is it possible to configure the Excepetion Handling Block programmatically as well? Maybe in additon with your example above?

Greetings,
Michael
Left by Michael on Nov 23, 2006 11:38 PM

# re: Programatic Configuraton - Enterprise Library (v2.0) Logging Block
Requesting Gravatar...
Hi Michael,

sort of:
http://www.agileprogrammer.com/oneagilecoder/archive/2006/02/20/11628.aspx

But you have to modify the source of the Exception handling block to make it work. And it is quite complicated to set up as you can see.

Yours,
Alois
Left by Alois Kraus on Nov 23, 2006 11:59 PM

# Question on Flat File Trace Listener
Requesting Gravatar...
Have a query regarding Flat File Trace Listener.
To log data,i am currently picking up file name from the (App.config)config file.
is there any way that i can change the name of
the config @ runtime.
any pointers would be great.
Left by raja on Feb 12, 2007 8:46 AM

# re: Programatic Configuraton - Enterprise Library (v2.0) Logging Block
Requesting Gravatar...
Thanks a lot for this wonderful article.

Is there any way we can configure the exception hadling dynamically?
i don't want to put any of my configurations on web.config but on database.

Plz help
Left by Ayush on Sep 16, 2007 9:56 PM

# re: Programatic Configuraton - Enterprise Library (v2.0) Logging Block
Requesting Gravatar...
It is possible to use the SqlConfigurationSource which is part of Entlib 3.1 and 2.0 in the QuickStarts folder.

Yours,
Alois Kraus
Left by Alois Kraus on Sep 17, 2007 10:56 AM

# re: Programatic Configuraton - Enterprise Library (v2.0) Logging Block
Requesting Gravatar...
Hi Alois,

The code is works great but it logs the message into the event log as information(information icon seen in windows event log), what should i do to make it log the messages as errors(with the red error icon in the event log)?

Left by pushpendra on Oct 28, 2007 1:26 AM

# re: Programatic Configuraton - Enterprise Library (v2.0) Logging Block
Requesting Gravatar...
Is it possible to have multiple TextFormatters in this example that you could then select the format from based on a parameter or condition?
Left by Michael Richards on Nov 14, 2007 2:40 AM

# re: Programatic Configuraton - Enterprise Library (v2.0) Logging Block
Requesting Gravatar...
Hi,
I could log the errors using flat file & email trace listneres programatically.

How can i log the errors in database programatically, can anyone help me out with that.

Thanks,
Kaushal.
Left by Kaushal patel on Nov 03, 2008 8:16 PM

# re: Programatic Configuraton - Enterprise Library (v2.0) Logging Block
Requesting Gravatar...
//Create TextFormatrer with diffrent Tokens

string template="Timestamp: {timestamp}{newline}" +
"Message: {message}{newline} " +
"Category: {category}{newline}" +
"Priority: {priority}{newline}" +
"EventId: {eventid}{newline}" +
"Severity: {severity}{newline}" +
"Title:{title}{newline}" +
"Machine: {machine}{newline}" +
"Application Domain: {appDomain}{newline}" +
"Process Id: {processId}{newline}" +
"Process Name: {processName}{newline}" +
"Win32 Thread Id: {win32ThreadId}{newline}" +
"Thread Name: {threadName}{newline}";



TextFormatter formatter = new TextFormatter(template);

//Create DatabaseTraceListener using TextFormatter created above.
string strConn - "...";
SqlDatabase sqlDB = new SqlDatabase(strConn);
FormattedDatabaseTraceListener databaseTraceListener = new FormattedDatabaseTraceListener(sqlDB, "WriteLog", "AddCategory", formatter);



//Collection of TraceListeners
LogSource errorsTraceSource = new LogSource("ErrorsTraceSource", SourceLevels.All);
errorsTraceSource.Listeners.Add(databaseTraceListener);


// Assigning a non-existant LogSource
// for Logging Application Block
// Used to say "don't log".
LogSource emptyTraceSource = new LogSource("Empty");


//Below will log all messages with a category of "Error" or "Debug" to all TraceListeners in errorsTraceSource.
IDictionary<string, LogSource> traceSources = new Dictionary<string, LogSource>();
traceSources.Add("Error", errorsTraceSource);
traceSources.Add("Debug", errorsTraceSource);



LogEntry logEntry = new LogEntry();
logEntry.EventId = 100;
logEntry.Priority = 2;
logEntry.Message = "Informational message generated using Logging Application Block.";
logEntry.Categories.Add("Error");
logEntry.Categories.Add("Debug");
logEntry.Categories.Add("Trace");
logEntry.Categories.Add("UI Events");
logEntry.TimeStamp = DateTime.Now;
logEntry.Severity = TraceEventType.Error;


LogWriter writer = new LogWriter(new ILogFilter[0], // ICollection<ILogFilter> filters
traceSources, // IDictionary<string, LogSource> traceSources
emptyTraceSource, // LogSource allEventsTraceSource
emptyTraceSource, // LogSource notProcessedTraceSource
errorsTraceSource, // LogSource errorsTraceSource
ErrorCategory, // string defaultCategory
false, // bool tracingEnabled
true); // bool logWarningsWhenNoCategoriesMatch


writer.Write(logEntry);
writer.Dispose();


Cheers,
Kaushal
Left by Kaushal on Nov 04, 2008 7:11 PM

# re: Programatic Configuraton - Enterprise Library (v2.0) Logging Block
Requesting Gravatar...
Thank you! I've been looking for a good example (database programatically). (btw I was using entlib 4.1 and it worked perfectly)
Left by Brandon on Jul 10, 2009 1:25 AM

# re: Programatic Configuraton - Enterprise Library (v2.0) Logging Block
Requesting Gravatar...
Hello Alois,

Thanks for the interesting blog. I had a question in the TextFormatter you have the following pattern:

TextFormatter formatter = new TextFormatter("Timestamp: {timestamp}{newline}" +
"Message: {message}{newline}" +
"Category: {category}{newline}" );

Is there a way where I can show the timestamp in the following format dd/mm/yyyy hh:mm:ss.fff

as i am using the log file for both debug and error. and for debug want to find out how long did it take to process each request.

Any help would be highly appreciated.

Cheers,

Manthan
Left by Manthan on Nov 26, 2009 9:11 PM

# re: Programatic Configuraton - Enterprise Library (v2.0) Logging Block
Requesting Gravatar...
Hi Manthan,

sure you can do this. Simply type: {timestamp(dd/mm/yyy hh:mm:ss.fff)} into your text template to use the formatting options of DateTime.ToString.

http://www.geekzilla.co.uk/View00FF7904-B510-468C-A2C8-F859AA20581F.htm

Yours,
Alois Kraus
Left by Alois Kraus on Nov 29, 2009 9:46 AM

# re: Programatic Configuraton - Enterprise Library (v2.0) Logging Block
Requesting Gravatar...
Hi David,
I am using Ent Lib 5.0 and IBM DB2 database. I want to use the Logging Application Block to log to the IBM DB2 Database. Could you please provide me a sample code which I can use to do that. I am fine with both Configuration Based Code or Programatic one as shown in above examples.
Left by Rahul on Mar 28, 2011 2:13 AM

# re: Programatic Configuraton - Enterprise Library (v2.0) Logging Block
Requesting Gravatar...
хочу видеоо
Left by Dasha on Aug 19, 2011 7:09 AM

# re: Programatic Configuraton - Enterprise Library (v2.0) Logging Block
Requesting Gravatar...
Hi Alois,
I noticed you mentioned in Erwyn van der Meer Rolling File Trace Listener Extension that you implemented an extension to his code to use the . ProcessID Expansion to support multi process logging. I have been trying to figure out what is required in order to do this. Is this an extension that you can share with me. I need to be able to log multiple processes and the current Rolling File Trace Listener provided by Enterprise Library 5.0 does not provide this capability. Your help would be greatly appreciated.
Left by Linh on Jun 26, 2012 5:01 PM

# re: Programatic Configuraton - Enterprise Library (v2.0) Logging Block
Requesting Gravatar...
Hi Linh,
sorry but that was something I did for my day work. This is not something I can publish.
Left by Alois Kraus on Jun 29, 2012 6:00 PM

Your comment:
 (will show your gravatar)
 


Copyright © Alois Kraus | Powered by: GeeksWithBlogs.net | Join free