如何在EntLib日志应用程序块中为跟踪侦听器设置和使用多个格式化程序

时间:2013-06-13 05:19:17

标签: logging enterprise-library

我已经配置了EntLib 5日志记录应用程序块,用于为WinForms应用程序创建日志。

日志记录配置的配置如下:

<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>

这很好用。

我想要的是日志中的某种格式。 目前日志只是从开始到结束的一堆行:

[ 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: 

因此,不是第3行和第6行写时间戳,机器和消息我想要一个空行,如下所示:

[ 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

我想要的就是能够在需要的地方放置空行。 目前,即使是空行,EntLib也会因为格式化程序而写入时间戳和机器名。

如何在日志中添加空行?

1 个答案:

答案 0 :(得分:1)

跟踪侦听器只能有一个格式化程序,并且只有一个跟踪侦听器可以写入一个文件,因此您不能为同一个跟踪侦听器使用多个格式化程序。

据我所知,您想要记录一定数量的LogEntry,并且在一定数量之后,您想在日志文件中添加一个新行。

如果是这种情况,那么您的应用程序需要跟踪何时写入空行。最简单的方法是简单地在message属性中添加一个新行(格式化程序中的最后一个属性)以强制换行:

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);

这将产生如下输出:

[ 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

为了示例,我只重用一个LogEntry,但几乎总是为每个Write()调用创建一个新的LogEntry。

现在,如果您不知道您可能正在记录哪些LogEntry(因为日志记录具有基于数据的条件逻辑),那么它会变得有点混乱。我能想到的唯一方法是预先格式化Message属性,然后将Message属性写入文件。

为此,我将创建两个格式化程序:一个用于根据您的要求格式化日志条目(“文本格式化程序”),另一个用于简单地写出消息属性(“消息文本格式化程序”)。基本上,您正在将格式转移到代码中,并且只写出包含已格式化消息的Message属性。

您不必使用Enterprise Library格式化程序来执行此操作,但此示例可以。此外,由于格式化在代码中完成,您只需将格式化的消息字符串传递给其中一个Write重载方法。

<?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>

然后,您可以获取格式化程序,格式化消息,将格式化的消息分配给Message属性,然后记录消息。要编写新行,只需将Message属性设置为空字符串:

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);

这不是特别优雅,所以你可能想要将这个逻辑包装在一些帮助/扩展方法背后(即使这样,只需要获得一个新行就可以完成一些工作)。

输出如下:

[ 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