简体   繁体   中英

How to set and use more than one formatter for a trace listener in EntLib log app block

I have configured EntLib 5 logging app block for creating logs for a WinForms app.

The logging configuration is configured like so:

<loggingConfiguration name="Logging Application Block" tracingEnabled="true" defaultCategory="Developer" logWarningsWhenNoCategoriesMatch="true">
    <listeners>
      <add listenerDataType="Microsoft.Practices.EnterpriseLibrary.Logging.Configuration.CustomTraceListenerData, Microsoft.Practices.EnterpriseLibrary.Logging, Version=5.0.505.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" traceOutputOptions="None" filter="All" type="DataSynchronizationManager.CustomStatusTraceListener, DataSynchronizationManager, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" name="Custom Trace Listener" initializeData="" />
      <add fileName="trace.log" header="" footer="" formatter="Text Formatter" listenerDataType="Microsoft.Practices.EnterpriseLibrary.Logging.Configuration.FlatFileTraceListenerData, Microsoft.Practices.EnterpriseLibrary.Logging, Version=5.0.505.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" traceOutputOptions="DateTime" filter="Information" type="Microsoft.Practices.EnterpriseLibrary.Logging.TraceListeners.FlatFileTraceListener, Microsoft.Practices.EnterpriseLibrary.Logging, Version=5.0.505.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" name="InformationListener" />
    </listeners>
    <formatters>
      <add template="[ {timestamp} ]    Machine: {machine}  Message: {message}" type="Microsoft.Practices.EnterpriseLibrary.Logging.Formatters.TextFormatter, Microsoft.Practices.EnterpriseLibrary.Logging, Version=5.0.505.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" name="Text Formatter" />
    </formatters>
    <logFilters>
      <add categoryFilterMode="AllowAllExceptDenied" type="Microsoft.Practices.EnterpriseLibrary.Logging.Filters.CategoryFilter, Microsoft.Practices.EnterpriseLibrary.Logging, Version=5.0.505.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" name="Category Filter" />
    </logFilters>
    <categorySources>
      <add switchValue="Information" name="Developer">
        <listeners>
          <add name="Custom Trace Listener" />
          <add name="InformationListener" />
        </listeners>
      </add>
      <add switchValue="Information" name="User">
        <listeners>
          <add name="Custom Trace Listener" />
          <add name="InformationListener" />
        </listeners>
      </add>
    </categorySources>
    <specialSources>
      <allEvents switchValue="All" name="All Events" />
      <notProcessed switchValue="All" name="Unprocessed Category" />
      <errors switchValue="All" name="Logging Errors &amp; Warnings" />
    </specialSources>
  </loggingConfiguration>

This works fine.

What I would like to have is some kind of formatting in the log. Currently the log is just a bunch of lines from beggining to end like so:

[ 04-06-2013 08:54:20 ]    Machine: ABC  Message: sjfdj ajlfkdjlf ajflkdjf ajfkljadlk jlkafjlkds
[ 04-06-2013 14:24:20 ]    Machine: ABC  Message: iweurtweu mcxvnmcxnvmx dksjflkdjf eowiruoei
[ 04-06-2013 14:24:20 ]    Machine: ABC  Message: 
[ 04-06-2013 08:54:20 ]    Machine: ABC  Message: sjfdj ajlfkdjlf ajflkdjf ajfkljadlk jlkafjlkds
[ 04-06-2013 14:24:20 ]    Machine: ABC  Message: iweurtweu mcxvnmcxnvmx dksjflkdjf eowiruoei
[ 04-06-2013 14:24:20 ]    Machine: ABC  Message: 

So instead of the 3rd and 6th lines writing the timestamp, Machine and Message I would like to have an empty line like so:

[ 04-06-2013 08:54:20 ]    Machine: ABC  Message: sjfdj ajlfkdjlf ajflkdjf ajfkljadlk jlkafjlkds
[ 04-06-2013 14:24:20 ]    Machine: ABC  Message: iweurtweu mcxvnmcxnvmx dksjflkdjf eowiruoei

[ 04-06-2013 08:54:20 ]    Machine: ABC  Message: sjfdj ajlfkdjlf ajflkdjf ajfkljadlk jlkafjlkds
[ 04-06-2013 14:24:20 ]    Machine: ABC  Message: iweurtweu mcxvnmcxnvmx dksjflkdjf eowiruoei

All I want is the ability to put an empty line where required. Currently even for an empty line EntLib will write the timestamp and the machine name because of the formatter.

What should be done to just put an empty line in the log?

A Trace Listener can have only one formatter and only one Trace Listener can write to one file so you can't have multiple formatters for the same Trace Listener.

As I understand your question you want to log a certain number of LogEntry's and after a certain number you want to put a new line in the log file.

If that is the case then your application needs to keep track of when to write an empty line. The easiest way is to simply add a new line to the message property (last property in the formatter) to force a line break:

LogEntry logEntry = new LogEntry()
{
    Message = "Test",
    Categories = new string[] { "User" }
};

var logWriter = EnterpriseLibraryContainer.Current.GetInstance<LogWriter>();

logWriter.Write(logEntry);
logWriter.Write(logEntry);

// Force a line break
logEntry.Message += Environment.NewLine;
logWriter.Write(logEntry);

logEntry.Message = "Next Set";
logWriter.Write(logEntry);

This will result in an output like this:

[ 6/13/2013 7:57:59 PM ]    Machine: MACHINE12  Message: Test
[ 6/13/2013 7:57:59 PM ]    Machine: MACHINE12  Message: Test
[ 6/13/2013 7:57:59 PM ]    Machine: MACHINE12  Message: Test

[ 6/13/2013 7:57:59 PM ]    Machine: MACHINE12  Message: Next Set

For sake of example I just reuse one LogEntry but you would almost always be creating a new LogEntry for every Write() call.

Now, if you don't know what LogEntry's you may be logging (because the logging has conditional logic based on the data) then it gets a bit messy. The only way I can think to do that would be to preformat the Message property and then just write the Message property to the file.

To do this I would create two formatters: one to format the Log Entry as per your requirements ("Text Formatter") and one to simply write out the Message Property ("Message Text Formatter"). Basically you are moving the formatting into the code and only writing out the Message property which contains the already formatted message.

You don't have to use an Enterprise Library formatter to do this but this example does. Also, you since the formatting is done in the code, you can just pass the formatted message string into one of the Write overload methods.

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
  <configSections>
    <section name="loggingConfiguration" type="Microsoft.Practices.EnterpriseLibrary.Logging.Configuration.LoggingSettings, Microsoft.Practices.EnterpriseLibrary.Logging, Version=5.0.505.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" requirePermission="true" />
  </configSections>
  <loggingConfiguration name="Logging Application Block" tracingEnabled="true"
    defaultCategory="User" logWarningsWhenNoCategoriesMatch="true">
    <listeners>
      <add name="InformationListener" type="Microsoft.Practices.EnterpriseLibrary.Logging.TraceListeners.FlatFileTraceListener, Microsoft.Practices.EnterpriseLibrary.Logging, Version=5.0.505.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"
        listenerDataType="Microsoft.Practices.EnterpriseLibrary.Logging.Configuration.FlatFileTraceListenerData, Microsoft.Practices.EnterpriseLibrary.Logging, Version=5.0.505.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"
        fileName="trace.log" header="" footer="" formatter="Message Text Formatter"
        traceOutputOptions="DateTime" filter="Information" />
    </listeners>
    <formatters>
      <add type="Microsoft.Practices.EnterpriseLibrary.Logging.Formatters.TextFormatter, Microsoft.Practices.EnterpriseLibrary.Logging, Version=5.0.505.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"
        template="[ {timestamp} ]    Machine: {machine}  Message: {message}"
        name="Text Formatter" />
      <add type="Microsoft.Practices.EnterpriseLibrary.Logging.Formatters.TextFormatter, Microsoft.Practices.EnterpriseLibrary.Logging, Version=5.0.505.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"
        template="{message}" name="Message Text Formatter" />
    </formatters>
    <logFilters>
      <add type="Microsoft.Practices.EnterpriseLibrary.Logging.Filters.CategoryFilter, Microsoft.Practices.EnterpriseLibrary.Logging, Version=5.0.505.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"
        categoryFilterMode="AllowAllExceptDenied" name="Category Filter" />
    </logFilters>
    <categorySources>
      <add switchValue="All" name="User">
        <listeners>
          <add name="InformationListener" />
        </listeners>
      </add>
    </categorySources>
    <specialSources>
      <allEvents switchValue="All" name="All Events" />
      <notProcessed switchValue="All" name="Unprocessed Category" />
      <errors switchValue="All" name="Logging Errors &amp; Warnings" />
    </specialSources>
  </loggingConfiguration>
</configuration>

Then you can get the formatter, format the message, assign the formatted message to the Message property and then log the message. To write a new line just set the Message property to be an empty string:

LogEntry logEntry = new LogEntry()
{
    Message = "Test",
    Categories = new string[] { "User" }
};

// Get the formatter
var formatter = EnterpriseLibraryContainer.Current.GetInstance<ILogFormatter>("Text Formatter");

// Format the message into the desired format and set as Message property
string formattedMessage = formatter.Format(logEntry);
logEntry.Message = formattedMessage;

var logWriter = EnterpriseLibraryContainer.Current.GetInstance<LogWriter>();

// Don't have to use a Log Entry...instead can pass in formatted message 
// string and category...the 3 lines below result in the same output
logWriter.Write(formattedMessage, "User");
logWriter.Write(logEntry);
logWriter.Write(logEntry);

// write new line
logEntry.Message = "";
logWriter.Write(logEntry);

logEntry.Message = "Next Set";
formattedMessage = formatter.Format(logEntry);
logEntry.Message = formattedMessage;

logWriter.Write(logEntry);
logWriter.Write(logEntry);
logWriter.Write(logEntry);

// write new line
logEntry.Message = "";
logWriter.Write(logEntry);

This is not particularly elegant so you would probably want to wrap this logic behind some helper/extension methods (and even then it's quite a bit of work just to get a new line).

The output would look like:

[ 6/13/2013 8:13:30 PM ]    Machine: MACHINE12  Message: Test
[ 6/13/2013 8:13:30 PM ]    Machine: MACHINE12  Message: Test
[ 6/13/2013 8:13:30 PM ]    Machine: MACHINE12  Message: Test

[ 6/13/2013 8:13:30 PM ]    Machine: MACHINE12  Message: Next Set
[ 6/13/2013 8:13:30 PM ]    Machine: MACHINE12  Message: Next Set
[ 6/13/2013 8:13:30 PM ]    Machine: MACHINE12  Message: Next Set

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM