禁用FileConfigurationSourceChanged上的日志记录 - LogEnabledFilter

时间:2016-09-16 19:29:30

标签: enterprise-library enterprise-library-6

我希望管理员通过更改配置中LogEnabledFilter的enabled属性来在运行时启用/禁用日志记录。

SO上有几个解释变通方法的线程,但我想这样做。 我试图像这样更改启用日志记录的过滤器:

private static void FileConfigurationSourceChanged(object sender, ConfigurationSourceChangedEventArgs e)
{
    var fcs = sender as FileConfigurationSource;

    System.Diagnostics.Debug.WriteLine("----------- FileConfigurationSourceChanged called --------");

    LoggingSettings currentLogSettings = e.ConfigurationSource.GetSection("loggingConfiguration") as LoggingSettings;
    var fdtl = currentLogSettings.TraceListeners.Where(tld => tld is FormattedDatabaseTraceListenerData).FirstOrDefault();
    var currentLogFileFilter = currentLogSettings.LogFilters.Where(lfd => { return lfd.Name == "Logging Enabled Filter"; }).FirstOrDefault();
    var filterNewValue = (bool)currentLogFileFilter.ElementInformation.Properties["enabled"].Value;

    var runtimeFilter = Logger.Writer.GetFilter<LogEnabledFilter>("Logging Enabled Filter");
    runtimeFilter.Enabled = filterNewValue;

   var test =  Logger.Writer.IsLoggingEnabled();

}

但是测试总是显示最初加载的配置值,它不会改变。 我想,在更改配置中的值时,更改将自动传播到运行时配置。但事实并非如此! 如上面代码所示以编程方式设置它也不起作用。

现在是重建Enterprise Library或关闭它的时候了。

2 个答案:

答案 0 :(得分:1)

您发布的代码不起作用是对的。该代码使用配置文件(FileConfigurationSource)作为配置企业库的方法。

让我们深入一点,看看程序化配置是否有效。

我们将使用Fluent API,因为它是编程配置的首选方法:

var builder = new ConfigurationSourceBuilder();

builder.ConfigureLogging()
    .WithOptions
    .DoNotRevertImpersonation()
    .FilterEnableOrDisable("EnableOrDisable").Enable()
    .LogToCategoryNamed("General")
    .WithOptions.SetAsDefaultCategory()
    .SendTo.FlatFile("FlatFile")
    .ToFile(@"fluent.log");

var configSource = new DictionaryConfigurationSource();
builder.UpdateConfigurationWithReplace(configSource);

var defaultWriter = new LogWriterFactory(configSource).Create();
defaultWriter.Write("Test1", "General");

var filter = defaultWriter.GetFilter<LogEnabledFilter>();
filter.Enabled = false;

defaultWriter.Write("Test2", "General");

如果你尝试这个代码,过滤器将不会更新 - 所以另一个失败。

让我们尝试使用#34;旧学校&#34;直接使用类的编程配置:

var flatFileTraceListener = new FlatFileTraceListener(
    @"program.log", 
    "----------------------------------------", 
    "----------------------------------------"
    );

LogEnabledFilter enabledFilter = new LogEnabledFilter("Logging Enabled Filter", true);
// Build Configuration
var config = new LoggingConfiguration();

config.AddLogSource("General", SourceLevels.All, true)
    .AddTraceListener(flatFileTraceListener);

config.Filters.Add(enabledFilter);

LogWriter defaultWriter = new LogWriter(config);

defaultWriter.Write("Test1", "General");

var filter = defaultWriter.GetFilter<LogEnabledFilter>();
filter.Enabled = false;

defaultWriter.Write("Test2", "General");

成功!第二个(&#34; Test2&#34;)消息未被记录。

那么,这里发生了什么?如果我们自己实例化过滤器并将其添加到配置中它可以工作,但是当依赖Enterprise Library配置时,过滤器值不会更新。

这导致了一个假设:在使用Enterprise Library配置时,每次都返回新的过滤器实例,这就是更改值对Enterprise Library正在使用的内部实例没有影响的原因。

如果我们深入研究企业库代码,我们(最终)会点击LoggingSettings类和BuildLogWriter方法。这用于创建LogWriter。以下是创建过滤器的位置:

var filters = this.LogFilters.Select(tfd => tfd.BuildFilter());

因此,这一行使用配置的LogFilterData并调用BuildFilter方法来实例化适用的过滤器。在这种情况下,配置类BuildFilter LogEnabledFilterData方法的BuildFilter方法返回LogEnabledFilter的实例:

return new LogEnabledFilter(this.Name, this.Enabled);

此代码的问题是this.LogFilters.Select返回一个创建LogFilters的惰性评估枚举,并且此枚举将传递到LogWriter以用于所有过滤器操作。每次引用过滤器时,都会计算枚举值并创建一个新的Filter实例!这证实了最初的假设。

使其明确:每次调用LogWriter.Write()时,都会根据原始配置创建新的LogEnabledFilter。通过调用GetFilter()查询过滤器时,将根据原始配置创建新的LogEnabledFilterGetFilter()返回的对象的任何更改都不会影响内部配置,因为它是一个新的对象实例,无论如何,内部企业库将在下一个Write()调用中创建另一个新实例。

首先,这是完全错误的,但在每次调用Write()时创建新对象也是低效的,可以多次调用..

此问题的一个简单方法是通过调用ToList()来评估LogFilters枚举:

var filters = this.LogFilters.Select(tfd => tfd.BuildFilter()).ToList();

仅在确保只创建一个过滤器实例时评估枚举。然后,问题中发布的GetFilter()和更新过滤器值方法将起作用。

答案 1 :(得分:0)

<强>更新

Randy Levy在上面的回答中提供了一个解决方案。 实现修复并重新编译企业库。

以下是Randy Levy的回答:

  

是的,您可以通过设置LogEnabledFiter来禁用日志记录。主要的   这样做的方法是手动编辑配置文件 -   这是该功能的主要目的(开发人员指南)   引用管理员调整此设置)。其他类似   设置过滤器的方法是以编程方式修改   原始的基于文件的配置(基本上是一个   重新配置块),或重新配置块   以编程方式(例如使用流畅的界面)。没有任何一个   程序化方法就是我所说的简单 - Randy Levy 39   分钟前

  

如果您尝试使用过滤器并禁用它,我认为它没有   没有重新配置就会影响。所以下面的代码仍然会结束   logging:var enabledFilter = logWriter.GetFilter();   enabledFilter.Enabled = false; logWriter.Write(&#34; TEST&#34);一个非EntLib   方法只是用bool管理启用/禁用自己   属性和帮助类。但我认为优先考虑的方法是   很直接的选择。

<强>结论:

在自定义Logger类中实现IsLoggenabled属性并在运行时更改/检查此属性。

这不会起作用

var runtimeFilter = Logger.Writer.GetFilter<LogEnabledFilter>("Logging Enabled Filter");
runtimeFilter.Enabled = false/true;
相关问题