包装Log4net时如何记录MethodName?
时间:2020-03-06 14:58:21 来源:igfitidea点击:
我已经将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);
解决方案
我唯一想做的事情(因为我目前不使用log4net)是请求stacktrace(new StackTrace),然后返回一个框架以获取所需的信息。但是,我不确定这对运行时性能的影响。
嗯,错误发生在我的添加程序中,但是出于完整性方面的考虑,请提供我所知的答案:
我们需要的外观应包装ILogger而不是ILog
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); } }
只需像这样声明日志变量...
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; } } } }
那%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>
那不是在做什么吗?