当前位置: 首页 > 知识库问答 >
问题:

Log4j2:切换到路由后自定义插件不工作

孟文栋
2023-03-14

我使用了一个自定义插件,该插件使用PluginManager类以编程方式注册,以加载map中的值,并根据map的内容更改RollingFileAppender的文件名。

然后,我更改了配置,使用路由追加器,以便能够使用ThreadContext内容进一步更改文件名(基本上,我希望应用程序的每个线程都有一个日志文件)。

然而,自从我开始使用Routing appender以来,我的自定义插件不再产生期望的结果,尽管我根本没有更改它。基本上,它返回的是空值。

我的log4j2-configuration.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/-thenameofthread.log”,而应该是“/var/log/tomcat9/thenameofwar-thenameofthread.log”。

我尝试了几件没有帮助的事情:

  • 对log4j2配置的配置标签使用packages属性。xml

现在,我已经求助于使用xml文件在tomcat中部署应用程序,该文件包含一个上下文参数,可以使用${web:initParam.warName}访问该参数,但这对我来说并不实际。

是否有一种嵌入式方法可以检索正在部署的war的名称,而不必使用“自定义”参数方法?

谢谢你!

共有1个答案

陈俊誉
2023-03-14

当它停止工作时,它正在创建一个名为“-threadId.log”的文件,这表明正在调用查找。如果不是,文件名将是“${propertyMap:warName}-threadId.log”。因此,这意味着要么您存储的warName错误,要么您的查找有问题。我可以想到两种可能性。

  1. 您没有显示战争名称是如何派生的。有可能那里出了问题。
  2. 您的Lookup可能存在于两个不同的类加载器中。如果发生这种情况,您将在servlet上下文初始化器中初始化一个,但在日志记录时使用另一个。

如果是我,我会调试并确保在添加战争名称和查找战争名称时使用相同的地图。

正如我在上面的评论中所指出的,您还可以将web查找的contextPath键用作${web:contextPath}。这并不总是与war名称相同,但在默认的Tomcat环境中应该是相同的。

 类似资料:
  • 我正在尝试为log4j2.0创建一个自定义appender,但是在获取log4j配置以识别appender时遇到问题。我知道log4j 2.0不支持配置属性中的包。因此,正如这里所建议的,我尝试使用纯javac运行代码,但即使如此,它也会出现以下错误: 这是我的自定义附件: 和我的配置xml: 提前感谢您提供的有用信息

  • 在Swoole::$php->runMVC() 调用之前可以修改默认的路由函数。 Swoole::$php->router(function(){ return array('controller' => 'YourController', 'view' => 'YourView'); }); Swoole::$php->runMVC(); 设置后将使用制定的函数作为路由,路由函数务必要

  • phpGrace 追求极致的效率,我们并不认同在url的基础上继续进行复杂的正则匹配是一种高效的、明智的选择!方便的调用规则比不上轻快的效率!所以我们并不建议您使用复杂的路由规则!尽管如此为了满足开发者的需求和习惯我们还是开放了简单路由!在入口页开启路由配置 <?php define('PG_ROUTE', true);//在框架核心文件引用前定义 include 'phpGrace/phpGra

  • 我正在尝试发送电子邮件时,一个订单被移动到一个自定义状态在Woocommerce。我已经成功地创建了一个插件,它创建了一个自定义状态,订单被分配给自定义状态。 我还成功地在WooCommerce中的Settings->Emails下添加了一个自定义电子邮件模板,并编写了代码,当订单移动到自定义状态时,该代码应该发送电子邮件。 但是,代码不会被触发,电子邮件也不会被发送。 下面是我的代码。 在我编写

  • 我正在我的web项目中使用log4j2。我试图通过扩展AbstractAppender将日志直接放入Kafka。根据文档,我的理解是我可以为一个自定义的附加器指定patternlayout,并且设置好了,我的记录器将用格式化的字符串向kafka发送日志事件,但这并没有发生。log4j2.xml看起来像

  • 问题内容: 我已经将我的log4j2自定义插件打包到一个单独的jar中(仅包含插件类),并将其放在应用程序类路径中。但是不会被检测到。 我用谷歌搜索发现它是一个错误-“ packages”参数不再使用。还有一些链接建议了一些替代方案,其中将maven pom.xml和log4j2插件dat文件放入上下文中。问题是我不熟悉Maven,并且不知道如何生成dat文件。我只知道它包含在log4j-2.1-