Хорошо ошибка была где-нибудь в моем appender, но для полноты плохо включают ответ насколько я знаю:
Фасад, в котором Вы нуждаетесь, должен обернуть 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);
Тогда можно обычно использовать его.
Единственная вещь я могу думать о выполнении (поскольку я в настоящее время не использую log4net) состоит в том, чтобы запросить stacktrace (новый StackTrace) и возвратиться кадр для получения информации, в которой Вы нуждаетесь. Однако я не уверен во влиянии производительности во время выполнения этого.
Этот пост помог мне разобраться, как написать свою собственную обертку, так что взамен я подумал, что вам, возможно, понравится мой полный класс для обёртывания логгера, который, кажется, работает довольно неплохо и на самом деле занимает чуть больше половины времени, чем непосредственное использование 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>
Разве это не то, что вы после?