代码之家  ›  专栏  ›  技术社区  ›  kyle

c#log4net扩展错误的行和位置

  •  1
  • kyle  · 技术社区  · 11 年前

    当我在PatternLayout中使用%l或%l进行调试时,我得到的是扩展静态类的位置和该文件中的行号,而不是调用者的位置和行。任何标准测井方法都能产生正确的结果。有没有一种方法可以让扩展方法做到这一点?

    Log4NetExtensions.cs的一部分

    namespace Dashboard
    {
        public static partial class Util
        {
            public static void SqlError(this ILog log, SqlException sqle)
            {
                 if (log.IsDebugEnabled)
                {
                    string[] names = Enum.GetNames(typeof(Dashboard.Models.Response.DashError.StandardErrors));
                    int idx = Array.IndexOf(names, sqle.Message);
                    if (idx > 0)
                    {
                        log.Debug(sqle.Message);
                    }
                    else
                    {
                        log.Error(sqle);
                    }
                }
                else
                {
                    log.Error(sqle);
                }
            }
        }
    }
    

    编辑: 根据wageoghe的回答,我将log.Error()和log.Debug更改为这个,但它仍然打印Util而不是调用者:

    log.Logger.Log(typeof(Util), Level.Error, sqle.Message, sqle);
    
    1 回复  |  直到 11 年前
        1
  •  1
  •   Community CDub    7 年前

    关于如何在包装log4net时维护呼叫站点信息,请参阅SO上另一个问题的答案。

    how to log method name when using wrapper class with Log4net

    即使您正在编写一个扩展方法,但实际上还是在包装log4net。该答案中描述的技术应该适用于扩展方法,也适用于包装器。您的解决方案应该是在包装器中使用Log方法,而不是Info、Error等。作为Log方法的第一个参数,发送扩展方法静态类的类型。

    您的扩展方法将如下所示(未编译或测试):

    namespace Dashboard
    {
        public static partial class Util
        {
            public static void SqlError(this ILog log, SqlException sqle)
            {
                 if (log.IsDebugEnabled)
                {
                    string[] names = Enum.GetNames(typeof(Dashboard.Models.Response.DashError.StandardErrors));
                    int idx = Array.IndexOf(names, sqle.Message);
                    if (idx > 0)
                    {
                        //Note that I am using the Logger member and then calling the Log method it.
                        log.Logger.Log(typeof(Util), LogLevel.Debug, sqle.Message, null);
                    }
                    else
                    {
                        //Not sure about this call because you want to log only the exception.  Don't
                        //know if log4net will accept null as "message" parameter.
                        log.Logger.Log(typeof(Util), LogLevel.Error, null, sqle);
                    }
                }
                else
                {
                    //Not sure about this call because you want to log only the exception.  Don't
                    //know if log4net will accept null as "message" parameter.
                    log.Logger.Log(typeof(Util), LogLevel.Error, null, sqle);
                }
            }
        }
    }
    

    如果不完全正确,我想你会明白的。

    更新

    FWIW,我把这个小样本放在一起,它使用扩展方法为调用站点记录所需的方法(Main):

      class Program
      {
        static void Main(string[] args)
        {
          var logger = LogManager.GetLogger("abc");
          ILogger ilog = logger.Logger;
    
          logger.Info("Hello");
          logger.InfoExt("Hello2");
        }
      }
    
      public static class Extensions
      {
        public static void InfoExt(this ILog logger, string message)
        {
          logger.Logger.Log(typeof(Extensions), Level.Info, message, null);
        }
      }