Log4netをラップするときにMethodNameを記録する方法は?
質問
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);
解決 2
まあ、エラーはアペンダーのどこかにありましたが、完全を期すために、私の知る限りの答えを含めてください:
必要なファサードは、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);
}
}
他のヒント
%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>
それはあなたが望んでいることをしないのですか?
このようにログ変数を宣言するだけ...
private static readonly log4net.ILog log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
その後、通常どおり使用できます。
この投稿は、私自身のラッパーを作成する方法を考え出したので、見返りに、私の完全なクラスがロガーをラップして、非常にうまく動作し、実際にILogを直接使用するのに比べて半分以上の時間がかかると思うかもしれません!
必要なのは、設定ファイルでログを設定するための適切なxmlと
[assembly: log4net.Config.XmlConfigurator(Watch = true)]
AssemblyInfo.csで簡単に機能するはずです。
注:Log4NetDashを非常にシンプルなセットアップで使用しているため、不正なフィールドにいくつかの情報(たとえば、Domainフィールドのスタックトレース)をごまかしましたが、どこでもかまいません。情報は表示されますが、時間を空けて適切に設定している場合はこれを修正することをお勧めします!
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; }
}
}
}
変換パターンとして%stacktrace {2}
のようなものを使用するだけです。
出力の例:
MyNamespace.ClassName.Method&gt; Common.Log.Warning
MyNamespace.ClassName.Method
はラッパーを呼び出すメソッドで、 Common.Log.Warning
はラッパークラスのメソッドです。
変換パターンは、こちらで見つけることができます。
私がやろうと思うことができるのは(現在log4netを使用していないため)、stacktrace(new StackTrace)を要求し、必要な情報を取得するためにフレームに戻ります。ただし、この実行時のパフォーマンスへの影響は不明です。
条項の正解のコードをもっと書くだけ
ラッパークラス内
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>
実装方法については、こちらをクリックしてください.NET Core 2.2のlog4net
上記のリンクから次の手順を実行し、log4netを.NET Core 2.2プロジェクトに追加する方法を分類します。
まず、パッケージマネージャーコンソールで次のコマンドを実行します。
Install-Package Log4Net_Logging -Version 1.0.0
次に、次の情報を含むlog4net.configを追加します(設定に合わせて編集してください):
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<configSections>
<section name="log4net" type="log4net.Config.Log4NetConfigurationSectionHandler, log4net" />
</configSections>
<log4net>
<appender name="FileAppender" type="log4net.Appender.FileAppender">
<file value="logfile.log" />
<appendToFile value="true" />
<layout type="log4net.Layout.PatternLayout">
<conversionPattern value="%d [%t] %-5p - %m%n" />
</layout>
</appender>
<root>
<!--LogLevel: OFF, FATAL, ERROR, WARN, INFO, DEBUG, ALL -->
<level value="ALL" />
<appender-ref ref="FileAppender" />
</root>
</log4net>
</configuration>
次に、次のコードをコントローラーに追加します(これは一例です。コントローラーに追加する前に編集してください):
public ValuesController()
{
LogFourNet.SetUp(Assembly.GetEntryAssembly(), "log4net.config");
}
// GET api/values
[HttpGet]
public ActionResult<IEnumerable<string>> Get()
{
LogFourNet.Info(this, "This is Info logging");
LogFourNet.Debug(this, "This is Debug logging");
LogFourNet.Error(this, "This is Error logging");
return new string[] { "value1", "value2" };
}
次に、関連するコントローラーアクションを呼び出し(上記の例を使用して、HTTP GETで / Values / Get
を呼び出す)、次の内容に一致する出力を受け取ります。
2019-06-05 19:58:45,103 [9] INFO- [Log4NetLogging_Project.Controllers.ValuesController.Get:23]-これは情報ロギングです