web-dev-qa-db-ja.com

Dependency Injectionでlog4netを使用する方法

依存関係注入フレームワークでのlog4netの適切なパターンと使用法を理解しようとしています。

Log4NetはILogインターフェースを使用していますが、呼び出す必要があります

LogManager.GetLogger(Reflection.MethodBase.GetCurrentMethod().DeclaringType)

情報をログに記録する必要がある各クラスまたはメソッド。これはIoCの原則に反するようで、Log4Netを使用することにつながります。

どういうわけかどこかに抽象化の別のレイヤーを入れるべきでしょうか?

また、現在のユーザー名のようなカスタムプロパティを次のようにログに記録する必要があります。

log4net.ThreadContext.Properties["userName"] = ApplicationCache.CurrentUserName;

これをカプセル化して、毎回それを行うことを覚えておく必要がなく、ロギングしている現在のメソッドを維持する方法を教えてください。私はこのようなことをするべきですか、それとも完全にマークを逃していますか?

public static class Logger
{
    public static void LogException(Type declaringType, string message, Exception ex)
    {
        log4net.ThreadContext.Properties["userName"] = ApplicationCache.CurrentUserName;
        ILog log = LogManager.GetLogger(declaringType);
        log.Error(message, ex);
    }
}
76
Micah

ここの木々の森は見えていないと思います。 ILogとLogManagerは、Apache commons-loggingとほぼ1:1で軽量のファサードであり、実際にコードをlog4netの残りの部分に結合しません。

_<rant>_
私はまた、ほとんど常に誰かがlog4netの周りにMyCompanyLoggerラッパーを作成すると、彼らはポイントをひどく失い、重要性を失い、フレームワークの有用な機能、有用な情報の破棄、簡略化されたILogインターフェース、または上記のすべてを使用しても可能なパフォーマンスの向上が失われます。言い換えると、-log4netをラップしてそれに結合しないようにすることはアンチパターンですです。
_</rant>_

インジェクトする必要があると思われる場合は、プロパティを介してロガーインスタンスにアクセスできるようにして、インジェクションを有効にしますが、デフォルトのインスタンスを昔ながらの方法で作成します。

すべてのログメッセージにコンテキストの状態を含める場合は、ToString()が目的のものに解決されるグローバルプロパティを追加する必要があります。例として、現在のヒープサイズの場合:

_public class TotalMemoryProperty
{
    public override string ToString()
    {
        return GC.GetTotalMemory(false).ToString();
    }
}
_

次に、起動時にプラグインするには:

_GlobalContext.Properties["TotalMemory"] = new TotalMemoryProperty();
_
62
Jeffrey Hantin

私がやった方法は、自分のインターフェースを作成することであり、Log4Netを使用するインターフェースを実装するクラスを用意し、そのクラスに注入しました。そのようにして、Log4Netに縛られることはありません...新しいロガー用に別のクラスを作成し、そのクラスを注入するだけです。

2
CSharpAtl

複数のロガーがあることを本当に心配している場合は、いつでもグローバルロガーを宣言して、すべてのロギングニーズに対してそれを呼び出すことができます。これの欠点は、ログの発行元のクラスを識別する組み込み機能が失われることですが、独自のカスタムメッセージをログに挿入してクラスを識別することもできます。

ロギングをどの程度堅牢にしたいかによります。また、ロガーをメインクラスに配置して、すべての未処理の例外をログに記録することもできます。

2
Dillie-O

これを行う別の方法は、次のようにlog4net ILogインターフェイスコンテナー登録シーケンスを結び付けることです(例として、以下のASP.NETコンテキストでCastleを使用)。

container.Register(Component.For<ILog>().LifeStyle
    .PerWebRequest.UsingFactoryMethod(() => LogManager.GetLogger(
    MethodBase.GetCurrentMethod().DeclaringType)));

必要なときはいつでも、コンストラクター注入ILogを使用します。

2
santos