如何使用 Java 在日志文件中写入调用者位置信息,而不影响性能?

问题描述 投票:0回答:3

如何使用 Java 和 log4j 在日志文件中写入调用者位置信息(Java 源文件和行),而不影响性能? log4j允许您在日志文件中写入此类信息,但它使用堆栈跟踪来获取该信息,每次发出日志语句时,这会导致性能下降。 我正在寻找一种性能友好的替代方案,例如在编译时而不是在运行时获取位置信息。可以使用注释来实现这一点吗?或者也许还有其他技术?

java performance logging log4j
3个回答
1
投票

如何将其作为构建过程的一部分来替换某些占位符,例如此代码片段中的

$filename$
$linenumber$

logger.info("The original message... $filename$ $linenumber$");

要替换文件名,用您的版本控制系统进行关键字替换可能就足够了。免责声明:这只是我的想法,我自己从未尝试过。


0
投票

我同意 Rob 的观点,一般来说这是没有必要的。通常,日志消息中会有一些不同的字符串,搜索它就能找到源头。有了一个好的 IDE,这真的很快。

现在,鉴于问题本身,这是一个可能的解决方案:

Class Foo
    void bar()
        new Logger(){} . warn("blah");

对于运行时的每个日志操作,都会创建一个新对象 - 这不是问题。

对于包含此类日志语句的每一行源代码,都会创建一个新类。那可能太多了。

这就是魔法的运作方式:

abstract public class Logger
    static Map<Class, String> sourceInfo = new ...
    public Logger()
        Class thisClass = this.getClass();
        String info = sourceInfo.get(thisClass);
        if(info==null)
             info = ... // init from stack trace
             sourceInfo.put(thisClass,info)
        this.info = info

     public void warn(msg)
        log(WARN, this.info,msg)

0
投票

对于任何寻求更新解决方案的人(如果您将 log4j/logback 与 slf4j 一起使用),我编写了一个 maven-plugin 来解决此问题,同时也不会产生任何性能问题: https://github.com/PhilKes/slf4j-caller-info-maven-plugin

此插件在编译时将类名、方法名称和源代码行号注入到所有 SLF4J 日志语句中(请参阅配置)。 您需要做的就是将

callerInformation
MDC 参数添加到您的日志模式中,并将插件添加到您的
pom.xml
:

<plugin>
 <groupId>io.github.philkes</groupId>
 <artifactId>slf4j-caller-info-maven-plugin</artifactId>
 <version>1.1.0</version>
 <executions>
   <execution>
     <goals>
        <goal>inject</goal>
     </goals>
   </execution>
 </executions>
</plugin>
© www.soinside.com 2019 - 2024. All rights reserved.