【问题标题】:Enterprise Library 6 - dynamically change log file nameEnterprise Library 6 - 动态更改日志文件名
【发布时间】:2015-08-27 11:29:42
【问题描述】:

是否可以在 C# 中动态设置日志文件夹和文件名,从而覆盖日志配置的 Listeners 部分中的配置值(文件名)? 尝试按照以下链接进行操作,但它仅适用于 EL 5 Log messages going to previously created log file

这就是我初始化 EL 日志的方式:

 IConfigurationSource configurationSource = ConfigurationSourceFactory.Create();
        LogWriterFactory logWriterFactory = new LogWriterFactory(configurationSource);
        Logger.SetLogWriter(logWriterFactory.Create(), false);

        ExceptionPolicyFactory factory = new ExceptionPolicyFactory(configurationSource);
        ExceptionPolicy.SetExceptionManager(factory.CreateManager());           

这些是我在 listeners 标签中的 web.config 条目:

 <add name="RollingFlatFileTraceLog" type="Microsoft.Practices.EnterpriseLibrary.Logging.TraceListeners.RollingFlatFileTraceListener, Microsoft.Practices.EnterpriseLibrary.Logging, Version=6.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"
    listenerDataType="Microsoft.Practices.EnterpriseLibrary.Logging.Configuration.RollingFlatFileTraceListenerData, Microsoft.Practices.EnterpriseLibrary.Logging, Version=6.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"
    fileName="C:\logs\Trace.log" footer=""
    formatter="CustomRollingFlatFileLogFormatter"
    header="" rollFileExistsBehavior="Overwrite" rollInterval="Day"
    rollSizeKB="2048" maxArchivedFiles="52" />
  <add name="RollingFlatFileErrorLog" type="Microsoft.Practices.EnterpriseLibrary.Logging.TraceListeners.RollingFlatFileTraceListener, Microsoft.Practices.EnterpriseLibrary.Logging, Version=6.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"
    listenerDataType="Microsoft.Practices.EnterpriseLibrary.Logging.Configuration.RollingFlatFileTraceListenerData, Microsoft.Practices.EnterpriseLibrary.Logging, Version=6.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"
    fileName="C:\logs\Error.log" footer="----------------------------------------"
    formatter=" CustomRollingFlatFileLogFormatter "
    header="----------------------------------------" rollFileExistsBehavior="Overwrite"
    rollInterval="Day" rollSizeKB="2048" maxArchivedFiles="52" />

我使用 Logger.Write 和 ExceptionPolicy.HandleException 写入相应的跟踪和错误日志。

【问题讨论】:

    标签: c# logging web-config enterprise-library enterprise-library-6


    【解决方案1】:

    最好的(也是最简单的!)方法是使用编程配置来设置文件名。

    但是,您可以使用类似的方法在运行时修改设置。在外部文件中设置配置并使用 app/web.config 中的文件配置源。需要外部文件以避免配置为只读异常。

    <?xml version="1.0" encoding="utf-8"?>
    <configuration>
        <configSections>
            <section name="enterpriseLibrary.ConfigurationSource" type="Microsoft.Practices.EnterpriseLibrary.Common.Configuration.ConfigurationSourceSection, Microsoft.Practices.EnterpriseLibrary.Common, Version=6.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" requirePermission="true" />
        </configSections>
        <enterpriseLibrary.ConfigurationSource selectedSource="File-based Configuration Source">
            <sources>
                <add name="File-based Configuration Source" type="Microsoft.Practices.EnterpriseLibrary.Common.Configuration.FileConfigurationSource, Microsoft.Practices.EnterpriseLibrary.Common, Version=6.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"
                    filePath="entlib.config" />
            </sources>
        </enterpriseLibrary.ConfigurationSource>
        <startup> 
            <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.6"/>
        </startup>
    </configuration>
    

    并配置外部文件(本例为entlib.config):

    <configuration>
        <configSections>
            <section name="exceptionHandling" type="Microsoft.Practices.EnterpriseLibrary.ExceptionHandling.Configuration.ExceptionHandlingSettings, Microsoft.Practices.EnterpriseLibrary.ExceptionHandling, Version=6.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" requirePermission="true" />
            <section name="loggingConfiguration" type="Microsoft.Practices.EnterpriseLibrary.Logging.Configuration.LoggingSettings, Microsoft.Practices.EnterpriseLibrary.Logging, Version=6.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" requirePermission="true" />
        </configSections>
        <exceptionHandling>
            <exceptionPolicies>
                <add name="Policy">
                    <exceptionTypes>
                        <add name="All Exceptions" type="System.Exception, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"
                            postHandlingAction="NotifyRethrow">
                            <exceptionHandlers>
                                <add name="Logging Exception Handler" type="Microsoft.Practices.EnterpriseLibrary.ExceptionHandling.Logging.LoggingExceptionHandler, Microsoft.Practices.EnterpriseLibrary.ExceptionHandling.Logging, Version=6.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"
                                    logCategory="General" eventId="100" severity="Error" title="Enterprise Library Exception Handling"
                                    formatterType="Microsoft.Practices.EnterpriseLibrary.ExceptionHandling.TextExceptionFormatter, Microsoft.Practices.EnterpriseLibrary.ExceptionHandling"
                                    priority="0" />
                            </exceptionHandlers>
                        </add>
                    </exceptionTypes>
                </add>
            </exceptionPolicies>
        </exceptionHandling>
        <loggingConfiguration name="" tracingEnabled="true" defaultCategory="General">
            <listeners>
                <add name="Event Log Listener" type="Microsoft.Practices.EnterpriseLibrary.Logging.TraceListeners.FormattedEventLogTraceListener, Microsoft.Practices.EnterpriseLibrary.Logging, Version=6.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"
                    listenerDataType="Microsoft.Practices.EnterpriseLibrary.Logging.Configuration.FormattedEventLogTraceListenerData, Microsoft.Practices.EnterpriseLibrary.Logging, Version=6.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"
                    source="Enterprise Library Logging" formatter="Text Formatter"
                    log="" machineName="." traceOutputOptions="None" />
                <add name="Flat File Trace Listener" type="Microsoft.Practices.EnterpriseLibrary.Logging.TraceListeners.FlatFileTraceListener, Microsoft.Practices.EnterpriseLibrary.Logging, Version=6.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"
                    listenerDataType="Microsoft.Practices.EnterpriseLibrary.Logging.Configuration.FlatFileTraceListenerData, Microsoft.Practices.EnterpriseLibrary.Logging, Version=6.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"
                    fileName="trace.log" />
            </listeners>
            <formatters>
                <add type="Microsoft.Practices.EnterpriseLibrary.Logging.Formatters.TextFormatter, Microsoft.Practices.EnterpriseLibrary.Logging, Version=6.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"
                    template="Timestamp: {timestamp}{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="Event Log Listener" />
                    </listeners>
                </errors>
            </specialSources>
        </loggingConfiguration>
    </configuration>
    

    使用博文中的SerializableConfigurationSource

    public class SerializableConfigurationSource : IConfigurationSource
    {
        Dictionary<string, ConfigurationSection> sections = new Dictionary<string, ConfigurationSection>();
    
        public SerializableConfigurationSource()
        {
        }
    
        public ConfigurationSection GetSection(string sectionName)
        {
            ConfigurationSection configSection;
    
            if (sections.TryGetValue(sectionName, out configSection))
            {
                SerializableConfigurationSection section = configSection as SerializableConfigurationSection;
    
                if (section != null)
                {
                    using (StringWriter xml = new StringWriter())
                    using (XmlWriter xmlwriter = System.Xml.XmlWriter.Create(xml))
                    {
                        section.WriteXml(xmlwriter);
                        xmlwriter.Flush();
    
                        MethodInfo methodInfo = section.GetType().GetMethod("DeserializeSection", BindingFlags.NonPublic | BindingFlags.Instance);
                        methodInfo.Invoke(section, new object[] { XDocument.Parse(xml.ToString()).CreateReader() });
    
                        return configSection;
                    }
                }
            }
    
            return null;
        }
    
        public void Add(string sectionName, ConfigurationSection configurationSection)
        {
            sections[sectionName] = configurationSection;
        }
    
        public void AddSectionChangeHandler(string sectionName, ConfigurationChangedEventHandler handler)
        {
            throw new NotImplementedException();
        }
    
        public void Remove(string sectionName)
        {
            sections.Remove(sectionName);
        }
    
        public void RemoveSectionChangeHandler(string sectionName, ConfigurationChangedEventHandler handler)
        {
            throw new NotImplementedException();
        }
    
        public event EventHandler<ConfigurationSourceChangedEventArgs> SourceChanged;
    
        public void Dispose()
        {
        }
    }
    

    在启动时引导块:

    IConfigurationSource configSource = ConfigurationSourceFactory.Create();
    
    var loggingSettings = configSource.GetSection(LoggingSettings.SectionName) as LoggingSettings;    
    var data = loggingSettings.TraceListeners.First(t => t.Name == "Flat File Trace Listener") as FlatFileTraceListenerData;
    // Change the file name
    data.FileName = "trace_1.txt";
    
    var loggingXmlConfigSource = new SerializableConfigurationSource();
    loggingXmlConfigSource.Add(LoggingSettings.SectionName, loggingSettings);
    
    var logFactory = new LogWriterFactory(loggingXmlConfigSource);
    Logger.SetLogWriter(logFactory.Create());
    
    IConfigurationSource config = ConfigurationSourceFactory.Create();
    ExceptionPolicyFactory factory = new ExceptionPolicyFactory(config);
    
    ExceptionManager exManager = factory.CreateManager();
    ExceptionPolicy.SetExceptionManager(exManager);
    
    // This will log to the file trace_1.txt
    ExceptionPolicy.HandleException(new Exception(), "Policy");
    

    【讨论】:

    • 感谢 Randy,已更改为 RollingFlatFileListenerData,能够使用您的解决方案,日志文件名在启动期间动态设置在内存中,并且按预期工作!再次感谢。由于我的解决方案在 Windows 服务中运行(无需重新启动即可运行),为了刷新内存,我猜我必须在午夜重新启动服务才能重新初始化日志记录(我的要求是将日志文件放入具有今天名称 YYYYMMDD - 12.AM) 的目录。
    【解决方案2】:

    正如您在帖子中提到的,在外部文件中设置配置。外部文件的意思,你能确定我们必须把Entlib.config文件放在哪个路径吗?

    【讨论】:

    猜你喜欢
    • 2014-06-15
    • 2023-04-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-01-21
    相关资源
    最近更新 更多