How to log MethodName when wrapping Log4net?

后端 未结 10 1681
说谎
说谎 2020-11-29 23:41

I have wrapped Log4net in a static wrapper and want to log

loggingEvent.LocationInformation.MethodName
loggingEvent.LocationInformation.ClassName
         


        
相关标签:
10条回答
  • 2020-11-30 00:36

    Well the error was somewhere in my appender but for completeness ill include the answer to the best of my knowledge:

    the Facade you need should wrap ILogger and NOT 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);
            }
        }
    
    0 讨论(0)
  • 2020-11-30 00:42

    I implemented the following solution for this (.Net framework 4.5+) : the log4net wrapper methods (e.g. Info, Warn, Error) could make use of CallerMemberName and CallerFilePath to fetch the class and method name of the code from where the logs are being called. You can then aggregate these into a custom log4net property.

    Feel free to use your log4net own wrapper implementation, the only important things here are: the signature of the Info and Error methods, and the implementation of the GetLogger method.

    The 'memberName' and 'sourceFilePath' args should never be specified when calling the Logger.Info or Logger.Error methods, they are auto-filled-in by .Net.

    public static class Logger
    {
        private class LogSingletonWrapper
        {
            public ILog Log { get; set; }
            public LogSingletonWrapper()
            {
                Log = LogManager.GetLogger(GetType());
            }
        }
    
        private static readonly Lazy<LogSingletonWrapper> _logger = new Lazy<LogSingletonWrapper>();
    
        public static void Info(string message, [CallerMemberName] string memberName = "", [CallerFilePath] string sourceFilePath = "") 
            => GetLogger(memberName, sourceFilePath).Info(message);
        
        public static void Error(string message,Exception ex, [CallerMemberName] string memberName = "", [CallerFilePath] string sourceFilePath = "") 
            => GetLogger(memberName, sourceFilePath).Error(message, ex);
    
        private static ILog GetLogger(string memberName, string sourceFilePath)
        {
            var classname = sourceFilePath.Split('\\').Last().Split('.').First();
            log4net.ThreadContext.Properties["Source"] = $"{classname}.{memberName.Replace(".", "")}";
            return _logger.Value.Log;
        }
    }
    

    Then you would could use a log conversion pattern like this in your .config file :

    <conversionPattern value="[%level][%date][Thd%thread: %property{Source}][Message: %message]%newline" />
    

    This would result in logs looking like this:

    [INFO][2019-07-03 16:42:00,936][Thd1: Application.Start][Message: The application is starting up ...]

    [ERROR][2019-07-03 16:42:44,145][Thd6: DataProcessor.ProcessDataBatch][Message: Attempted to divide by zero.]

    The following methods were called in the above example: the Start method of the Application class, and the ProcessDataBatch method of the DataProcessor class.

    0 讨论(0)
  • 2020-11-30 00:44

    The only thing I can think of doing (as I dont currently use log4net) is to request a stacktrace(new StackTrace), and go back a frame to get the info you need. However, I am unsure of the runtime performance impact of this.

    0 讨论(0)
  • 2020-11-30 00:45

    Click here to learn how to implement log4net in .NET Core 2.2

    The following steps are taken from the above link, and break down how to add log4net to a .NET Core 2.2 project.

    First, run the following command in the Package-Manager console:

    Install-Package Log4Net_Logging -Version 1.0.0
    

    Then add a log4net.config with the following information (please edit it to match your 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>
    

    Then, add the following code into a controller (this is an example, please edit it before adding it to your 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" };
    }
    

    Then call the relevant controller action (using the above example, call /Values/Get with an HTTP GET), and you will receive the output matching the following:

    2019-06-05 19:58:45,103 [9] INFO-[Log4NetLogging_Project.Controllers.ValuesController.Get:23] - This is Info logging

    0 讨论(0)
提交回复
热议问题