34

Log4net を静的ラッパーでラップしており、ログを記録したい

loggingEvent.LocationInformation.MethodName
loggingEvent.LocationInformation.ClassName

ただし、取得できるのはラッパーの名前だけです。

forwardingappender と次のような静的ラッパー クラスを使用してその情報をログに記録するにはどうすればよいですか

Logger.Debug("Logging to Debug");
Logger.Info("Logging to Info");
Logger.Warn("Logging to Warn");
Logger.Error(ex);
Logger.Fatal(ex);
4

10 に答える 10

30

%M%C変数 はどうですか?http://logging.apache.org/log4net/log4net-1.2.11/release/sdk/log4net.Layout.PatternLayout.html

使用法、次のようなもの:

<layout type="log4net.Layout.PatternLayout">
  <conversionPattern value="%date [%thread] %-5level %logger [%M %C] - %message%newline" />
</layout>

それはあなたが求めていることではありませんか?

于 2010-08-15T19:19:34.630 に答える
29

エラーは私の付録のどこかにありましたが、完全を期すために、私の知る限りの答えを含めてください。

必要なファサードは、ILogではなくILoggerをラップする必要があります

 public static class Logger
 {
    private readonly static Type ThisDeclaringType = typeof(Logger);
    private static readonly ILogger defaultLogger;

    static Logger()
    {
      defaultLogger =
        LoggerManager.GetLogger(Assembly.GetCallingAssembly(),"MyDefaultLoggger");

..。

    public static void Info(string message)
    {
        if (defaultLogger.IsEnabledFor(infoLevel))
        {
            defaultLogger.Log(typeof(Logger), infoLevel, message, null);
        }
    }
于 2008-10-01T14:28:50.223 に答える
5

このようにログ変数を宣言するだけです...

private static readonly log4net.ILog log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);

その後、通常どおりに使用できます。

于 2008-10-01T14:30:32.343 に答える
4

この投稿は、独自のラッパーを作成する方法を理解するのに役立ちました。その見返りに、私の完全なクラスでロガーをラップすることをお勧めします。これは非常にうまく機能しているように見え、実際には ILog を直接使用する場合の半分以上の時間がかかります!

必要なのは、構成ファイルでログを設定するための適切な xml だけです。

[assembly: log4net.Config.XmlConfigurator(Watch = true)] 

AssemblyInfo.cs で簡単に動作するはずです。

1 つのメモ: 私は非常に単純なセットアップで Log4NetDash を使用しているので、だまされて間違ったフィールド (ドメイン フィールドのスタック トレースなど) にいくつかの情報を入力しましたが、情報がどこにあるかは気にしないので、これはまだ機能します示されていますが、時間があれば適切に設定している場合は、これを修正することをお勧めします!

using System;
using System.ComponentModel;
using System.Diagnostics;
using System.Reflection;
using System.Threading;
using log4net;
using log4net.Core;

namespace Utility
{
    public class Logger
    {
        static Logger()
        {
            LogManager.GetLogger(typeof(Logger));
        }

        public static void Debug(string message, params object[] parameters)
        {
            Log(message, Level.Debug, null, parameters);
        }

        public static void Info(string message, params object[] parameters)
        {
            Log(message, Level.Info, null, parameters);
        }

        public static void Warn(string message, params object[] parameters)
        {
            Log(message, Level.Warn, null, parameters);
        }

        public static void Error(string message, params object[] parameters)
        {
            Error(message, null, parameters);
        }

        public static void Error(Exception exception)
        {
            if (exception==null)
                return;
            Error(exception.Message, exception);
        }

        public static void Error(string message, Exception exception, params object[] parameters)
        {
            string exceptionStack = "";

            if (exception != null)
            {
                exceptionStack = exception.GetType().Name + " : " + exception.Message + Environment.NewLine;
                Exception loopException = exception;
                while (loopException.InnerException != null)
                {
                    loopException = loopException.InnerException;
                    exceptionStack += loopException.GetType().Name + " : " + loopException.Message + Environment.NewLine;
                }
            }

            Log(message, Level.Error, exceptionStack, parameters);
        }



        private static void Log(string message, Level logLevel, string exceptionMessage, params object[] parameters)
        {
            BackgroundWorker worker = new BackgroundWorker();
            worker.DoWork += LogEvent;
            worker.RunWorkerAsync(new LogMessageSpec
                                      {
                                          ExceptionMessage = exceptionMessage,
                                          LogLevel = logLevel,
                                          Message = message,
                                          Parameters = parameters,
                                          Stack = new StackTrace(),
                                          LogTime = DateTime.Now
                                      });
        }

        private static void LogEvent(object sender, DoWorkEventArgs e)
        {
            try
            {
                LogMessageSpec messageSpec = (LogMessageSpec) e.Argument;

                StackFrame frame = messageSpec.Stack.GetFrame(2);
                MethodBase method = frame.GetMethod();
                Type reflectedType = method.ReflectedType;

                ILogger log = LoggerManager.GetLogger(reflectedType.Assembly, reflectedType);
                Level currenLoggingLevel = ((log4net.Repository.Hierarchy.Logger) log).Parent.Level;

                if (messageSpec.LogLevel<currenLoggingLevel)
                    return;

                messageSpec.Message = string.Format(messageSpec.Message, messageSpec.Parameters);
                string stackTrace = "";
                StackFrame[] frames = messageSpec.Stack.GetFrames();
                if (frames != null)
                {
                    foreach (StackFrame tempFrame in frames)
                    {

                        MethodBase tempMethod = tempFrame.GetMethod();
                        stackTrace += tempMethod.Name + Environment.NewLine;
                    }
                }
                string userName = Thread.CurrentPrincipal.Identity.Name;
                LoggingEventData evdat = new LoggingEventData
                                             {
                                                 Domain = stackTrace,
                                                 Identity = userName,
                                                 Level = messageSpec.LogLevel,
                                                 LocationInfo = new LocationInfo(reflectedType.FullName,
                                                                                 method.Name,
                                                                                 frame.GetFileName(),
                                                                                 frame.GetFileLineNumber().ToString()),
                                                 LoggerName = reflectedType.Name,
                                                 Message = messageSpec.Message,
                                                 TimeStamp = messageSpec.LogTime,
                                                 UserName = userName,
                                                 ExceptionString = messageSpec.ExceptionMessage
                                             };
                log.Log(new LoggingEvent(evdat));
            }
            catch (Exception)
            {}//don't throw exceptions on background thread especially about logging!
        }

        private class LogMessageSpec
        {
            public StackTrace Stack { get; set; }
            public string Message { get; set; }
            public Level LogLevel { get; set; }
            public string ExceptionMessage { get; set; }
            public object[] Parameters { get; set; }
            public DateTime LogTime { get; set; }
        }
    }
}
于 2010-01-08T12:31:19.823 に答える
2

これに対して次のソリューションを実装しました (.Net Framework 4.5+): log4net ラッパー メソッド (Info、Warn、Error など) は、CallerMemberName と CallerFilePath を使用して、ログが存在する場所からコードのクラスとメソッド名を取得できます。呼ばれた。次に、これらをカスタム log4net プロパティに集約できます。

log4net 独自のラッパー実装を自由に使用してください。ここで重要なのは、Info メソッドと Error メソッドのシグネチャ、および GetLogger メソッドの実装だけです。

「memberName」および「sourceFilePath」引数は、Logger.Info または Logger.Error メソッドを呼び出すときに指定しないでください。.Net によって自動入力されます。

public static class Logger
{
    private class LogSingletonWrapper
    {
        public ILog Log { get; set; }
        public LogSingletonWrapper()
        {
            Log = LogManager.GetLogger(GetType());
        }
    }

    private static readonly Lazy<LogSingletonWrapper> _logger = new Lazy<LogSingletonWrapper>();

    public static void Info(string message, [CallerMemberName] string memberName = "", [CallerFilePath] string sourceFilePath = "") 
        => GetLogger(memberName, sourceFilePath).Info(message);
    
    public static void Error(string message,Exception ex, [CallerMemberName] string memberName = "", [CallerFilePath] string sourceFilePath = "") 
        => GetLogger(memberName, sourceFilePath).Error(message, ex);

    private static ILog GetLogger(string memberName, string sourceFilePath)
    {
        var classname = sourceFilePath.Split('\\').Last().Split('.').First();
        log4net.ThreadContext.Properties["Source"] = $"{classname}.{memberName.Replace(".", "")}";
        return _logger.Value.Log;
    }
}

次に、.config ファイルで次のようなログ変換パターンを使用できます。

<conversionPattern value="[%level][%date][Thd%thread: %property{Source}][Message: %message]%newline" />

これにより、ログは次のようになります。

[情報][2019-07-03 16:42:00,936][Thd1: Application.Start][メッセージ: アプリケーションを起動しています ...]

[エラー][2019-07-03 16:42:44,145][Thd6: DataProcessor.ProcessDataBatch][メッセージ: ゼロで除算しようとしました。]

上記の例では、Application クラスの Start メソッドと DataProcessor クラスの ProcessDataBatch メソッドが呼び出されました。

于 2019-07-03T16:40:44.957 に答える
2

C#4.5 機能 callerinfo について - http://msdn.microsoft.com/en-us/library/system.runtime.compilerservices.callermembernameattribute.aspx

于 2014-06-11T06:49:32.263 に答える
0

クラウスの正解のコードをもっと書くだけです

ラッパークラスで

public static class Logger
{
   private static readonly ILogger DefaultLogger;

   static Logger()
   {
      defaultLogger = LoggerManager.GetLogger(Assembly.GetCallingAssembly(), "MyDefaultLoggger"); // MyDefaultLoggger is the name of Logger
   }

  public static void LogError(object message)
  {
      Level errorLevel = Level.Error;
      if (DefaultLogger.IsEnabledFor(errorLevel))
      {
          DefaultLogger.Log(typeof(Logger), errorLevel, message, null);
      }
  }

  public static void LogError(object message, Exception exception)
  {
      Level errorLevel = Level.Error;
      if (DefaultLogger.IsEnabledFor(errorLevel))
      {
          DefaultLogger.Log(typeof(Logger), errorLevel, message, exception);
      }
  }

残りのメソッドについても同様です。

web.config またはapp.config log4net.Layout.PatternLayout では 、次のような変換パターンを使用できます。

%location %method %line

<layout type="log4net.Layout.PatternLayout">
    <conversionPattern value="%date{dd/MM/yyyy hh:mm:ss.fff tt} [%thread] %level %logger [%location %method %line] [%C %M] - %newline%message%newline%exception"/>
  </layout>
于 2015-11-16T22:18:53.567 に答える
0

私が考えられる唯一のことは(現在log4netを使用していないため)、スタックトレース(新しいStackTrace)をリクエストし、フレームに戻って必要な情報を取得することです。ただし、これによる実行時のパフォーマンスへの影響については確信が持てません。

于 2008-10-01T11:58:01.617 に答える