Я думаю, у вас есть несколько фундаментальных недоразумений по поводу log4j2.Вместо того, чтобы пытаться перечислить все проблемы, которые я вижу в вашем коде, я думаю, что для меня лучше всего предоставить пример кода и объяснить результаты.Я думаю, что, увидев какой-то рабочий код, вы поймете, где вы ошиблись.
Для целей этого примера я упростил ваш файл конфигурации log4j2, удалив элементы, которые работают, и сосредоточив внимание на тех, которые не работают.Я изменил PatternLayout
на следующее:
<PatternLayout pattern="{'LEVEL' : '%level', 'typeFromStructMsg' : '${sd:type}', 'contextValue' : '${ctx:myContextKey}', 'nameFromMapMsg' : '${map:name}', 'mySysProperty' : '${sys:mySysProperty}'}%n" />
Я также изменил предоставленный вами класс App
:
package example;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.apache.logging.log4j.ThreadContext;
import org.apache.logging.log4j.message.MapMessage;
import org.apache.logging.log4j.message.StringFormattedMessage;
import org.apache.logging.log4j.message.StringMapMessage;
import org.apache.logging.log4j.message.StructuredDataMessage;
public class App {
private static final Logger logger = LogManager.getLogger();
public static void main( String[] args )
{
ThreadContext.put("myContextKey", "myContextValue");
StructuredDataMessage structMsg = new StructuredDataMessage("1", "name", "string");
StringMapMessage mapMsg = new StringMapMessage();
mapMsg.put("name", "arun");
System.setProperty("mySysProperty", "sys prop value");
logger.info(mapMsg);
logger.warn(structMsg);
logger.error("Error log message");
}
}
Когда класс App
запущен, следующеесгенерирован вывод консоли:
{'LEVEL' : 'INFO', 'typeFromStructMsg' : '${sd:type}', 'contextValue' : 'myContextValue', 'nameFromMapMsg' : 'arun', 'mySysProperty' : 'sys prop value'}
{'LEVEL' : 'WARN', 'typeFromStructMsg' : 'string', 'contextValue' : 'myContextValue', 'nameFromMapMsg' : '${map:name}', 'mySysProperty' : 'sys prop value'}
{'LEVEL' : 'ERROR', 'typeFromStructMsg' : '${sd:type}', 'contextValue' : 'myContextValue', 'nameFromMapMsg' : '${map:name}', 'mySysProperty' : 'sys prop value'}
Обратите внимание, что в первой строке вывода мы видим это: 'nameFromMapMsg' : 'arun'
, а в других строках мы видим это: 'nameFromMapMsg' : '${map:name}'
Первая строкавыходные данные генерируются этой строкой кода: logger.info(mapMsg);
, которая передает экземпляр MapMessage
, называемый mapMsg
, методу info
.Поскольку сообщение является экземпляром MapMessage
и содержит ключ с именем name
, поиск по карте заменит ${map:name}
найденным значением для ключа name
в сообщении.Вот почему только первая строка вывода показывает 'nameFromMapMsg' : 'arun'
- другие строки вывода генерируются из сообщений, которые не являются экземплярами MapMessage
.
Аналогично, обратите внимание, как вВо второй строке вывода мы видим 'typeFromStructMsg' : 'string'
.Это связано с тем, что журнал был сгенерирован из StructuredDataMessage
, который был определен с типом «строка»:
StructuredDataMessage structMsg = new StructuredDataMessage("1", "name", "string");
В других строках вывода мы не передавалиStructuredDataMessage
, поэтому в этих строках мы видим 'typeFromStructMsg' : '${sd:type}'
, поскольку log4j2 не может найти значение для типа.
Наконец, обратите внимание, как во всех выходных строках мы видим это: 'mySysProperty' : 'sys prop value'
.Это связано с тем, что поиск системных свойств не зависит от типа сообщения, передаваемого в регистратор.Этот поиск всегда может найти значение для системного свойства mySysProperty
, потому что мы его определили:
System.setProperty("mySysProperty", "sys prop value");
и, как я уже говорил, системные свойства не зависят от сообщения (они не хранятся всообщение).
То же самое верно для 'contextValue' : 'myContextValue'
- ThreadContext
не зависит от сообщения, и так как мы определили значение для этого ключа:
ThreadContext.put("myContextKey", "myContextValue");
поисквсегда в состоянии найти значение независимо от типа сообщения, отправляемого в регистратор.
Надеюсь, этот пример кода поможет проиллюстрировать, как используются некоторые поиски и как устроена архитектура log4j2.Желаем удачи!