Domanda

Ho avvolto Log4net in un wrapper statico e voglio accedere

loggingEvent.LocationInformation.MethodName
loggingEvent.LocationInformation.ClassName

Comunque tutto ciò che ottengo è il nome del mio wrapper.

Come posso registrare queste informazioni usando un forwardingappender e una classe di wrapper statico come

Logger.Debug("Logging to Debug");
Logger.Info("Logging to Info");
Logger.Warn("Logging to Warn");
Logger.Error(ex);
Logger.Fatal(ex);
È stato utile?

Soluzione 2

Beh, l'errore era da qualche parte nella mia appender, ma per completezza includo la risposta al meglio delle mie conoscenze:

la facciata di cui hai bisogno dovrebbe avvolgere ILogger e NON 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);
        }
    }

Altri suggerimenti

Che dire delle variabili % M e % C ? http: //logging.apache. org / log4net / log4net-1.2.11 / rilascio / sdk / log4net.Layout.PatternLayout.html

Utilizzo, qualcosa del tipo:

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

Non fa quello che cerchi?

Dichiara semplicemente la tua variabile di registro in questo modo ...

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

Quindi puoi usarlo normalmente.

Questo post mi ha aiutato a capire come scrivere il mio wrapper così in cambio, ho pensato che ti sarebbe piaciuta la mia classe completa per avvolgere il logger che sembra funzionare abbastanza bene e in realtà impiega poco più della metà del tempo che usando un ILog direttamente !

Tutto ciò che serve è l'xml appropriato per impostare la registrazione nel file di configurazione e

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

in AssemblyInfo.cs e dovrebbe funzionare facilmente.

Una nota: sto usando Log4NetDash con una configurazione davvero semplice, quindi ho barato e messo alcune informazioni nei campi sbagliati (ad es. stack stack nel campo Dominio), questo funziona ancora per me poiché non mi interessa dove le informazioni sono mostrate ma potresti voler risolvere questo problema se stai sistemando le cose correttamente se risparmi tempo!

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

Userei semplicemente qualcosa come % stacktrace {2} come modello di conversione.

Esempio di output:

  

MyNamespace.ClassName.Method > Common.Log.Warning

dove MyNamespace.ClassName.Method è un metodo che chiama il mio wrapper e Common.Log.Warning è un metodo della classe wrapper.

I modelli di conversione sono disponibili qui .

L'unica cosa che mi viene in mente di fare (poiché attualmente non utilizzo log4net) è richiedere uno stacktrace (nuovo StackTrace) e tornare indietro di un frame per ottenere le informazioni necessarie. Tuttavia, non sono sicuro dell'impatto delle prestazioni di runtime di questo.

Scriverò solo più codice della risposta corretta di Claus

  

Nella classe wrapper

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

e così via per il resto dei metodi.

  

in web.config o app.config log4net.Layout.PatternLayout   puoi utilizzare alcuni schemi di conversione come:

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

Fai clic su qui per informazioni su come implementare log4net in .NET Core 2.2

I seguenti passaggi sono presi dal link sopra e spiegano come aggiungere log4net a un progetto .NET Core 2.2.

Innanzitutto, esegui il seguente comando nella console di Package-Manager:

Install-Package Log4Net_Logging -Version 1.0.0

Quindi aggiungi un log4net.config con le seguenti informazioni (modificalo per adattarlo al tuo set up):

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

Quindi, aggiungi il seguente codice in un controller (questo è un esempio, modificalo prima di aggiungerlo al tuo controller):

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

Quindi chiama l'azione del controller pertinente (usando l'esempio sopra, chiama / Values ??/ Get con un HTTP GET), e riceverai l'output corrispondente al seguente:

  

19/06/2019 19: 58: 45,103 [9] INFO- [Log4NetLogging_Project.Controllers.ValuesController.Get: 23] - Questa è la registrazione delle informazioni

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top