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

用log4j包装器在日志语句中打印“source”类

  •  4
  • Mornedhel  · 技术社区  · 16 年前

    我的应用程序有一个自制的日志类,我将在封面下迁移到使用log4j。但是,由于我使用homebrew类将应用程序的其余日志语句传递给log4j,因此输出语句被记录为来自包装类而不是源类。

    除了为每个日志语句创建新的org.apache.log4j.logger实例之外,是否还有一种方法可以确保显示“正确”的源代码?我还尝试使用logger.log(string callerfqcn,priority level,object message,throwable t)方法,但它似乎不起作用,例如:

    public class Logger2 {
    
        public static org.apache.log4j.Logger log4JLogger = org.apache.log4j.Logger.getLogger(Logger2.class);
    
        public static void warning(Object source, String message) {
    
            log(source, message, Level.WARN, null)
        }
    
        private static void log(Object source, String message, Level level, Throwable t) {
    
            String className = source.getClass().getName();
            System.out.println("Logging class should be " + className);
            log4JLogger.log(className, loggingLevel, message, t);
        }
    }
    

    当被调用时:

    public void testWarning() {
        Logger2.warning(new Integer(3), "This should warn");
    }
    

    印刷品:

    Logging class should be java.lang.Integer
    2010-05-25 10:49:57,152 WARN                              test.Logger2 - This should warn
    
    3 回复  |  直到 10 年前
        1
  •  4
  •   Espen    16 年前

    我的自制测井解决方案使用了log4j LocationInfo 类以查找源代码信息。

    有了这个解决方案, locationInfo 对象包含来自对象的信息,该对象使用 loggerName .

    以下是使用log4j登录的日志记录器的简化版本:

    public void log(Level level, String message) {
        LocationInfo locationInfo = new LocationInfo(new Throwable(),
                loggerName);
    
        MDC.put(LINE_NUMBER, locationInfo.getLineNumber());
        MDC.put(FILE_NAME, locationInfo.getFileName());
        MDC.put(CLASS_NAME, locationInfo.getClassName());
        MDC.put(METHOD_NAME, locationInfo.getMethodName());
        MDC.put(FQMETHOD_NAME, locationInfo.getClassName() + "."
                + locationInfo.getMethodName());
    
        logger.log(level, message);
    
        MDC.remove(LINE_NUMBER);
        MDC.remove(FILE_NAME);
        MDC.remove(CLASS_NAME);
        MDC.remove(METHOD_NAME);
        MDC.remove(FQMETHOD_NAME);
    }
    

    顺便说一句 Level , MDC Logger 类都是log4j类。

    回复评论:

    MDC对象存储在 ThreadLocal 对象,可供log4j记录器访问。

    来自MDC Java文档:

    MDC是基于每个线程进行管理的。

        2
  •  0
  •   Havok    15 年前

    在log4j api中,关于logger.log(字符串callerfqcn、优先级、对象消息、throwable t):

    参数:

    • callerfqcn-包装类的完全限定类名。
    • 级别-日志记录请求的级别。
    • 消息-日志记录请求的消息。
    • T-日志记录请求的可放弃项,可以为空。

    见: Log4J API .

    很奇怪,我知道,参数被称为“callerfqcn”,它连接到调用对象类,但是(muajaja!)它实际上是“包装器”类(例如myclass.class.getname())。

    事实上,打电话的人被我认为是被抛弃的论点说服了。不确定,还没有检查实现。

    当您将throwable参数留空时,我认为下面一定发生了类似的事情:

    StackTraceElement[] stack = (new Throwable()).getStackTrace();
    String caller = stack[something, meaby 1].getClassName();
    

    如果要创建记录器包装器,则需要执行以下操作:

    public static void myWarn(String message) {
        myLogger.log(MyWrapper.class.getName(), message, Level.WARN, null);
    }
    

    作为一个包装器,这是没有问题的。

    或者,如果您绝对需要维护下面显示的接口,请执行如下操作:

    // Warning: Pseudocode
    public static void myWarn(Object source, String message) {
        String sourceClass = source.class.GetName();
        StackTraceElement[] stack = (new Throwable()).getStackTrace();
        stack[1, or meaby 2... or 0?] = new whatever(sourceClass);
        myLogger.log(MyWrapper.class.getName(), message, Level.WARN, myStack);
    }
    

    希望这有帮助。

        3
  •  0
  •   jake256    11 年前

    应该这样做:

    class Logger2 {
    
      Logger _log4JLogger;
    
      public void log(Object msg) {
        _log4JLogger.log(Logger2.class.getName(), Priority.INFO, msg, null);
      }
    
    }