2012-01-09 6 views
2

私はEF 5を使用していますが、ShouldLogメソッドを使用してLogEntryを実際にログに記録するかどうかを判断しようとしています。私の問題は、特定のレベルを除外するフィルタがある場合でも、必ずShouldLogがtrueを返すということです。フィルタは機能し、エントリはログに記録されませんが、ShouldLogは動作していないように見えます。エンタープライズフレームワークのロギング - ShouldLogがSourceLevelフィルタと連携しない

私はそうのように私のロガーを設定しています:

internal static void ConfigureLogging(SourceLevels logLevel) 
{ 
    var builder = new ConfigurationSourceBuilder(); 

    builder.ConfigureLogging() 
     .LogToCategoryNamed("General") 
     .WithOptions.SetAsDefaultCategory() 
     .SendTo.FlatFile("Main log file") 
     .FormatWith(
      new FormatterBuilder() 
       .TextFormatterNamed("Text Formatter") 
       .UsingTemplate("{timestamp(local:MM/dd/yyyy HH:mm:ss.fff)} [{severity}] {message}")) 
     .Filter(logLevel) //Setting the source level filter 
     .ToFile("log.txt"); 

    var configSource = new DictionaryConfigurationSource(); 
    builder.UpdateConfigurationWithReplace(configSource); 
    EnterpriseLibraryContainer.Current 
     = EnterpriseLibraryContainer.CreateDefaultContainer(configSource); 
} 

そして、このようにそれをテスト:

ConfigureLogging(SourceLevels.Warning); //Do not allow Information level 

var logEntry = new LogEntry { Message = "test", Severity = TraceEventType.Information }; 
var shouldLog = Logger.Writer.ShouldLog(logEntry); 
Logger.Writer.Write(logEntry); 

私はこのコードを実行した後shouldLog変数が真のですが、何のログエントリが書き込まれていません。 SourceLevels.InformationをConfigureLoggingメソッドに渡すと、代わりにログに書き込まれたエントリが取得されます。私は何か間違っているのですか?

答えて

1

私はあなたが何か間違っているとは思わない。しかし、私はその行動がちょっと奇妙だと認めます。

hereのように、ShouldLogメソッドは、設定されたすべてのフィルタをLogEntryに対して照会します。 ShouldLogがtrueを返す理由は、すべてのフィルタが定義されていないためです。

「待って!」と、あなたは言う。 「流暢な設定でソースレベルのフィルタを設定しました!」

これは本当に意味があります。しかし、その名前にもかかわらず、Filterメソッドは実際のフィルタを作成しません(おそらくそれは必要です)。基本的には、Writeが呼び出されたときにのみチェックされるSourceLevelsの値を設定します。流暢な設定の代わりに設定ファイルを使用すると、設定ファイルFilterは実際にはswitchValueという名前になりますので、あまり混乱しません。

したがって、SourceLevelsとの比較のために、Writeは実際には書き込みを行いません。したがって、ShouldLogはtrueを返します。これはかなり直感的です。バージョン6では、チェックがShouldLogに含まれていればいいですか?それがShouldLogの目的を破るとtrueを返します。これによりユーザーは高価なオブジェクトをたくさん作成しますが、最終的にはSourceLevelsチェックのためにメッセージは記録されません。

私がチェックし、それは、この動作のように見えますが、この動作についてはどのように過ごし少なくともバージョン4.

以来の周りされていますか?最も簡単な方法は、SourceLevelsチェックを実行するカスタムフィルタを追加することです:

public class SourceLevelFilter : LogFilter 
{ 
    private SourceLevels level; 

    public SourceLevelFilter(NameValueCollection nvc) 
     : base("SourceLevelFilter") 
    { 
     if (!Enum.TryParse<SourceLevels>(nvc["Level"], out level)) 
     { 
      throw new ArgumentOutOfRangeException(
       "Value " + nvc["Level"] + " is not a valid SourceLevels value"); 
     } 
    } 

    public override bool Filter(LogEntry log) 
    { 
     if (log == null) throw new ArgumentNullException("log"); 
     return ShouldLog(log.Severity); 
    } 

    public bool ShouldLog(TraceEventType eventType) 
    { 
     return ((((TraceEventType)level) & eventType) != (TraceEventType)0); 
    } 

    public SourceLevels SourceLevels 
    { 
     get { return level; } 
    } 
} 

// ... 

SourceLevels logLevel = SourceLevels.Warning; 

var builder = new ConfigurationSourceBuilder(); 

builder.ConfigureLogging() 
    .WithOptions 
    .FilterCustom<SourceLevelFilter>("SourceLevelFilter", 
     new NameValueCollection() { { "Level", logLevel.ToString() } }) 
    .LogToCategoryNamed("General") 
    .WithOptions.SetAsDefaultCategory() 
    .SendTo.FlatFile("Main log file") 
    .FormatWith(
     new FormatterBuilder() 
      .TextFormatterNamed("Text Formatter") 
      .UsingTemplate("{timestamp(local:MM/dd/yyyy HH:mm:ss.fff)} [{severity}] {message}")) 
    .Filter(logLevel) //Setting the source level filter 
    .ToFile("log.txt"); 

ShouldLogはそのチェックにSourceLevels値を組み込む予定してSourceLevelsが警告に設定されている場合、情報の重要度にLogEntryにfalseを返します。 。あなたはフィルタを持っているかもしれません

UPDATE

1つの問題は、おそらくカテゴリーと一緒にSourceLevelsを保存するために上記のフィルタをアップ牛肉する必要があると思いますので、彼らはグローバルであるということです。

あなただけの警告は、あなたが特定のフィルタをチェックすることができ有効であったかどうかを確認したい場合は、次の

public bool IsWarningEnabled 
{ 
    get 
    { 
     return writer.GetFilter<SourceLevelFilter>().ShouldLog(TraceEventType.Warning); 
    } 
} 

別のアプローチは、フィルタなしSourceLevelsを自分で管理することであろう。汎用のログラッパーを作成しているので、SourceLevelsがラッパーを介して設定されると仮定します。また、IsDebugEnabledなどの独自のメソッドを公開する方法についても説明します。そうであれば、その知識をラッパーの内部に保持し、その要求をオンデマンドで提供することができます。 EntLib LogWritersを呼び出し元に返す場合は、ユーザーがLogWriterでShouldLogを呼び出す必要があるため動作します。ただし、LogWriterに拡張メソッド(IsWarningEnabled()など)を作成することもできます。

+0

徹底的な対応をいただきありがとうございます。クイックフォローアップ、私の目標は、log4netのIsDebugEnabledなどと同様のプロパティを実装することです。このカスタムSourceLevelフィルタは、このタイプのものを動作させる唯一の方法ですか、それともShouldLogを避ける方法ですか?ロギングの前に現在のログレベルをチェックするのは、すぐに使用できるシナリオであるはずです。 – knms

+0

@knms:複数のカテゴリを使用する予定があるかどうか聞かせてください。例えば。データレイヤー、UI、パフォーマンスなど –

+0

これは社内のチームによって使用される汎用のログラッパーであるため、複数のカテゴリを活用するかどうかは予測できません。ログレベルを示すカテゴリを使用することをお勧めしますか? – knms

関連する問題