Commons Logging プロジェクト (.NET と Java の両方) がマップされた診断コンテキストまたはネストされた診断コンテキストをサポートしていないという事実を回避するために、他の人は何をしましたか?
4 に答える
エグゼクティブサマリー:
インプリメンタ ロギング フレームワークを直接使用することを選択しました (この場合は log4j)。
長い答え:
要件を満たすために抽象ロギング フレームワークが必要ですか? それらは、最終的にどのようなホスト環境でもうまく機能したいライブラリには最適ですが、アプリケーションを作成している場合は、多くの場合、ロギング フレームワークの実装を直接使用できます (つまり、多くの場合、理由はありません)。アプリケーションの存続期間中にロギングの実装者を変更する必要がある理由)。
インプリメンタ ロギング フレームワークを直接使用することを選択しました (この場合は log4j)。Commons-Logging はクラスパスで利用できますが、それに依存するライブラリのためだけにあります。私たちの場合、これは簡単な選択でした。なぜなら、私が働いている会社は何年も前から log4j を必須の標準として採用しており、変更される可能性は低いからです。 .
- NDC やその他の専門機能がもたらすメリットは何ですか?
- ロギング実装者を変更しなければならない可能性はどのくらいですか? また、変更しなければならない場合のコストは?
そして多分:
- 同時展開で異なるロギング実装者をサポートする必要がありますか?
私たちの場合、ロギングの実装者を変更する必要が生じた場合は、リファクタリングを行う必要がありますが、org.apache.log4j パッケージのすべてを使用すると、リファクタリングは難しくもリスクも高くありません1。log4e Eclipes プラグインは、実際のログ ステートメントを自動的に変換します。すべてのロギング フレームワークがそのようなことをサポートしているわけではないため、NDC オブジェクトが問題になる可能性があります。NDC.enter() および NDC.leave() メソッドをユーティリティ クラス内の独自の制御下に隠すことを検討することもできますが、私たちは気にしませんでした。
1 ) 有名な最後の言葉
これはあなたの質問に対する直接的な回答ではありませんが、Commons Logging 以外のものを使用するオプションはありますか? SLF4J (Simple Logging Facade - http://www.slf4j.org/ ) は、マッピングされた診断コンテキストをサポートしているように見える別のログ抽象化 API です。
個人的に使用したことはありませんが、Commons Logging よりもはるかに優れていると主張しているため、次の主要なプロジェクトで使用することを検討しています。多くの新しい主要なオープン ソース プロジェクトもそれを使用しているようです (Hibernate、Spring モジュール、いくつかの Apache プロジェクト)。
完全を期すために、私は独自の非常に単純な汎用インターフェイスを作成することになりました。
public interface IDiagnosticContextHandler
{
void Set(string name, string value);
}
次に、Log4Net 固有のバージョンを実装しました。
public class Log4NetDiagnosticContextHandler : IDiagnosticContextHandler
{
private readonly Assembly assembly;
private readonly Type mdcType;
public Log4NetDiagnosticContextHandler()
{
this.assembly = Assembly.Load("log4net");
this.mdcType = this.assembly.GetType("log4net.MDC", true);
}
public void Set(string name, string value)
{
this.mdcType.InvokeMember("Set", BindingFlags.InvokeMethod, null, null, new object[] { name, value });
}
}
次に、IoC コンテナー (Spring.Net) を使用して正しい実装を導入しました。後で別のロギング フレームワークが必要になった場合は、IoC 構成を変更するそのインターフェイスの別の実装を作成するだけで済みます。
これは、元の質問および最新の (受け入れられた) 回答に比べて遅れていますが、将来の検索者のために投稿します。
Common.Logging (NET)の Web サイトによると、次のバージョン (現在のバージョンは 2.0) では、まさにこの機能がサポートされる予定です。ただし、このリリースがいつ予定されているかは明らかではありません。2.0 は 2009 年 4 月にリリースされました。Web サイトによると、次のリリースは「6 月」に予定されています。年については言及されていません。2009 年 6 月と 2010 年 6 月が過ぎ去りました。
そうは言っても、少なくとも log4net/NLog の「コンテキスト」抽象化の実装は、Castle プロジェクトの git ソース コード リポジトリに存在します。ここから始めて、ExtendedLog4netLogger、GlobalContextProperties、ThreadContextProperties、ThreadContextStack、および ThreadContextStacks を見て、Castle が NDC と MDC を公開する方法を確認します。同様の実装が Castle for NLog に存在します。
NET の Common.Logging が同様の抽象化を実装する場合、次のように LogManager から返されるロガー インスタンスを介してコンテキスト値を設定できます。
ILog logger = LogManager.GetCurrentClassLogger();
logger.ThreadContextProperties["EventID"] = 123;
logger.GlobalContextPropeties["USER"] = GetUser();
これに加えて、すべてのログ メッセージに設定したい特定のコンテキストがある場合 (たとえば、コードで渡している独自のコンテキストから)、独自の log4net および/または NLog 抽象化を記述して Common にプラグインできます。 .その情報を自動的に入力するためのログ。たとえば、特定の「トランザクション」の情報を追跡するのに役立つ、渡される「コンテキスト」がアプリケーションにあるとします。また、簡単にするために、「MyContext」などの静的クラスを介してアクセスできると仮定します。
WriteInternal (Common.Logging にプラグインするロガーの抽象化を記述するときに実装するもの) は次のようになります (これは NLog 用です。log4net は少し異なる場合があります)。
protected override void WriteInternal(CommonLoggingLogLevel logLevel, object message, Exception exception)
{
LogLevelNLog level = GetLevel(logLevel);
LogEventInfo logEvent = new LogEventInfo(level, _logger.Name, null, "{0}", new object[] { message }, exception);
//Access these context values for output formatting using the event-context:item token
logEvent.Context["ActivityID"] = MyContext.ActivityID;
logEvent.Context["SessionID"] = MyContext.SessionID;
logEvent.Context["TransactionStartTime"] = MyContext.TransactionStartTime;
//Note that you can also set NDC and/or MDC here:
NLog.MDC.Set("SoftwareVersion", MyContext.Version.ToString());
_logger.Log(declaringType, logEvent);
}
あなた (または他の誰か) が Common.Logging (NET) を使用していて、log4net/NLog コンテキスト プロパティを今すぐ公開する必要がある場合は、Castle がロギング抽象化インターフェイスを介してそれらを公開するために行ったことと同様のことを行うことができます。ロギング呼び出し内から取得できる情報を使用してコンテキストを自動的に設定したい場合は、上記で提案したのと同様のことを行うことができます。