Logback - 获取方法名

7

我们目前正在从log4j迁移到Logback,但我们在获取触发日志的“原始”方法名称方面遇到了问题。

我称其为“原始”是因为我们有一个集中的记录器类(用于隐藏和操作某些日志),在日志中显示的是该集中类的方法名称。

在log4j中,我们能够正确地获取“原始”方法名称。

Logback是否能够获取它?

记录器参数:

log4j

<param name="ConversionPattern" value="%d{dd-MM-yyyy HH:mm:ss,SSS} %5p [%F] - %M() - %m%n"/>

Logback

<pattern>%d{"dd-MM-yyyy HH:mm:ss,SSS"} %-5level [%logger - %M] - %msg%n</pattern>

Results: (Method Name - Class Name)

log4j

doLogTester1 - a.Tester1            
doLogTester2 - b.Tester2            
doLogTester1 - a.Tester1            
doLogTester2 - b.Tester2            

Logback

processLog - a.Tester1              
processLog - b.Tester2              
processLog - a.Tester1              
processLog - b.Tester2              

编辑 - 完整示例

Main.java

public class Main
{
private static final LoggerCommon logger = new LoggerCommon(Main.class);

    public static void main(String[] args)
    {
        logger.doLog("I'm on the Main class in the main method");
    }
}

LoggerCommon

log4j

import org.apache.log4j.Level;
import org.apache.log4j.Logger;

public class LoggerCommon
{
    private static Logger logger;

    public LoggerCommon(Class<?> c)
    {
        logger = Logger.getLogger(c);
    }

    public void doLog(String message)
    {
        logger.log(LoggerCommon.class.getName(), Level.INFO, message, null);
    }
}

logback

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class LoggerCommon
{
    private Logger logger;

    public LoggerCommon(Class<?> c)
    {
        logger = LoggerFactory.getLogger(c);
    }

    public void doLog(String message)
    {
        logger.info(message);
    }
}

配置

log4j

<log4j:configuration xmlns:log4j="http://jakarta.apache.org/log4j/">
    <appender name="CA" class="org.apache.log4j.ConsoleAppender">
        <layout class="org.apache.log4j.PatternLayout">
            <param name="ConversionPattern" value="%M - %F - %m%n"/>
        </layout>
    </appender>
    <root>
        <level value="debug"/>
        <appender-ref ref="CA"/>
    </root>
</log4j:configuration>

logback

<configuration>
    <appender name="CA" class="ch.qos.logback.core.ConsoleAppender">
        <encoder>
            <pattern>%M - %logger - %msg %n</pattern>
        </encoder>
    </appender>
    <root level="TRACE">
        <appender-ref ref="CA"/>
    </root>
</configuration>

在Log4j中,你使用%M来返回调用的方法。我不明白你的Log4j如何比Logback更好地处理你的集中日志类。这个集中日志类是一个新的东西吗? - Duncan Jones
1
log4j文档警告不要使用M,因为“生成调用者位置信息非常缓慢,除非执行速度不是问题,否则应该避免使用。”过去,当我需要记录消息的方法名称时,我会在方法的文本中包含方法名称。例如,从主方法记录:logger.info(“main(); blah blah blah”); - DwB
请更新您的问题,提供一些示例代码,以便在Log4j中打印正确的方法名称和在Logback中打印错误的方法名称。我仍然不确定您是否能够使用Log4j实现它。 - Duncan Jones
如所请求,刚刚添加了示例。 - Gonçalo Cardoso
@balizeiro 目前还没有。但感谢您提供一个例子——在那之前我是不相信你的! - Duncan Jones
显示剩余2条评论
2个回答

3
您需要确保日志事件中的“调用者数据”是正确的。
以下方案可能会有帮助:
1. 在您的记录器包装器中调用ILoggingEvent::getCallerData(),以确保尽早收集调用者数据。 2. 在您的集中式记录器中装饰事件来欺骗调用者数据ILoggingEvent::getCallerData()调用? 3. 推断出调用者数据,然后将ILoggingEvent转换为LoggingEvent,并使用setCallerData()调用您的数据。

我对logback不熟悉,不太明白你的意思。能否请您提供一个例子?先谢谢了。 - Gonçalo Cardoso
看一下logback源代码,看看AsyncAppender是怎么做的。 - David Roussel
刚刚查看了AsyncAppender.java文件,发现它有四个方法:boolean isDiscardable(ILoggingEvent event)、void preprocess(ILoggingEvent eventObject)、boolean isIncludeCallerData()和void setIncludeCallerData(boolean includeCallerData),但我仍然不明白如何将其包含到我的LoggerCommon.java中。 - Gonçalo Cardoso
大部分的逻辑都在基类中。 - David Roussel
顺便问一下,是否真的需要拥有自己的日志包装器。如果你可以转移到普通日志记录,那么就容易得多了。 - David Roussel
仍然不明白你的意思。我查看了 AsyncAppenderBase.java,但仍然不知道如何将其合并到我的 LoggerCommon.java 中。如果您能提供一个示例,我将非常感激。关于需要拥有自己的类,是因为每次记录日志时,我都需要隐藏和操作某些日志。 - Gonçalo Cardoso

0

使用以下方法解决了问题:

methodName = stackTrace[xxxx].getMethodName();

由于xxxx基于服务器而异,所以并不完美,但这是我们能找到的最好的选择。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接