56

私は .net (c#) のロギング フレームワークを探していましたが、stackoverflow のいくつかの質問/回答スレッドを読んだ後、log4net を試してみることにしました。log4netのラッパークラスを使用していると何度も言及している人を見かけますが、それがどのようになるのか疑問に思っています。

コードをさまざまなプロジェクト (データ アクセス/ビジネス/Web サービス/..) に分割しています。log4net ラッパー クラスはどのようになりますか? すべてのプロジェクトにラッパー クラスを含める必要がありますか? 別のプロジェクトとしてまとめてビルドする必要がありますか?

ラッパーはシングルトン クラスにする必要がありますか?

4

9 に答える 9

54

基本的に、インターフェースを作成してから、Log4net のクラスとメソッドを直接ラップするそのインターフェースの具体的な実装を作成します。追加のロギング システムは、それらのシステムの他のクラスとメソッドをラップするより具体的なクラスを作成することでラップできます。最後に、ファクトリを使用して、構成設定またはコード行の変更に基づいてラッパーのインスタンスを作成します。(注: StructureMapなどのInversion of Controlコンテナーを使用すると、より柔軟かつ複雑にすることができます。)

public interface ILogger
{
    void Debug(object message);
    bool IsDebugEnabled { get; }

    // continue for all methods like Error, Fatal ...
}

public class Log4NetWrapper : ILogger
{
    private readonly log4net.ILog _logger;

    public Log4NetWrapper(Type type)
    {
        _logger = log4net.LogManager.GetLogger(type);
    }

    public void Debug(object message)
    {
        _logger.Debug(message);
    }

    public bool IsDebugEnabled
    {
        get { return _logger.IsDebugEnabled; }
    }

    // complete ILogger interface implementation
}

public static class LogManager
{
    public static ILogger GetLogger(Type type)
    {
        // if configuration file says log4net...
        return new Log4NetWrapper(type);
        // if it says Joe's Logger...
        // return new JoesLoggerWrapper(type);
    }
}

クラスでこのコードを使用する例 (静的読み取り専用フィールドとして宣言):

private static readonly ILogger _logger =
    LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);

以下を使用して、同じようにわずかにパフォーマンスに適した効果を得ることができます。

private static readonly ILogger _logger = 
    LogManager.GetLogger(typeof(YourTypeName));

前者の例は、より保守しやすいと考えられています。

Log4Net は呼び出しタイプのログを記録するため、すべてのロギングを処理するシングルトンを作成することは望ましくありません。すべてのメッセージを報告するログ ファイル内の単一のタイプを確認するだけでなく、各タイプで独自のロガーを使用する方が、はるかにクリーンで便利です。

実装はかなり再利用可能 (組織内の他のプロジェクト) である必要があるため、それを独自のアセンブリにするか、理想的には自分の個人/組織のフレームワーク/ユーティリティ アセンブリに含めることができます。各ビジネス/データ/UI アセンブリで個別にクラスを再宣言しないでください。これは維持できません。

于 2008-10-03T11:49:54.603 に答える
26

上記のcfedukeの回答のようなものを使用していると仮定すると、次のようにオーバーロードを追加することもできますLogManager

public static ILogger GetLogger()
{
    var stack = new StackTrace();
    var frame = stack.GetFrame(1);
    return new Log4NetWrapper(frame.GetMethod().DeclaringType);
}

そうすれば、コードで次のように使用できます。

private static readonly ILogger _logger = LogManager.GetLogger();

これらのいずれかの代わりに:

private static readonly ILogger _logger =
    LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
private static readonly ILogger _logger = 
    LogManager.GetLogger(typeof(YourTypeName));

これは、最初の選択肢(つまり、を使用するものMethodBase.GetCurrentMethod().DeclaringType)と実質的に同等ですが、少しだけ単純です。

于 2009-02-26T02:52:23.027 に答える
5

log4netのラッパーを書くことから抜け出すことを計画している利点は何ですか? ラッパーを作成する前に、まず log4net クラスに慣れることをお勧めします。cfeduke は、前述のラッパーの書き方に関する彼の回答で正しいですが、彼の例に実際の機能を追加する必要がない限り、ラッパーはログ記録プロセスを遅くし、将来のメンテナーにとって複雑さを追加することにしか成功しません。これは、.Net で使用できるリファクタリング ツールによってこのような変更が非常に簡単になる場合に特に当てはまります。

于 2008-10-03T12:30:30.387 に答える
0

Alconja さん、スタックトレースを使用して呼び出し元のメソッドに戻るというあなたのアイデアが気に入っています。ロガーオブジェクトを取得するだけでなく、実際にログを実行するために、呼び出しをさらにカプセル化することを考えていました。私が欲しいのは、使用されている特定の実装から抽象化することにより、ロギングを処理する静的クラスです。いえ

LoggingService.LogError("my error message");

そうすれば、後で別のロギング システムを使用することにした場合に、静的クラスの内部を変更するだけで済みます。

だから私はスタックトレースを使用して呼び出し元のオブジェクトを取得するためにあなたのアイデアを使用しました:

public static class LoggingService
{
    private static ILog GetLogger()
    {    
        var stack = new StackTrace();    
        var frame = stack.GetFrame(2);    
        return log4net.LogManager.GetLogger(frame.GetMethod().DeclaringType);
    }

    public static void LogError(string message)
    {
        ILog logger = GetLogger();
        if (logger.IsErrorEnabled)
            logger.Error(message);
    }
    ...
}

このアプローチに問題がある人はいますか?

于 2009-08-17T09:02:38.963 に答える
0

私の理解では、log4net のラッパー クラスは、app.config/web.config またはコード (NUnit との統合など) からログ オブジェクトを初期化する静的クラスになります。

于 2008-10-03T11:45:47.873 に答える
0

log4netラッパーの可能な用途は、リフレクションを介して呼び出し元のクラスとメソッドを取得し、ログエントリが発生した場所を把握するクラスです。少なくとも私はこれを頻繁に使用します。

于 2008-10-03T11:45:49.743 に答える
-3

この答えが遅れていることは知っていますが、将来誰かを助けるかもしれません。

XQuiSoft Logging が提供するプログラム API が必要なようです。XQuiSoft で必要なロガーを指定する必要はありません。これは次のように簡単です。

Log.Write(Level.Verbose, "source", "category", "メッセージはこちら");

次に、構成を介して、ソース、カテゴリ、レベル、またはその他のカスタム フィルターによってメッセージを別の場所 (ファイル、電子メールなど) に送信します。

紹介はこちらの記事をご覧ください。

于 2010-12-06T19:39:20.817 に答える