Как войти в систему MethodName при переносе Log4net? - PullRequest
26 голосов
/ 01 октября 2008

Я завернул 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);

Ответы [ 9 ]

26 голосов
/ 15 августа 2010

А как насчет переменных %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>

Разве это не делает то, что вы ищете?

24 голосов
/ 01 октября 2008

Ну, ошибка была где-то в моем 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);
        }
    }
7 голосов
/ 01 октября 2008

Просто объявите свою переменную журнала следующим образом ...

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

Тогда вы можете использовать его как обычно.

4 голосов
/ 08 января 2010

Этот пост помог мне разобраться, как написать свою собственную обертку, взамен подумав, что вам может понравиться мой полный класс, чтобы обернуть регистратор, который, кажется, работает довольно хорошо и на самом деле занимает чуть больше половины времени, чем непосредственное использование ILog !

Все, что требуется, - это соответствующий XML для настройки регистрации в файле конфигурации и

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

в вашем AssemblyInfo.cs, и он должен работать легко.

Одно примечание: я использую 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; }
        }
    }
}
3 голосов
/ 05 мая 2015

Я бы просто использовал что-то вроде %stacktrace{2} в качестве шаблона преобразования.

Пример вывода:

MyNamespace.ClassName.Method> Common.Log.Warning

где MyNamespace.ClassName.Method - это метод, вызывающий мою оболочку, а Common.Log.Warning - метод класса оболочки.

Шаблоны конверсии можно найти здесь .

1 голос
/ 11 июня 2014

Как насчет функции звонящего в C # 4.5 - http://msdn.microsoft.com/en-us/library/system.runtime.compilerservices.callermembernameattribute.aspx

0 голосов
/ 05 июня 2019

Нажмите здесь , чтобы узнать, как реализовать log4net в .NET Core 2.2

Следующие шаги взяты из приведенной выше ссылки и описывают, как добавить 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" };
}

Затем вызовите соответствующее действие контроллера (используя приведенный выше пример, вызовите /Values/Get с HTTP GET), и вы получите вывод, соответствующий следующему:

2019-06-05 19: 58: 45,103 [9] INFO- [Log4NetLogging_Project.Controllers.ValuesController.Get: 23] - это запись информации

0 голосов
/ 17 ноября 2015

Я просто напишу больше кода правильного ответа Клауса

В классе обёрток

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>
0 голосов
/ 01 октября 2008

Единственное, о чем я могу подумать (поскольку я в настоящее время не использую log4net), это запросить трассировку стека (новый StackTrace) и вернуться назад к кадру, чтобы получить необходимую информацию. Однако я не уверен в том, как это повлияет на производительность во время выполнения.

...