Java 日志记录 : Log4j Version2. x:显示终端客户端调用方的方法(不是中间日志记录帮助程序方法)

标签 java logging log4j

以下 3 篇文章提供了有关如何使用中间日志记录助手并仍然让底层记录器从客户端方法向该日志记录助手报告(而不是将日志记录助手方法作为源报告)的答案:

但似乎只提供 Log4j 1.2 的答案,它提供了现已解散的:

 Category.log(String callerFQCN, Priority level, Object message, Throwable t). 

Logger in the log4J 2.5 API 似乎没有明显的等价物.

任何人都可以提供与直接使用 Log4J 2.x 兼容的答案吗?

最佳答案

对于 Log4j2,答案完全是通过使用记录器包装器提供的,如 Log4j2 手册中描述的 Example Usage of a Generated Logger Wrapper .可以简单地生成(使用此处所示的 org.apache.logging.log4j.core.tools.Generate$ExtendedLogger 工具)具有单个 STUB 级别的记录器包装器,然后对其进行调整以创建自定义日志记录方法,模仿 logIfEnabled 的使用(FQCN、LEVEL、Marker、message、Throwable)——可能忽略 STUB 级别并使用常规级别——然后如果需要,删除或注释掉 STUB 级别及其方法)。为此,FormattedMessage 可能会有所帮助。

例子:

java -cp log4j-core-2.5.jar org.apache.logging.log4j.core.tools.Generate\$ExtendedLogger com.mycomp.ExtLogger STUB=350 > com/mycomp/ExtLogger.java

然后适配生成的类(省略大部分支持方法):

public final class ExtLogger extends ExtendedLoggerWrapper {
    ...
    private final ExtendedLoggerWrapper logger;

    private static final String FQCN = ExtLogger.class.getName();
    private static final Level STUB = Level.forName("STUB", 350);
    //Delete this afterwards if level not used.

    private ExtLogger(final Logger logger) {
        super((AbstractLogger) logger, logger.getName(), logger.getMessageFactory());
        this.logger = this;
    }

    /**
     * Returns a custom Logger with the name of the calling class.
     * 
     * @return The custom Logger for the calling class.
     */
    public static ExtLogger create() {
        final Logger wrapped = LogManager.getLogger();
        return new ExtLogger(wrapped);
    }

    /**
     * Returns a custom Logger using the fully qualified name of the Class as
     * the Logger name.
     * 
     * @param loggerName The Class whose name should be used as the Logger name.
     *            If null it will default to the calling class.
     * @return The custom Logger.
     */
    public static ExtLogger create(final Class<?> loggerName) {
        final Logger wrapped = LogManager.getLogger(loggerName);
        return new ExtLogger(wrapped);
    }

    ...

    /**
     * Logs a message object with the {@code STUB} level.
     * 
     * @param message the message object to log.
     */
    public void stub(final String message) {
        logger.logIfEnabled(FQCN, STUB, null, message, (Throwable) null);
    }


    /**
     * Example: Adapt with custom formatting.
     * Here DEBUG level is used just as an example.
     *
     * @param name
     * @param value 
     */
    public void echo(final String name, Object value) {
        Message m = new FormattedMessage("echo: %s(%s)",name,value);
        logger.logIfEnabled(FQCN, Level.DEBUG, null, m, (Throwable) null);
    }
    ...
}

然后在客户端类中,它现在将通过记录器的辅助方法正确地“代表”该客户端进行记录,在本例中为格式化示例 echo(name,value):

public class TestLog4j {

    private static final ExtLogger extLogger = ExtLogger.create(TestLog4j.class);

    public static void elseWhere() {
        extLogger.echo("aVariableName", 4);
    }

    public static void main(String[] args) {
            extLogger.echo("aStringVariableName","from main");
            elseWhere();
    }
}

简单的图案布局:

  <PatternLayout pattern=" %-5level [%C{1}::%M(%L)] %logger{36} - %msg%n"/>

输出:

 DEBUG [TestLog4j::main(63)] testlogging.TestLog4j - echo: aStringVariableName(from main)
 DEBUG [TestLog4j::elseWhere(42)] testlogging.TestLog4j - echo: aVariableName(4)

一旦掌握了将 logger.logIfEnabled(FQCN,...) 与 FQCN(log4j 在堆栈跟踪中搜索的)一起使用的窍门,您可能希望删除或注释掉 stub(..) 方法和 STUB 级别(如果您不使用其他级别)。

关于Java 日志记录 : Log4j Version2. x:显示终端客户端调用方的方法(不是中间日志记录帮助程序方法),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35360887/

相关文章:

java - 如何找到 log4j 默认初始化中使用的 URL?

java - 如何启用传输编码 :chunked in Java on AppEngine

javascript - Vaadin onbeforeunload 事件

java - 如何使用 xdocreport 将 odt 转换为 docx?

java - 如何在 Log4j 中根据时间而不是大小轮换日志文件?

json - HIVE:如何解析/忽略JSON日志消息中的SLF4J header

java - 可运行 Jar 中的源文件夹消失

java - 线程启动方法在运行返回之前返回

java - 使用 java.util.logging 和 Log4j Loggers 的区别

Linux 'script' docker 内的命令未按预期写入文件