AdoNetAppender を使用してデータベースのログを記録しています。私がやりたいのは、各ログ ステートメントにユーザー ID を記録することです。ただし、次の 2 つの理由から、標準の log4net %identity パラメーターを使用したくありません。
- log4net は、コンテキスト ID を検索する必要があるため、非常に遅いと警告しています。
- 一部のサービス コンポーネントでは、標準の ID はサービス アカウントですが、ユーザー ID は既に変数に取り込まれており、それを使用したいと考えています。
一部の人々が log4net.ThreadContext を使用して追加のプロパティを追加するコードを見たことがありますが、スレッドのインターリーブが原因でこれが「安全ではない」ことを理解しています (また、パフォーマンスの低下でもあります)。
私のアプローチは、次のように AdoNetAppenderParameter クラスを拡張することでした。
public class UserAdoNetAppenderParameter : AdoNetAppenderParameter
{
public UserAdoNetAppenderParameter()
{
DbType = DbType.String;
PatternLayout layout = new PatternLayout();
Layout2RawLayoutAdapter converter = new Layout2RawLayoutAdapter(layout);
Layout = converter;
ParameterName = "@username";
Size = 255;
}
public override void Prepare(IDbCommand command)
{
command.Parameters.Add(this);
}
public override void FormatValue(IDbCommand command, LoggingEvent loggingEvent)
{
string[] data = loggingEvent.RenderedMessage.Split('~');
string username = data[0];
command.Parameters["@username"] = username;
}
}
次に、プログラムでこれを現在のアペンダーに次のように追加します。
ILog myLog = LogManager.GetLogger("ConnectionService");
IAppender[] appenders = myLog.Logger.Repository.GetAppenders();
AdoNetAppender appender = (AdoNetAppender)appenders[0];
appender.AddParameter(new UserAdoNetAppenderParameter());
myLog.InfoFormat("{0}~{1}~{2}~{3}", userName, "ClassName", "Class Method", "Message");
ここでの意図は、メッセージに標準形式を使用し、常にユーザー名である必要がある文字列の最初の部分を解析することです。カスタム アペンダー パラメーターの FormatValue() メソッドは、ログ データベースの別のフィールドに書き込むことができるように、文字列のその部分のみを使用する必要があります。
私の問題は、ログ ステートメントがデータベースに書き込まれないことです。奇妙なことに、デバッグ時に FormatValue() メソッドのブレークポイントがヒットするのは、サービスを停止したときだけです。
私はこれに関連する多くのものを調べましたが、まだ答えが見つかりません. 誰かがこれをやったことがありますか、それとも私は間違った道を進んでいますか? PS AdoNetAppender の拡張も試みましたが、パラメーター値を設定するためのアクセス権はありません。