SIGN UP MEMBER LOGIN:    
ARTICLE

Extending Logging Functionality From Enterprise Library

Posted by Wei Chen Articles | Articles C# April 17, 2009
The Microsfot Enterprise Library provide us a collection of reusable software components, so software developers can take advantage of them to put them into enterprise use. Now I will share my personal experiences with my friends of how to extend current enterprise library functionality and improve the performance of enterprise applications.
Reader Level:


Introduction:
The Microsfot Enterprise Library provide us a collection of reusable software components, so software developers can take advantage of them to put them into enterprise use. Now I will share my personal experiences with my friends of how to extend current enterprise library functionality and improve the performance of enterprise applications.
Context:
We currently have a project which is intended to create a data repository cache for reference data and the requirement from the customer is that we need to log everything the user does. Currently, our company still uses enterprise lib 2.0 due to some security reasons. It is enough to fulfill the log function using a text formatter but that causes poor readability.
Let's start:
Okay, first, we need to code our own xmlformatter which must extend from LogFormatter:

[ConfigurationElementType(typeof(CustomFormatterData))]

    public class LongXmlFormatter : LogFormatter

    {

        private NameValueCollection Attributes = null;

        public LongXmlFormatter( NameValueCollection attributes )

        {

            this.Attributes = attributes;

        }

        public override string Format(LogEntry log)

        {          

            using (StringWriter sw = new StringWriterWithEncoding(new StringBuilder(), Encoding.UTF8))  //reader have to enforce their own encoding style in order to correnctly present them. 

            {

                XmlTextWriter w = new XmlTextWriter(sw);

               

                w.Formatting = Formatting.Indented;

                w.Indentation = 2;

 

                w.WriteStartDocument(true);              

                w.WriteStartElement("LogEntry");

            

                w.WriteElementString("Timestamp",  log.TimeStampString);

                w.WriteElementString("Message", log.Message);

                w.WriteElementString("Category", log.CategoriesStrings[0].ToString());

                w.WriteElementString( "Priority", log.Priority.ToString( ) );

                w.WriteElementString( "EventId", log.EventId.ToString( CultureInfo.InvariantCulture ) );

                w.WriteElementString( "Severity", log.Severity.ToString( ) );

                w.WriteElementString( "Title", log.Title );

                w.WriteElementString( "Machine", log.MachineName );

                w.WriteElementString( "AppDomain", log.AppDomainName );

                w.WriteElementString( "ProcessId", log.ProcessId );

                w.WriteElementString( "ProcessName", log.ProcessName );

                w.WriteElementString( "Win32ThreadId", log.Win32ThreadId );

                w.WriteElementString( "ThreadName", log.ManagedThreadName );

 

                w.WriteEndElement();

                w.WriteEndDocument();              

                return sw.ToString().Substring(55);

            }

        }
}
And in log config file, we defined providers that provide users 3 different formatters, so that they can flexibly pick up the formatter they want through the entprise config GUI.
1.gif

2.gif

And formatters section in config file would be like below:

<formatters>

      <add type="MyAssembly.Logging.ShortXmlFormatter, MyAssembly, Version=1.0.0.0, Culture=neutral, PublicKeyToken=1c35d9e2a9c27e83"

        name="Xml Short Formatter" />

      <add template="Timestamp: {timestamp}&#xD;&#xA;Message: {message}&#xD;&#xA;Category: {category}&#xD;&#xA;Priority: {priority}&#xD;&#xA;EventId: {eventid}&#xD;&#xA;Severity: {severity}&#xD;&#xA;Title:{title}&#xD;&#xA;Machine: {machine}&#xD;&#xA;Application Domain: {appDomain}&#xD;&#xA;Process Id: {processId}&#xD;&#xA;Process Name: {processName}&#xD;&#xA;Win32 Thread Id: {win32ThreadId}&#xD;&#xA;Thread Name: {threadName}&#xD;&#xA;Extended Properties: {dictionary({key} - {value}&#xD;&#xA;)}"

        type=" MyAssembly.Formatters.TextFormatter, Microsoft.Practices.EnterpriseLibrary.Logging, Version=2.0.0.0, Culture=neutral, PublicKeyToken=7fa4cc4c62ff1809"

        name="Text Formatter" />

      <add prefix="x" namespace=" MyAssembly" type=" MyAssembly.LongXmlFormatter, MyAssembly, Version=1.0.0.0, Culture=neutral, PublicKeyToken=1c35d9e2a9c27e83"

        name="Xml Formatter" />
</formatters>
Through above code, we can create correct XML layout but presenting as text formatter like below:

<LogEntry>

  <Timestamp>23/02/2009 2:03:35 PM</Timestamp>

  <Message>project initialization starting...</Message>

  <Category>Information</Category>

  <Priority>-1</Priority>

  <EventId>1</EventId>

  <Severity>Information</Severity>

  <Title />

  <Machine>Asset</Machine>

  <AppDomain>UTA_6657793a-1f3a-40e8-86f3-5996dcd2cea2</AppDomain>

  <ProcessId>14796</ProcessId>

  <ProcessName>C:\Program Files\Microsoft Visual Studio 9.0\Common7\IDE\vstesthost.exe</ProcessName>

  <Win32ThreadId>4360</Win32ThreadId>

  <ThreadName>Agent: adapter run thread for test 'ApplyMapFilterTest' with id 'df8ee337-9d6d-472a-93f5-949a5409ffa9'</ThreadName>
</LogEntry>
Now the question is how we can present it as XML format and show it in browser like IE. Technically, browser can only open xml file that follow the scheme strictly. We can see the drawback of above format that does not have root node element, so IE can not analyse and present them correctly. However, we can not add the root node element in our xmlFormatter class that would cause the duplicate root element each time when you append new log event. Therefore, this is not the right solution.
Then, xslt would come to the rescue. We define below xml tranforming file as xmlLogTransforms.xslt:

<?xml version="1.0" encoding="UTF-8" ?>

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

    <xsl:template match="/">

        <html>

            <head>

                <Title>My Log File</Title>

                <style>

                    body

                    {

                        font-family: any font you want;

                        font-size: 10pt;

                        color: #001;

                        margin: 0px 6px;

                        padding: 0px;

                        cursor: default;

                    }

                    .LineItem

                    {

                        cursor: pointer;

                    }

                    .LineItem:hover

                    {

                        color: #418;

                    }

                    .EntryDetails

                    {

                        margin: 4px 18px 12px 218px;

                    }

                    .ErrorStackHeader

                    {

                        cursor: pointer;

                    }

                    .ErrorStack

                    {

                        font-family: Lucida Console;

                        font-size: 8pt;

                        color: #f00;

                        margin: 8px -8px 8px 18px;

                    }

                </style>

                <script language="JavaScript" type="text/javascript">

                         function ShowHide(panelID)

                    {

                        var panel = document.getElementById(panelID);

                        if (panel != null)

                        {

                            if (panel.style.visibility == "hidden")

                            {

                                panel.style.display = "block";

                                panel.style.visibility = "visible";

                            }

                            else

                            {

                                panel.style.display = "none";

                                panel.style.visibility = "hidden";

                            }

                        }

                    }

                </script>

 

            </head>

            <body>

                <xsl:for-each select="MyLog/LogEntry">

                    <xsl:sort select="Timestamp" order="ascending" />

                        <div class="LineItem" onclick="ShowHide('{generate-id(Message)}')"><span class="EntryDetailsLabel"><xsl:value-of select="Timestamp"/>: </span><xsl:value-of select="Message" /></div>

                        <div class="EntryDetails" style="visibility: hidden; display: none;" id="{generate-id(Message)}">

                            <div><span class="EntryLogDetailsLabel">Category: </span><xsl:value-of select="Category" /></div>

                            <div><span class=" EntryLogDetailsLabel ">Priority: </span>

                            <xsl:choose>

                                               <xsl:when test="Priority = -1">Lowest</xsl:when>

                                <xsl:when test="Priority = 1">Low</xsl:when>

                                <xsl:when test="Priority = 2">Medium</xsl:when>

                                <xsl:when test="Priority = 3">High</xsl:when>

                                <xsl:when test="Priority = 4">Urgent</xsl:when>

                            </xsl:choose></div>

                            <div><span class=" EntryLogDetailsLabel ">EventId: </span>

                            <div><span class=" EntryLogDetailsLabel ">Severity: </span><xsl:value-of select="Severity" /></div>

                            <div><span class=" EntryLogDetailsLabel ">Machine name: </span><xsl:value-of select="Machine" /></div>

                            <div><span class=" EntryLogDetailsLabel "> Process ID: </span><xsl:value-of select="AppDomain" /></div>

                            <div><span class=" EntryLogDetailsLabel "> AppDomain: </span><xsl:value-of select="ProcessId" /></div>

                            <div><span class=" EntryLogDetailsLabel ">Process name: </span><xsl:value-of select="ProcessName" /></div>

                            <div><span class=" EntryLogDetailsLabel ">Win32 Thread ID: </span><xsl:value-of select="ThreadName" /></div>

                        </div>

                </xsl:for-each>

            </body>

        </html>

    </xsl:template>
</xsl:stylesheet>
Then we can put the user favorite xml file name on the same folder as the original txt formatter log file. Then when user click their favorite xml file name, it will automatically locate the txt formatter log file and transform them and present them as neat xml file in the browser. The xml file looks like below:

<?xml version="1.0" encoding="utf-8" ?>

<?xml-stylesheet type="text/xsl" href=" xmlLogTransforms.xslt "?>

<!DOCTYPE MyLog [ <!ENTITY LogEntries SYSTEM "favorite.log"> ]>

<MyLog>

    &LogEntries;
</MyLog>

Conclusion:
Now, user should be able to see the concise and lovely xml formatter log file, which outstandingly offer us below improvements:

  1. optimize the performance by speeding up the opening process outstandingly.
  2. user can customize the layout style by themselves.
  3. improve reading capability by clicking show and hiding.

Login to add your contents and source code to this article
share this article :
post comment
 

Nice Article

Posted by Dea Saddler Aug 03, 2011

I am using Enterprise Library 3.1 to log exceptions. It uses rolling text file to log exceptions. I need to create a .NET Application to read rolling text file and display it in user friendly manner to support team. Is there a way to do so? In future, we may add filter criteria too.

Thanks

Posted by Gnanavel M Aug 12, 2009
Become a Sponsor
PREMIUM SPONSORS
  • Finally – a virtual platform that delivers next-generation Windows Server 2008 Hyper-V virtualization technology from a managed hosting partner you can truly depend on. Visit www.maximumasp.com/max for a FREE 30 day trial. Hurry offer ends soon. Climb aboard the MaxV platform and take advantage of High Availability, Intelligent Monitoring, Recurrent Backups, and Scalability – with no hassle or hidden fees. As a managed hosting partner focused solely on Microsoft technologies since 2000, MaximumASP is uniquely qualified to provide the superior support that our business is built on. Unparalleled expertise with Microsoft technologies lead to working directly with Microsoft as first to offer IIS 7 and SQL 2008 betas in a hosted environment; partnering in the Go Live Program for Hyper-V; and product co-launches built on WS 2008 with Hyper-V technology.
    ceTE software specializes in components for dynamic PDF generation and manipulation. The DynamicPDF™ product line allows you to dynamically generate PDF documents, merge PDF documents and new content to existing PDF documents from within your applications.
Nevron Gauge for SharePoint
Become a Sponsor