Log4j2: пользовательский плагин не работает после переключения на маршрутизацию - PullRequest
0 голосов
/ 03 февраля 2020

Я использовал пользовательский плагин, зарегистрированный программно с использованием класса PluginManager, чтобы загрузить значения в карту и изменить имя файла моего RollingFileAppender на основе содержимого карты.

Затем я изменил свою конфигурацию, чтобы использовать маршрутизацию appender, чтобы иметь возможность использовать содержимое ThreadContext для дальнейшего изменения fileName (в основном, я хотел иметь один файл журнала на поток моего приложения).

Однако, так как я начал использовать приложение Routing, мой пользовательский плагин не дает желаемых результатов больше, хотя я не изменил его вообще. По сути, он возвращает пустые значения.

Моя log4j2-конфигурация. xml выглядит так:

<?xml version="1.0" encoding="UTF-8"?>
<Configuration status="debug">
    <Appenders>
        <Console name="STDOUT">
            <PatternLayout pattern="%m%n"/>
            <ThresholdFilter level="debug"/>
        </Console>

        <Routing name="contextSpecificAppender">
            <Routes pattern="$${ctx:threadName}">
                <!-- This route is chosen if ThreadContext has no value for key threadName -->
                <Route key="$${ctx:threadName}">
                    <RandomAccessFile
                        name="applicationAppender"
                        fileName="${sys:catalina.base}/logs/${propertymap:warName}.log"
                        filePattern="${sys:catalina.base}/logs/%d{yyyy-MM-dd}/${propertymap:warName}.%i.log"
                        append="true"
                    >
                        <PatternLayout>
                            <Pattern>%d{yyyy-MM-dd HH:mm:ss} %highlight{%p} %style{[%t]}{magenta} %style{%c{1}:%L}{cyan,bold} - %m%n</Pattern>
                        </PatternLayout>
                        <Policies>
                            <TimeBaseTriggeringPolicy />
                            <SizeBasedTriggeringPolicy size="100 MB" />
                        </Policies>
                        <DefaultRolloverStrategy max="1" />
                    </RandomAccessFile>
                </Route>
                <Route>
                    <RandomAccessFile
                        name="${ctx:threadName}"
                        fileName="${sys:catalina.base}/logs/${propertymap:warName}-${ctx:threadName}.log"
                        filePattern="${sys:catalina.base}/logs/%d{yyyy-MM-dd}/${propertymap:warName}-${ctx:threadName}.%i.log"
                        append="true"
                    >
                        <PatternLayout>
                            <Pattern>%d{yyyy-MM-dd HH:mm:ss} %highlight{%p} %style{[%t]}{magenta} %style{%c{1}:%L}{cyan,bold} - %m%n</Pattern>
                        </PatternLayout>
                        <Policies>
                            <TimeBaseTriggeringPolicy />
                            <SizeBasedTriggeringPolicy size="100 MB" />
                        </Policies>
                        <DefaultRolloverStrategy max="1" />
                    </RandomAccessFile>
                </Route>
            </Routes>
        </Routing>
    </Appenders>
    <Loggers>
        <Root level="debug">
            <AppenderRef ref="contextSpecificAppender" />
            <!--<AppenderRef ref="STDOUT"/>-->
        </Root>
        <Logger name="org.apache.axis2.enterprise" level="info">
            <AppenderRef ref="contextSpecificAppender" />
        </Logger>
        <Logger name="de.hunsicker.jalopy.io" level="fatal">
            <AppenderRef ref="contextSpecificAppender" />
        </Logger>
        <Logger name="httpclient.wire.header" level="fatal">
            <AppenderRef ref="contextSpecificAppender" />
        </Logger>
        <Logger name="org.apache.commons.httpclient" level="info">
            <AppenderRef ref="contextSpecificAppender" />
        </Logger>
    </Loggers>
</Configuration>

Класс, который отвечает за загрузку карты, находится здесь:

package com.my.package;

import java.net.URISyntaxException;
import java.net.URL;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.core.LoggerContext;
import org.apache.logging.log4j.core.config.plugins.util.PluginManager;

/**
 *
 * @author ixm
 */
public class Log4jInitiliazer {
    public static void initialize(String warName, URL log4jProperties) {
        PropertyMapLookup.propertyMap.put("warName", warName);

        PluginManager.addPackage(PropertyMapLookup.class.getPackageName());

        LoggerContext context = (LoggerContext) LogManager.getContext(false);
        try {
            context.setConfigLocation(log4jProperties.toURI());
        } catch (URISyntaxException ex) {
            ex.printStackTrace();
        }
    }
}

и он вызывается из ServletContextListener:

Log4jInitiliazer.initialize(warName, servletContextEvent.getServletContext().getResource("/WEB-INF/classes/log4j2-configuration.xml"));

Наконец, сам плагин находится здесь:

package com.my.package;

import java.util.HashMap;
import java.util.Map;
import org.apache.logging.log4j.core.LogEvent;
import org.apache.logging.log4j.core.config.plugins.Plugin;
import org.apache.logging.log4j.core.lookup.StrLookup;

/**
 *
 * @author ixm
 */
@Plugin(name="propertymap", category=StrLookup.CATEGORY)
public class PropertyMapLookup implements StrLookup {
    public static Map<String, String> propertyMap = new HashMap();

    @Override
    public String lookup(String arg0) {
        return propertyMap.getOrDefault(arg0, "");
    }

    @Override
    public String lookup(LogEvent arg0, String arg1) {
        return propertyMap.getOrDefault(arg0, "");
    }

}

Все имена файлов журналов в результате получаются "/ var / log /tomcat9/-theNameOfTheThread.log "и вместо этого должно быть" /var/log/tomcat9/theNameOfTheWar-theNameOfTheThread.log".

Я пробовал несколько вещей, которые не помогли:

  • с использованием атрибута пакетов для тега Configuration конфигурации log4j2. xml
  • отключение автоматической инициализации с помощью параметра контекста в сети. xml (http://logging.apache.org/log4j/2.x/manual/webapp.html* 1028) *)

На данный момент я прибег к развертыванию приложения в tomcat с использованием файла xml, который включает параметр контекста, доступный через $ {web: initParam.warName}, но это не очень практично для меня.

Есть ли Может быть, это встроенный способ получить название развертываемой войны, не прибегая даже к «пользовательскому» подходу к параметрам?

Спасибо!

1 Ответ

1 голос
/ 04 февраля 2020

Тот факт, что когда он перестал работать, он создает файл с именем -threadId.log, указывает, что ваш поиск вызывается. Если бы это не было именем файла, было бы "$ {propertyMap: warName} -threadId.log". Таким образом, это означает, что либо warName, который вы храните, неверен, либо что-то не так с вашим Lookup. Я могу думать о двух возможностях.

  1. Вы не показываете, как получено название войны. Возможно, там что-то не так.
  2. Возможно, ваш Lookup присутствует в двух разных загрузчиках классов. Если бы это произошло, вы бы инициализировали один в инициализаторе контекста сервлета, но использовали другой при регистрации.

если бы это был я, я бы отладил и убедился, что одна и та же Карта используется при добавлении названия войны и при поиске.

Как я заметил в Мой комментарий выше, вы также можете использовать ключ contextPath поиска в Интернете как $ {web: contextPath}. Это не всегда будет то же самое, что и имя войны, но оно должно быть таким же в среде Tomcat по умолчанию.

...