#java #logging #log4j #logback
#java #ведение журнала #log4j #logback
Вопрос:
В настоящее время мы переходим с log4j на Logback, но у нас возникают проблемы с получением «оригинального» имени метода, который вызвал журнал.
Я называю это «original», потому что у нас есть централизованный класс logger (для скрытия и управления определенными журналами), и в журналах отображается имя метода из этого централизованного класса.
В 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>
Результаты: (Имя метода — имя класса)
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>
Комментарии:
1. В Log4j, который вы используете
%M
, который возвращает вызывающий метод. Я не понимаю, как ваш Log4j мог бы справиться с вашим централизованным классом ведения журнала лучше, чем Logback. Является ли этот централизованный класс ведения журнала чем-то новым?2. Нет, централизованный регистратор использовался уже давно. Когда я увидел это поведение в logback, я проверил некоторые журналы log4j, чтобы узнать, происходит ли это также, но нет.
3. Документы log4j предостерегают от использования M, поскольку «Генерация информации о местоположении вызывающего абонента выполняется чрезвычайно медленно, и ее следует избегать, если скорость выполнения не является проблемой». В прошлом, когда мне требовалось имя метода, из которого я регистрирую сообщение, я включал имя метода в текст метода. например, ведение журнала из основного метода: logger.info («main(); бла-бла-бла»);
4. Пожалуйста, обновите свой вопрос, чтобы предоставить небольшой пример кода, который выведет правильное имя метода в Log4j и неправильное имя метода в Logback. Я все еще не уверен, что вы достигнете этого с помощью Log4j.
5. В соответствии с запросом только что добавлен пример
Ответ №1:
Вам нужно убедиться, что «данные вызывающего абонента» указаны правильно в событии журнала.
Вероятно, один из этих вариантов будет работать:
Вызовите ILoggingEvent::getCallerData() в оболочке вашего регистратора, чтобы убедиться, что данные вызывающего абонента собраны заранее.
Может быть, вы можете украсить событие в своем централизованном регистраторе, чтобы подделать данные вызывающего абонента ILoggingEvent::getCallerData() вызов?
Или извлеките данные вызывающего абонента, затем преобразуйте ILoggingEvent в LoggingEvent и вызовите setCallerData() вместе с вами.
Комментарии:
1. Я новичок в logback и не понимаю, что вы под этим подразумеваете. Не могли бы вы привести пример? Заранее спасибо.
2. Взгляните на исходный код logback, посмотрите, как это делает AsyncAppender.
3. Просто посмотрел в AsyncAppender.java и это 4 метода: boolean isDiscardable(событие ILoggingEvent), void preprocess(событие ILoggingEvent EventObject), boolean isIncludeCallerData(), void setIncludeCallerData(логическое значение includeCallerData), и я до сих пор не понимаю, как я могу включить его в свой LoggerCommon.java
4. Большая часть логики находится в базовом классе.
5. Кстати, действительно ли нужно иметь собственную оболочку журнала. Если вы можете просто перейти к обычному ведению журнала, тогда это намного проще.
Ответ №2:
Решил это с помощью этого:
methodName = stackTrace[xxxx].getMethodName();
Не идеально, поскольку xxxx зависит от сервера, но это лучшее, что мы смогли найти