在ASP.NET和EntLib 5.0中实现Rolling日志文件

时间:2012-05-10 04:40:43

标签: asp.net enterprise-library

我正在使用EntLib 5来创建滚动平面文件。这不使用Rolling Flat File跟踪侦听器,而是使用Flat File Trace侦听器,并在代码中进行一些修改。 滚动平面文件跟踪侦听器未被使用,因为它的固有设计问题因此不符合此处的要求。

以下是配置部分:

    <configuration>
    <configSections>
        <section name="loggingConfiguration" type="Microsoft.Practices.EnterpriseLibrary.Logging.Configuration.LoggingSettings, Microsoft.Practices.EnterpriseLibrary.Logging, Version=5.0.414.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" requirePermission="true"/>
        <sectionGroup name="system.web.extensions" type="System.Web.Configuration.SystemWebExtensionsSectionGroup, System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35">
            <sectionGroup name="scripting" type="System.Web.Configuration.ScriptingSectionGroup, System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35">
                <section name="scriptResourceHandler" type="System.Web.Configuration.ScriptingScriptResourceHandlerSection, System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" requirePermission="false" allowDefinition="MachineToApplication"/>
                <sectionGroup name="webServices" type="System.Web.Configuration.ScriptingWebServicesSectionGroup, System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35">
                    <section name="jsonSerialization" type="System.Web.Configuration.ScriptingJsonSerializationSection, System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" requirePermission="false" allowDefinition="Everywhere"/>
                    <section name="profileService" type="System.Web.Configuration.ScriptingProfileServiceSection, System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" requirePermission="false" allowDefinition="MachineToApplication"/>
                    <section name="authenticationService" type="System.Web.Configuration.ScriptingAuthenticationServiceSection, System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" requirePermission="false" allowDefinition="MachineToApplication"/>
                    <section name="roleService" type="System.Web.Configuration.ScriptingRoleServiceSection, System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" requirePermission="false" allowDefinition="MachineToApplication"/>
                </sectionGroup>
            </sectionGroup>
        </sectionGroup>
    </configSections>
    <loggingConfiguration name="" tracingEnabled="true" defaultCategory="General">
  <listeners>
   <add name="Flat File Trace Listener" type="Microsoft.Practices.EnterpriseLibrary.Logging.TraceListeners.FlatFileTraceListener, Microsoft.Practices.EnterpriseLibrary.Logging, Version=5.0.414.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"
    listenerDataType="Microsoft.Practices.EnterpriseLibrary.Logging.Configuration.FlatFileTraceListenerData, Microsoft.Practices.EnterpriseLibrary.Logging, Version=5.0.414.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"
    fileName="./Logs/MyLog.log" formatter="Text Formatter" />
  </listeners>
  <formatters>
   <add type="Microsoft.Practices.EnterpriseLibrary.Logging.Formatters.TextFormatter, Microsoft.Practices.EnterpriseLibrary.Logging, Version=5.0.414.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"
    template="Timestamp: {timestamp(local)}{newline}&#xA;Message: {message}{newline}&#xA;Category: {category}{newline}&#xA;Priority: {priority}{newline}&#xA;EventId: {eventid}{newline}&#xA;Severity: {severity}{newline}&#xA;Title:{title}{newline}&#xA;Machine: {localMachine}{newline}&#xA;App Domain: {localAppDomain}{newline}&#xA;ProcessId: {localProcessId}{newline}&#xA;Process Name: {localProcessName}{newline}&#xA;Thread Name: {threadName}{newline}&#xA;Win32 ThreadId:{win32ThreadId}{newline}&#xA;Extended Properties: {dictionary({key} - {value}{newline})}"
    name="Text Formatter" />
  </formatters>
  <categorySources>
   <add switchValue="All" name="General">
    <listeners>
     <add name="Flat File Trace Listener" />
    </listeners>
   </add>
  </categorySources>
  <specialSources>
   <allEvents switchValue="All" name="All Events" />
   <notProcessed switchValue="All" name="Unprocessed Category" />
   <errors switchValue="All" name="Logging Errors &amp; Warnings">
    <listeners>
     <add name="Flat File Trace Listener" />
    </listeners>
   </errors>
  </specialSources>
 </loggingConfiguration>
    <appSettings>
        <add key="LogFolder" value="./Logs"/>
        <add key="LogFileName" value="MyLog.log"/>
    </appSettings>
    <system.web>

然后我使用以下代码创建一个静态类来配置日志记录过程:

public static class LoggingHelper {
private static string date = String.Format(System.Globalization.CultureInfo.InvariantCulture, "{0:yyyyMMdd}", DateTime.Now);

public static void SetLogFile(string logFileFolder,string logFileName) {
    if (!string.IsNullOrEmpty(logFileName)) {
        string strfileName = logFileFolder + "/" + date + logFileName;
        LoggingHelper.SetTraceLogPath(strfileName, "FlatFile TraceListener", "General", "My Login System");
        LoggingHelper.WriteLogFile("General", "Log file path " + logFileFolder + "/" + logFileName, " My Login System");
    }
}  

public static void SetTraceLogPath(string logFile, string logFileName, string category, string message) {
    ConfigurationFileMap configFileMap = new ConfigurationFileMap();
    configFileMap.MachineConfigFilename = "Web.config";
    Configuration entLibConfig = WebConfigurationManager.OpenWebConfiguration("/ASP.NET_Logging");
    LoggingSettings loggingSettings = (LoggingSettings)entLibConfig.GetSection(LoggingSettings.SectionName);

    FlatFileTraceListenerData data = loggingSettings.TraceListeners.Get("Flat File Trace Listener") as FlatFileTraceListenerData;
    data.FileName = logFile;
    entLibConfig.Save();
    LogEntry objLog = new LogEntry();
    objLog.TimeStamp = System.DateTime.Now;
    objLog.Categories.Add(category);
    objLog.Message = message;
    objLog.Priority = 1;
    Logger.Write(objLog);

}

public static void WriteLogFile(string category, string msg, string title) {
    try {
        LogEntry le = new LogEntry();
        le.TimeStamp = System.DateTime.Now;
        le.Categories.Add(category);
        le.Severity = TraceEventType.Information;
        le.Priority = 1;
        le.Message = msg;
        le.Title = title;
        le.Priority = 1;
        Logger.Write(le);
    } catch (LoggingException ex) {
        LoggingHelper.WriteLogFile("General", "Error in writing log file " + ex.ToString(), "My Login System");
    }
}}

在Application_Start方法中调用SetLogFile是Global.aspx页面,如下所示:

void Application_Start(object sender, EventArgs e) 
{
    // Code that runs on application startup
    LoggingHelper.SetLogFile(ConfigurationSettings.AppSettings["LogFolder"].Trim     (),      ConfigurationSettings.AppSettings["LogFileName"].Trim());
    LoggingHelper.WriteLogFile("General", "*** Application_Start ***", "");
}

然后我只需要在需要记录的地方调用WriteLogFile方法:

protected void btn_Page2_Click(object sender, EventArgs e) {
    LoggingHelper.WriteLogFile("General", "btn_Page2_Click on Default.aspx", "");

    Response.Redirect("SecongPage.aspx");

}

这样可以正常使用,但是对于一个小问题。当第一次访问网页时,它不会创建具有Logfilename.log格式的日志文件,它只是创建MyLog.log或Web.config中指定的任何名称,并且在指定的文件夹之外创建日志文件,在此案例'Log',这是第一次。对于后续请求,它将在配置的文件夹中创建具有所需文件名的所需文件。 这种模式每天重复,第一次请求的第二天,日志将写入昨天的文件,然后从下一个请求开始创建具有今天日期的新文件,所有日志消息将写入该文件。

我在代码中做了什么导致这种情况发生?

我们使用上面的代码进行微小的更改,以便在没有问题的情况下登录我们的WinForms应用程序。

该网站目前尚未部署在IIS中。由于它正在进行中,我们正在使用VS 2008中的内置开发服务器。另一个值得关注的问题是代码尝试在启动期间以leat一次更新Web.config。不知道这是否可以解决这个问题!

这是一个非常简单的示例,有两个页面,第一页有一个按钮,点击时指向第二页。我正在尝试每天实施日志文件,EntLib附带的滚动平面文件不符合要求,因为它不会每天创建一个文件,并且当天需要该日期。

问候。

1 个答案:

答案 0 :(得分:0)

搜索了很长时间后。这就是我提出的。我们的想法是使用FlatFile Trace列表器而不是内置滚动平面文件。

<强>声明: 我的一位同事和他有这个代码,他不记得他从哪里得到它,所以如果你是所有者或者写了类似的代码,那么谢谢你。

请不要为这个答案投票,因为我不是它的拥有者。然而,它可以帮助任何寻找类似实现的人

这使用EntLib 4,但也可以与EntLib 5一起使用。

以下是我的Web.config中的日志记录部分:

<loggingConfiguration name="Logging Application Block" tracingEnabled="true"
defaultCategory="User" logWarningsWhenNoCategoriesMatch="true">
<listeners>
  <add fileName="trace.log" header="----------------------------------------"
    footer="----------------------------------------" formatter=""
    listenerDataType="Microsoft.Practices.EnterpriseLibrary.Logging.Configuration.FlatFileTraceListenerData, Microsoft.Practices.EnterpriseLibrary.Logging, Version=4.1.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"
    traceOutputOptions="None" filter="All" type="Microsoft.Practices.EnterpriseLibrary.Logging.TraceListeners.FlatFileTraceListener, Microsoft.Practices.EnterpriseLibrary.Logging, Version=4.1.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"
    name="FlatFile TraceListener" />
  <add fileName="MyLoggingSystem.log" header="" footer="" formatter="Text Formatter"
    listenerDataType="Microsoft.Practices.EnterpriseLibrary.Logging.Configuration.FlatFileTraceListenerData, Microsoft.Practices.EnterpriseLibrary.Logging, Version=4.1.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"
    traceOutputOptions="None" filter="All" type="Microsoft.Practices.EnterpriseLibrary.Logging.TraceListeners.FlatFileTraceListener, Microsoft.Practices.EnterpriseLibrary.Logging, Version=4.1.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"
    name="MyLoggingApp FlatFile TraceListener " />
  <add listenerDataType="Microsoft.Practices.EnterpriseLibrary.Logging.Configuration.WmiTraceListenerData, Microsoft.Practices.EnterpriseLibrary.Logging, Version=4.1.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"
    traceOutputOptions="None" filter="All" type="Microsoft.Practices.EnterpriseLibrary.Logging.TraceListeners.WmiTraceListener, Microsoft.Practices.EnterpriseLibrary.Logging, Version=4.1.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"
    name="WMI TraceListener" />
</listeners>
<formatters>
  <add template="[{timestamp}]  [{category}] {message}" type="Microsoft.Practices.EnterpriseLibrary.Logging.Formatters.TextFormatter, Microsoft.Practices.EnterpriseLibrary.Logging, Version=4.1.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"
    name="Text Formatter" />
</formatters>
<categorySources>
  <add switchValue="All" name="Developer">
    <listeners>
      <add name="FlatFile TraceListener" />
    </listeners>
  </add>
  <add switchValue="All" name="General" />
  <add switchValue="All" name="Instrumentation">
    <listeners>
      <add name="WMI TraceListener" />
    </listeners>
  </add>
  <add switchValue="All" name="EskoLoggingApp">
    <listeners>
      <add name="MyLogging FlatFile TraceListener " />
    </listeners>
  </add>
  <add switchValue="All" name="User">
    <listeners>
      <add name="FlatFile TraceListener" />
    </listeners>
  </add>
</categorySources>
<specialSources>
  <allEvents switchValue="All" name="All Events" />
  <notProcessed switchValue="All" name="Unprocessed Category" />
  <errors switchValue="All" name="Logging Errors &amp; Warnings">
    <listeners>
      <add name="FlatFile TraceListener" />
    </listeners>
  </errors>
</specialSources>
</loggingConfiguration>

我还有两个部分,文件名和文件夹来保存文件:

<appSettings>
    <add key="LogFolder" value="./Logs" />
    <add key="LogFileName" value="MyLoginSystem" />
</appSettings>

像这样创建一个类:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Configuration;
using Microsoft.Practices.EnterpriseLibrary.Logging.Configuration;
using Microsoft.Practices.EnterpriseLibrary.Logging;
using System.Diagnostics;
using System.Globalization;
using Microsoft.Practices.EnterpriseLibrary.Logging.Formatters;
using Microsoft.Practices.EnterpriseLibrary.Logging.TraceListeners;
using Microsoft.Practices.EnterpriseLibrary.Logging.Filters;

/// <summary>
/// Summary description for Utility
/// </summary>
public static class Utility {
    /// <summary>
    /// Instance for log writer 
    /// </summary> 
    private static LogWriter writer;

    /// <summary>
    /// Instance for log writer 
    /// </summary> 
    private static LogWriter wmiWriter;

    /// <summary>
    /// Instance for log writer 
    /// </summary> 
    private static LogWriter eskoLoggingWriter;

    /// <summary>
    /// Intialize the Trace listners without using app.config file
    /// </summary>
    /// <param name="fileName">log file name</param>
    public static void Initialize(string fileName) {
        CreateLogWriterFromCode(fileName);
    }


    /// <summary>
    /// Log User Messages
    /// </summary>
    /// <param name="message">Message text</param>
    /// <param name="prior">Logger Priority</param>
    /// <param name="traceType">Trave event type</param>
    public static void LogUserMessage(string message, int prior, System.Diagnostics.TraceEventType traceType) {
        LogEntry(message, "User", prior, traceType);
    }

    /// <summary>
    /// Any type of Log Entry 
    /// </summary>
    /// <param name="message">Message text</param>
    /// <param name="category">Logger category</param>
    /// <param name="prior">Priory logger </param>
    /// <param name="traceType">Trace event type</param>
    public static void LogEntry(string message, string category, int prior, System.Diagnostics.TraceEventType traceType) {
        try {
            LogEntry log = null;
            log = new LogEntry();
            log.Message = message;
            log.Categories.Add(category);
            log.Severity = traceType;
            log.Priority = prior;
            log.TimeStamp = DateTime.Now;
            if (writer != null) {
                writer.Write(log);
            } else {
                eskoLoggingWriter.Write(log);
            }
            // wmiWriter.Write(log);
        } catch (LoggingException ex) {
            LogEntry(ex.Message, "Developer", prior, traceType);
        }
    }

    /// <summary>
    /// Log Developer Messages 
    /// </summary>
    /// <param name="message">Message text</param>
    /// <param name="prior">Logger priority</param>
    /// <param name="traceType">Trace event type</param>
    public static void LogDeveloperMessage(string message, int prior, System.Diagnostics.TraceEventType traceType) {
        LogEntry(message, "Developer", prior, traceType);
    }

    /// <summary>
    /// Close splash screen
    /// </summary>
    public static void ExitSplash() {
        Logger.Reset();
    }

    /// <summary>
    /// Disposing log write instance
    /// </summary>
    public static void Dispose() {
        if (writer != null) {
            writer = null;
        }
    }

    /// <summary>
    /// Creating log writer programatically 
    /// </summary>
    /// <param name="fileName">Full path of log file</param>
    static private void CreateLogWriterFromCode(string fileName) {
        if (writer != null) {
            writer = null;
        }
        //// The formatter is responsible for the look of the message. Notice the tokens: {timestamp}, {newline}, {message}, {category}
        TextFormatter formatter = new TextFormatter
            ("[{timestamp}]" + "[{category}]" + "{message}{newline}");

        //// Log messages to a log file. Use the formatter mentioned above specified.

        FlatFileTraceListener logFileListener = new FlatFileTraceListener(fileName, "", "", formatter);
        //// My collection of TraceListeners. 
        LogSource mainLogSource =
            new LogSource("FlatFile TraceListener", SourceLevels.All);
        mainLogSource.Listeners.Add(logFileListener);

        //// Assigning a non-existant LogSource for Logging Application Block 
        //// Specials Sources I don't care about.Used to say "don't log".
        LogSource nonExistantLogSource = new LogSource("Empty");

        //// I want all messages with a category of "User" or "Developer" to get distributed
        //// to all TraceListeners in my mainLogSource.
        IDictionary<string, LogSource> traceSources =
                      new Dictionary<string, LogSource>();
        traceSources.Add("User", mainLogSource);
        traceSources.Add("Developer", mainLogSource);

        // Let's glue it all together.
        // No filters at this time.
        // I won't log a couple of the Special
        // Sources: All Events and Events not
        // using "Error" or "Debug" categories.
        writer = new LogWriter(new ILogFilter[0],
                        traceSources,
                        nonExistantLogSource,
                        nonExistantLogSource,
                        mainLogSource,
                        "ALL",
                        false,
                        true);

    }

    /// <summary>
    /// Creating log writer programatically 
    /// </summary>
    static public void CreateLogWriterFromCode(string folder, string fileName) {
        if (eskoLoggingWriter == null) {
            //// The formatter is responsible for the look of the message. Notice the tokens: {timestamp}, {newline}, {message}, {category}
            TextFormatter formatter = new TextFormatter
                ("[{timestamp}]" + "[{category}]" + "{message}{newline}");

            //// Log messages to a log file. Use the formatter mentioned above specified.

            string date = String.Format("{0:yyyyMMdd}", DateTime.Now);
            FlatFileTraceListener logFileListener = new FlatFileTraceListener(folder + "/" + fileName + "_" + date + ".log", "", "", formatter);
            WmiTraceListener wmiListener = new WmiTraceListener();
            //// My collection of TraceListeners. 
            LogSource mainLogSource =
                new LogSource("FlatFile TraceListener", SourceLevels.All);
            LogSource wmiMainLogSource = new LogSource("WmiTraceListener", SourceLevels.All);
            mainLogSource.Listeners.Add(logFileListener);
            wmiMainLogSource.Listeners.Add(wmiListener);

            //// Assigning a non-existant LogSource for Logging Application Block 
            //// Specials Sources I don't care about.Used to say "don't log".
            LogSource nonExistantLogSource = new LogSource("Empty");

            //// I want all messages with a category of "User" or "Developer" to get distributed
            //// to all TraceListeners in my mainLogSource.
            IDictionary<string, LogSource> traceSources =
                          new Dictionary<string, LogSource>();
            traceSources.Add("User", mainLogSource);
            traceSources.Add("Developer", mainLogSource);

            IDictionary<string, LogSource> wmiTraceSources =
                                     new Dictionary<string, LogSource>();
            wmiTraceSources.Add("Instrumentation", wmiMainLogSource);

            // Let's glue it all together.
            // No filters at this time.
            // I won't log a couple of the Special
            // Sources: All Events and Events not
            // using "Error" or "Debug" categories.
            eskoLoggingWriter = new LogWriter(new ILogFilter[0],
                            traceSources,
                            nonExistantLogSource,
                            nonExistantLogSource,
                            mainLogSource,
                            "ALL",
                            false,
                            true);

            wmiWriter = new LogWriter(new ILogFilter[0],
                           wmiTraceSources,
                           nonExistantLogSource,
                           nonExistantLogSource,
                           wmiMainLogSource,
                           "All",
                           true,
                           true);
        }
    }
}

在Global.asax中,在Application_Start

中添加这些行
void Application_Start(object sender, EventArgs e) {
        // Code that runs on application startup
        Utility.CreateLogWriterFromCode(ConfigurationSettings.AppSettings["LogFolder"].Trim(), ConfigurationSettings.AppSettings["LogFileName"].Trim());
        Utility.LogUserMessage("******** Application_Start Event My Login application started   ******", 1, System.Diagnostics.TraceEventType.Information);
}

现在想要记录消息,请使用

Utility.LogUserMessage

如果使用EntLib 5,您可能必须对Utility类进行微小更改。这应该是微不足道的。

因此,您每天都有一个日志文件,其中包含当天的正确数据。 再次感谢那位首先编写Utility类的匿名者。 希望这会有所帮助。

问候。