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

如何以编程方式正确配置log4j2?

龙繁
2023-03-14

我正在尝试使用RollingFileAppender设置log4j2以写入日志。我希望以编程方式配置日志记录系统,而不是使用XML文件。

以下是我尝试过的内容(大部分与网站上的文档相同)https://logging.apache.org/log4j/2.x/manual/customconfig.html#Configurator):

public static void configure(String rootLevel, String packageLevel) {
    ConfigurationBuilder<BuiltConfiguration> builder = ConfigurationBuilderFactory
        .newConfigurationBuilder();

    builder.setConfigurationName("RollingBuilder");
    builder.setStatusLevel(Level.TRACE);

    // Create a rolling file appender

    LayoutComponentBuilder layoutBuilder = builder.newLayout("PatternLayout")
        .addAttribute("pattern", "%d{yyyy-MM-dd HH:mm:ss,SSS} %-5p %c{1}:%L - %m%n");

    ComponentBuilder triggeringPolicy =
        builder
            .newComponent("Policies")
            .addComponent(
                builder
                    .newComponent("SizeBasedTriggeringPolicy")
                    .addAttribute("size", "200M")
            );

    AppenderComponentBuilder appenderBuilder =
        builder
            .newAppender("rolling", "RollingFile")
            .addAttribute("fileName", "log")
            .addAttribute("filePattern", "log.%d.gz")
            .add(layoutBuilder)
            .addComponent(triggeringPolicy);

    builder.add(appenderBuilder);

    // Create new logger

    LoggerComponentBuilder myPackageLoggerBuilder =
        builder.newLogger("com.mypackage", packageLevel)
            .add(builder.newAppenderRef("rolling"))
            .addAttribute("additivity", false);
    builder.add(myPackageLoggerBuilder);

    RootLoggerComponentBuilder rootLoggerBuilder =
        builder
            .newRootLogger(rootLevel)
            .add(builder.newAppenderRef("rolling"));
    builder.add(rootLoggerBuilder);

    // Initialize logging
    Configurator.initialize(builder.build());
}

我在main方法的开头调用configure()方法。当我运行我的程序时,会创建一个名为log的文件,但是所有日志输出都会转到标准输出,并且log文件保持为空。

有人能帮忙找出我的配置有什么问题吗?

我没有使用任何log4j配置文件,如果这有所不同。在我的代码中也使用slf4j API。依赖性-

org.apache.logging.log4j:log4j-api:2.11.1
org.apache.logging.log4j:log4j-core:2.11.1
org.apache.logging.log4j:log4j-slf4j-impl:2.11.1
org.slf4j:slf4j-api:1.7.25

共有2个答案

楚宇
2023-03-14

请查找示例根日志,最后需要调用重新配置函数。

java prettyprint-override">RootLoggerComponentBuilder rootLogger = builder
   .newRootLogger(Level.ALL)
   .add(builder.newAppenderRef("LogToRollingFile"));

LoggerComponentBuilder logger = builder
   .newLogger("MyClass",Level.ALL)
   .addAttribute("additivity", false);

Configurator.reconfigure(builder.build());
汪泓
2023-03-14

首先,这个答案是对您评论中提供的附加信息的回应。

我的要求是,我希望在启动程序时通过命令行标志控制不同包的日志级别

由于您希望使用程序参数来控制日志级别,我建议您查看主参数查找和路由附加器。结合使用这两个功能,您可以设置日志记录配置,以便根据程序参数将日志事件发送到相应的附加器。

我将提供一个简单的例子来帮助指导您。

首先,这里是一个生成一些日志事件的示例Java类:

import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.apache.logging.log4j.core.lookup.MainMapLookup;

public class SomeClass {

    private static Logger log = LogManager.getLogger();

    public static void main(String[] args){
        MainMapLookup.setMainArguments(args);

        if(log.isDebugEnabled())
            log.debug("This is some debug!");
        log.info("Here's some info!");
        log.error("Some error happened!");
    }
}

接下来是log4j2的配置文件(详见代码中的注释):

<?xml version="1.0" encoding="UTF-8"?>
<Configuration status="warn">
    <Appenders>
        <Routing name="myRoutingAppender">
            <!-- log events are routed to appenders based on the logLevel program argument -->
            <Routes pattern="$${main:logLevel}">
                <!-- If the logLevel argument is followed by DEBUG this route is used -->
                <Route ref="DebugFile" key="DEBUG" />
                <!-- If the logLevel argument is omitted or followed by any other value this route is used -->
                <Route ref="InfoFile" />
            </Routes>
        </Routing>

        <!-- This appender is not necessary, was used to test the config -->
        <Console name="Console" target="SYSTEM_OUT">
            <PatternLayout pattern="%d{HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n" />
        </Console>

        <!-- Below are the 2 appenders used by the Routing Appender from earlier -->
        <File name="DebugFile" fileName="logs/Debug.log" immediateFlush="true"
            append="false">
            <PatternLayout
                pattern="%d{yyy-MM-dd HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n" />
        </File>

        <File name="InfoFile" fileName="logs/Info.log" immediateFlush="true"
            append="false">
            <PatternLayout
                pattern="%d{yyy-MM-dd HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n" />
            <LevelRangeFilter minLevel="FATAL" maxLevel="INFO" onMatch="ACCEPT" onMismatch="DENY"/>
        </File>
    </Appenders>

    <Loggers>
        <!-- Root logger is set to DEBUG intentionally so that debug events are generated.
             However, events may be ignored by the LevelRangeFilter depending on where they
             are routed by the Routing Appender
         -->
        <Root level="DEBUG">
            <AppenderRef ref="Console" />
            <AppenderRef ref="myRoutingAppender" />
        </Root>
    </Loggers>
</Configuration>

使用此配置如果不提供“logLevel”参数,则默认情况下,日志事件将路由到“InfoFile”附件,并且通过LevelRangeFilter忽略比信息更具体的任何事件。

如果提供了“logLevel”参数并后跟“DEBUG”,则日志事件将路由到“DebugFile”附录器,并且不会忽略任何事件。

请注意,我确实尝试使用查找来设置日志级别,但似乎无法通过查找来配置日志级别参数。这就是为什么我不得不使用这种替代方法。我对这种方法的一个担忧是,正如我在配置文件中的注释中所指出的,日志级别必须保持在DEBUG,这意味着即使您不使用它们,您也总是生成DEBUG事件。这可能会影响性能。一种解决方法是使用程序参数来确定是否需要生成调试事件。例如:

通常你会使用:

if(log.isDebugEnabled())
    log.debug("This is some debug!");

但是当使用上面的配置时,你会使用这样的东西:

if("DEBUG".equals(args[1]))
    log.debug("This is some debug!");

如果需要,您可以使用enum(甚至可以使用log4j2提供的Level类)来提高效率。

我希望这能帮助你开始。

 类似资料:
  • 我需要实现一个Android应用程序,允许用户配置VPN连接,而无需访问Android设备的本机菜单。我有两个问题: > 在Android 4.0(api级别14及以上)中,我发现有一个名为VpnService的新组件,它提供了一个钩子来创建虚拟网络接口,配置它,并从它拦截/转发包到VPN服务器,但是有没有像PPTP或IPSec这样的内置vpn协议,只有实现它们的可能性。我的问题是PPTP和IPS

  • 我在logback.xml中定义了一个logback appender,它是一个DB appender,但是我想知道是否有任何方法可以使用我自己定义为bean的连接池在java中配置appender。 我发现了类似的事情,但从来没有真正的答案。

  • 问题内容: 我的问题很简单 如何以编程方式设置我的按钮layout_gravity? 我在互联网上找到了它,但它只是抛出了一个Nullpointer异常: 有什么办法吗? 问题答案: Java Kotlin 有关重力值以及如何设置重力,请检查“重力”。 基本上,您应该选择依赖于父项。可以是等等。

  • 问题内容: 我试图仅通过使用和此参考来配置和设置Log4j2 。我使用的代码如下: 注意 它扩展了默认情况下已经配置的控制台 它尝试向根记录器添加滚动文件追加器 我得到以下异常: 如果我在上面的代码之后注释掉该代码,它可以工作,但似乎缺少配置滚动文件附加程序的内容。我应该怎么做才能解决这个问题? 问题答案: 在 log4j 2.x中, 您必须以这种方式指定日期格式 标记格式的开始 表示它是日期格式

  • Im使用Log4j2 2.6.2。在应用程序的开始,我调用以下代码 输出显示为 即默认布局正在使用中。我对默认值的编程重写不起作用。有谁能帮你修改代码吗?

  • 问题内容: 说我有两个JavaBeans 和。 如果创建一个Person对象的列表,我想编组成这样的东西: 可以使用这里描述的技术: 使用JAXB解组/编组List 通过使用和注释JaxbList,可以将其编组为上述XML。 但是,能够重用相同的类来封送对象列表也很好。实际上,我将有许多其他类型的bean。我可以这样: 但是,理想情况下,最好用类名的复数形式替换“列表”,用类名替换“ item”。