如何从已部署的应用程序中以编程方式更改 WildFly 日志记录级别

问题描述 投票:0回答:3

我当前正在运行 WildFly 23,我想在部署应用程序时强制使用特定的日志级别。这意味着,如果有人进入standalone.xml 文件并将日志级别更改为其他级别,应用程序将检测到它并将其更改回我想要的级别。

检测部分很简单,但我很难将其设置回来。 我使用 slf4j,它没有 setLevel 方法。我可以通过导入 log4j 依赖项并通过 log4j 的 setLevel 方法更改级别来做到这一点,但我不想导入特定的记录器库依赖项,我只想保留 slf4j。

我也可以通过 jboss-cli 命令来完成此操作,但这需要运行一个单独的脚本,该脚本也可以手动修改,所以我想从代码内部以编程方式完成此操作。

我已经搜索了很多方法来做到这一点,但没有找到任何可以帮助我的东西。如果可能的话,有谁知道如何做到这一点?

非常感谢!

java logging wildfly slf4j jboss-cli
3个回答
1
投票

没有好的方法可以做到这一点,因为使用像 slf4j 这样的日志外观,您无法配置日志管理器。不过,这是一件好事,因为在我看来,以编程方式更改日志记录是不好的做法。

也就是说,您可以做的是创建一个保留在部署中的

logging.properties
,它为您配置日志记录。

# Additional loggers to configure (the root logger is always configured)
loggers=my.logger.name

logger.level=INFO
logger.handlers=CONSOLE,FILE

logger.my.logger.name.level=DEBUG

handler.CONSOLE=org.jboss.logmanager.handlers.ConsoleHandler
handler.CONSOLE.formatter=COLOR-PATTERN
handler.CONSOLE.properties=autoFlush,target
handler.CONSOLE.autoFlush=true
handler.CONSOLE.target=SYSTEM_OUT

handler.FILE=org.jboss.logmanager.handlers.PeriodicRotatingFileHandler
handler.FILE.formatter=PATTERN
handler.FILE.properties=autoFlush,append,fileName,suffix
handler.FILE.constructorProperties=fileName,append
handler.FILE.autoFlush=true
handler.FILE.append=true
handler.FILE.fileName=${jboss.server.log.dir}/my-app.log
handler.FILE.suffix=.yyyy-MM-dd

formatter.COLOR-PATTERN=org.jboss.logmanager.formatters.PatternFormatter
formatter.COLOR-PATTERN.properties=pattern
formatter.COLOR-PATTERN.pattern=%K{level}%d{HH\:mm\:ss,SSS} %-5p [%c] (%t) %s%e%n

formatter.PATTERN=org.jboss.logmanager.formatters.PatternFormatter
formatter.PATTERN.properties=pattern
formatter.PATTERN.pattern=%d{yyyy-MM-dd HH\:mm\:ss,SSS} %-5p [%c] (%t) %s%e%n

有一个问题是您无法写入

server.log
,但您仍然可以写入控制台。您可以将此文件放入您的部署中,每次部署时,它都会为您配置一个日志上下文,该上下文无法通过 CLI 等管理操作覆盖。


0
投票

很抱歉在问题发生后这么长时间才发布答案,我实际上不久前就解决了这个问题,但忘记在这里发布我的解决方案。

正如詹姆斯在回答中所说,您可能应该避免这样做,但就我而言,我必须这样做,因为监管规则规定,如果没有日志运行,系统永远无法执行。但如果日志关闭,我们也不能不执行系统,因为它是一个关键系统,永远不应该离线。 这可能不是最好的解决方案,但如果您也有同样的情况,我是这样做的:

首先,您的项目中需要 Wildfly Client 依赖项:

<!-- https://mvnrepository.com/artifact/org.wildfly.core/wildfly-controller-client -->
<dependency>
    <groupId>org.wildfly.core</groupId>
    <artifactId>wildfly-controller-client</artifactId>
    <version>18.1.1.Final</version>
</dependency>

然后就可以使用Wildfly Client执行jboss-cli命令了:

//First we find out the WildFly parameters
String hostname = (String) ManagementFactory.getPlatformMBeanServer().getAttribute(new ObjectName("jboss.as:interface=public"), "inet-address");
Integer managementPort = (Integer) ManagementFactory.getPlatformMBeanServer().getAttribute(new ObjectName("jboss.as:socket-binding-group=standard-sockets,socket-binding=management-http"), "port");
Integer portOffset = (Integer) ManagementFactory.getPlatformMBeanServer().getAttribute(new ObjectName("jboss.as:socket-binding-group=standard-sockets"), "port-offset");

//Then we create the client using the parameters obtained above
try (ModelControllerClient client = ModelControllerClient.Factory.create(hostname, managementPort+portOffset)) {
    //Creates the change log level operation
    ModelNode op = new ModelNode();
    op.get("operation").set("change-root-log-level");
    //Writes the way to the root logger that will be changed
    ModelNode addr = op.get("address");
    addr.add("subsystem", "logging");
    addr.add("logging-profile", "myApp"); //myApp is my logging-profile name, yours will be different!
    addr.add("root-logger", "ROOT");
    //Makes the level change
    op.get("level").set("INFO");
    //Executes the operation
    ModelNode returnVal = client.execute(op);
    
    //If you want, you can log the results
    if(logger.isInfoEnabled()) {
        logger.info("Execution results:");
        logger.info("Outcome: {}", returnVal.get("outcome"));
        logger.info("Result: {}", returnVal.get("result"));
    }
}

我希望这对那里的人有帮助!


0
投票

使用 JVM 内客户端连接更改日志级别会更容易一些(请注意,我在这里使用的是 Lombok 的

val
):

package org.test;

import lombok.extern.slf4j.Slf4j;
import lombok.val;
import org.jboss.as.cli.scriptsupport.CLI;

@Slf4j
public class LogLevelChanger {

    private static final String LOGGER_SUBSYSTEM = "/subsystem=logging/logger=";

    public static void changeLogLevel(String loggerName, String newLevel) {
        val cli = CLI.newInstance();
        try {
            cli.connect();
            changeConsoleHandlerLogLevel(cli, newLevel);
            val command = String.format(LOGGER_SUBSYSTEM +
                    (loggerExists(cli, loggerName) ?
                        "%s:change-log-level" :
                        "%s:add") +
                    "(level=%s)",
                loggerName, newLevel);
            val result = cli.cmd(command);
            if (result.isSuccess()) {
                log.info("{} log level changed successfully to {} - {}", loggerName, newLevel, result.getResponse());
            } else {
                log.warn("Changing {} log level to {} FAILED - {}", loggerName, newLevel, result.getResponse());
            }
        } finally {
            cli.disconnect();
        }
    }

    private static void changeConsoleHandlerLogLevel(CLI cli, String newLevel) {
        val command = String.format("/subsystem=logging/console-handler=CONSOLE:write-attribute(name=level,value=%s", newLevel);
        val result = cli.cmd(command);
        if (!result.isSuccess()) {
            throw new RuntimeException("Changing console handler log level failed: " + result.getResponse());
        }
    }

    private static boolean loggerExists(CLI cli, String loggerName) {
        val command = String.format(LOGGER_SUBSYSTEM + "%s:read-resource", loggerName);
        return cli.cmd(command).isSuccess();
    }
}
© www.soinside.com 2019 - 2024. All rights reserved.