Pregunta

Envolví Log4net en un contenedor estático y quiero registrarme

loggingEvent.LocationInformation.MethodName
loggingEvent.LocationInformation.ClassName

Sin embargo, todo lo que obtengo es el nombre de mi envoltorio.

¿Cómo puedo registrar esa información usando un forwardingappender y una clase de envoltura estática como

Logger.Debug("Logging to Debug");
Logger.Info("Logging to Info");
Logger.Warn("Logging to Warn");
Logger.Error(ex);
Logger.Fatal(ex);
¿Fue útil?

Solución 2

Bueno, el error estaba en alguna parte de mi appender pero, para completar, incluiré la respuesta a mi mejor saber y entender:

La fachada que necesitas debe envolver ILogger y NO 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);
        }
    }

Otros consejos

¿Qué pasa con las variables % M y % C ? http: //logging.apache. org / log4net / log4net-1.2.11 / release / sdk / log4net.Layout.PatternLayout.html

Uso, algo como:

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

¿No hace eso lo que buscas?

Simplemente declare su variable de registro como esta ...

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

Entonces puedes usarlo normalmente.

Esta publicación me ayudó a descubrir cómo escribir mi propio envoltorio, así que a cambio, pensé que le gustaría que mi clase completa envuelva el registrador, que parece funcionar bastante bien y en realidad toma casi la mitad de tiempo que usar un ILog directamente. !

Todo lo que se requiere es el xml apropiado para configurar el registro en el archivo de configuración y

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

en tu AssemblyInfo.cs y debería funcionar fácilmente.

Una nota: estoy usando Log4NetDash con una configuración realmente simple, así que hice trampa y puse algo de información en los campos incorrectos (por ejemplo, seguimiento de la pila en el campo Dominio), esto todavía funciona para mí ya que no me importa dónde la información se muestra, pero es posible que desee arreglar esto si está configurando las cosas correctamente si le dedica tiempo.

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; }
        }
    }
}

Simplemente usaría algo como % stacktrace {2} como patrón de conversión.

Ejemplo de salida:

  

MyNamespace.ClassName.Method > Common.Log.Warning

donde MyNamespace.ClassName.Method es un método que llama a mi contenedor y Common.Log.Warning es un método de la clase de contenedor.

Los patrones de conversión se pueden encontrar aquí .

Lo único que puedo pensar en hacer (ya que actualmente no uso log4net) es solicitar un stacktrace (nuevo StackTrace), y retroceder un marco para obtener la información que necesita. Sin embargo, no estoy seguro del impacto en el tiempo de ejecución de esto.

Simplemente escribiré más código de la respuesta correcta de Claus

  

En la clase contenedora

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);
      }
  }

y así sucesivamente para el resto de métodos.

  

en web.config o app.config log4net.Layout.PatternLayout   puede utilizar algunos patrones de conversión como:

%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>

Haga clic en aquí para obtener información sobre cómo implementar log4net en .NET Core 2.2

Los siguientes pasos se toman del enlace anterior y desglosan cómo agregar log4net a un proyecto .NET Core 2.2.

Primero, ejecute el siguiente comando en la consola de Package-Manager:

Install-Package Log4Net_Logging -Version 1.0.0

Luego agregue un log4net.config con la siguiente información (edítelo para que coincida con su configuración):

<?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>

Luego, agregue el siguiente código a un controlador (este es un ejemplo, edítelo antes de agregarlo a su controlador):

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" };
}

Luego, llame a la acción del controlador correspondiente (utilizando el ejemplo anterior, llame a / Values ??/ Get con un HTTP GET), y recibirá una salida que coincide con lo siguiente:

  

2019-06-05 19: 58: 45,103 [9] INFO- [Log4NetLogging_Project.Controllers.ValuesController.Get: 23] - Esto es el registro de información

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top