我希望管理员通过更改配置中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或关闭它的时候了。
答案 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()
查询过滤器时,将根据原始配置创建新的LogEnabledFilter
。 GetFilter()
返回的对象的任何更改都不会影响内部配置,因为它是一个新的对象实例,无论如何,内部企业库将在下一个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;