Передача динамического значения в конфигурацию log4j2 xml - PullRequest
0 голосов
/ 24 августа 2018

Я пытаюсь написать модуль ведения журнала, используя log4j2, который должен записывать журналы в консоль STDOUT в форме json.

Для этого я пытаюсь использовать PatternLayout в форме JSON, как показано ниже.

У меня есть некоторые трудности с динамической передачей значений из моего кода в файл конфигурации log4j2.xml для замены их во время выполнения при записи журнала.

Я пытался использовать StructuredDataMessage и MapMessages для замены значений изКарта, как упомянуто в https://logging.apache.org/log4j/2.0/manual/lookups.html.

Я также попробовал StrLookup и ContextMaplookup, но пока безуспешно.

Below is my xml config

    <?xml version="1.0" encoding="UTF-8"?>
    <Configuration status="WARN" name="App" packages="com.test.common.logging">
        <Properties>
            <Property name="filename">target/rolling1/rollingtest.log</Property>
            <Property name="maptype">$${map:type}</Property>

        </Properties>

        <ThresholdFilter level="debug"/>

        <Appenders>
            <Console name="Console" target="SYSTEM_OUT">
              <PatternLayout pattern="%highlight{{'logged time': '%d{dd MMM yyyy HH:mm:ss}', 
            'LEVEL' : '%level',
            'CLASS' : '%c{-1}',
            'Module' : '[%t]',
            'message' : '%m',
            'error' : '%exception',
            'class' : '%C',
            'threadid' : '%tid',
            'threadname' : '%thread',
            'whatisthis' : '${filename}',
            'processid' : '%pid', 
            'logdir' : '$${sd:type}'
            'location' : '${log4j:configLocation}'
            'systemproperty' : '$${ctx:key-}'
            }}%n"/>
            </Console>
        </Appenders>

        <Loggers>
            <Root level="trace">
                <AppenderRef ref="Console"/>
            </Root>
        </Loggers>

    </Configuration>

Ниже приведен мой код, в котором я пытаюсь передать динамические значения с помощью StrucuturedСообщение данных, strlookup и mapmessage

public class App 
{


    public static void main( String[] args )
    {
        Logger logger = LogManager.getLogger(App.class);

//      ConfigurationBuilder<BuiltConfiguration> builder
//       = ConfigurationBuilderFactory.newConfigurationBuilder();
//      
//      LayoutComponentBuilder standard 
//        = builder.newLayout("PatternLayout");
//      standard.
//      
        System.out.println( "Hello World!" );
        StructuredDataMessage message = new StructuredDataMessage("1", "name", "string");
        message.put("1", "nme");
       // MapMessage mapm = new MapMessage(map)
        MapMessage map = new MapMessage();
        map.put("type", "value");
        map.put("key", "value");
        map.put("name", "arun");
        StrLookup strlook = new StrLookup() {

            public String lookup(LogEvent event, String key) {
                // TODO Auto-generated method stub
                return null;
            }

            public String lookup(String key) {
                // TODO Auto-generated method stub

                return "value";
            }
        };
        ContextMapLookup lookup = new ContextMapLookup();
        System.out.println(lookup.lookup("key"));
        System.out.println(strlook.lookup("key"));

       // MapLookup.setMainArguments(args);

        System.setProperty("log_dir", App.class.getSimpleName());;
        logger.trace("trace log message");
        logger.debug("Debug log message");
        logger.info("Info log message");
        logger.error("Error log message");
        logger.fatal("Fatal log message");
        logger.info("Info log message[]");
        logger.error("null exception[]", new NullPointerException());

        // Lay

    }
}

Мой вывод:

Hello World!
null
value
[36m{'logged time': '24 Aug 2018 12:32:51',    'LEVEL' : 'DEBUG',   'CLASS' : 'test.common.logging.App',   'Module' : '[main]',   'message' : 'Debug log message',   'error' : '',   'class' : 'com.test.common.logging.App',   'threadid' : '1',   'threadname' : 'main',   'whatisthis' : 'target/rolling1/rollingtest.log',   'processid' : 'DEBUGid',    'logdir' : '${sd:type}'   'location' : '/Users/parunkarthick/ferry-commons/common/logging/target/classes/log4j2.xml'   'systemproperty' : '${ctx:key}'   [m}
[32m{'logged time': '24 Aug 2018 12:32:51',    'LEVEL' : 'INFO',   'CLASS' : 'test.common.logging.App',   'Module' : '[main]',   'message' : 'Info log message',   'error' : '',   'class' : 'com.test.common.logging.App',   'threadid' : '1',   'threadname' : 'main',   'whatisthis' : 'target/rolling1/rollingtest.log',   'processid' : 'INFOid',    'logdir' : '${sd:type}'   'location' : '/Users/parunkarthick/ferry-commons/common/logging/target/classes/log4j2.xml'   'systemproperty' : '${ctx:key}'   [m}
[1;31m{'logged time': '24 Aug 2018 12:32:51',    'LEVEL' : 'ERROR',   'CLASS' : 'test.common.logging.App',   'Module' : '[main]',   'message' : 'Error log message',   'error' : '',   'class' : 'com.test.common.logging.App',   'threadid' : '1',   'threadname' : 'main',   'whatisthis' : 'target/rolling1/rollingtest.log',   'processid' : 'ERRORid',    'logdir' : '${sd:type}'   'location' : '/Users/parunkarthick/ferry-commons/common/logging/target/classes/log4j2.xml'   'systemproperty' : '${ctx:key}'   [m}
[1;31m{'logged time': '24 Aug 2018 12:32:51',    'LEVEL' : 'FATAL',   'CLASS' : 'test.common.logging.App',   'Module' : '[main]',   'message' : 'Fatal log message',   'error' : '',   'class' : 'com.test.common.logging.App',   'threadid' : '1',   'threadname' : 'main',   'whatisthis' : 'target/rolling1/rollingtest.log',   'processid' : 'FATALid',    'logdir' : '${sd:type}'   'location' : '/Users/parunkarthick/ferry-commons/common/logging/target/classes/log4j2.xml'   'systemproperty' : '${ctx:key}'   [m}
[32m{'logged time': '24 Aug 2018 12:32:51',    'LEVEL' : 'INFO',   'CLASS' : 'test.common.logging.App',   'Module' : '[main]',   'message' : 'Info log message[]',   'error' : '',   'class' : 'com.test.common.logging.App',   'threadid' : '1',   'threadname' : 'main',   'whatisthis' : 'target/rolling1/rollingtest.log',   'processid' : 'INFOid',    'logdir' : '${sd:type}'   'location' : '/Users/parunkarthick/ferry-commons/common/logging/target/classes/log4j2.xml'   'systemproperty' : '${ctx:key}'   [m}
[1;31m{'logged time': '24 Aug 2018 12:32:51',    'LEVEL' : 'ERROR',   'CLASS' : 'test.common.logging.App',   'Module' : '[main]',   'message' : 'null exception[]',   'error' : ' java.lang.NullPointerException
    at com.test.common.logging.App.main(App.java:69)
',   'class' : 'com.test.common.logging.App',   'threadid' : '1',   'threadname' : 'main',   'whatisthis' : 'target/rolling1/rollingtest.log',   'processid' : 'ERRORid',    'logdir' : '${sd:type}'   'location' : '/Users/parunkarthick/ferry-commons/common/logging/target/classes/log4j2.xml'   'systemproperty' : '${ctx:key}'   [m}

Если вы видите, что последнее значение systemperperperty не отражает, как ожидалось, заменив значение кода.

1 Ответ

0 голосов
/ 26 августа 2018

Я думаю, у вас есть несколько фундаментальных недоразумений по поводу 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.Желаем удачи!

...