我当前正在运行 WildFly 23,我想在部署应用程序时强制使用特定的日志级别。这意味着,如果有人进入standalone.xml 文件并将日志级别更改为其他级别,应用程序将检测到它并将其更改回我想要的级别。
检测部分很简单,但我很难将其设置回来。 我使用 slf4j,它没有 setLevel 方法。我可以通过导入 log4j 依赖项并通过 log4j 的 setLevel 方法更改级别来做到这一点,但我不想导入特定的记录器库依赖项,我只想保留 slf4j。
我也可以通过 jboss-cli 命令来完成此操作,但这需要运行一个单独的脚本,该脚本也可以手动修改,所以我想从代码内部以编程方式完成此操作。
我已经搜索了很多方法来做到这一点,但没有找到任何可以帮助我的东西。如果可能的话,有谁知道如何做到这一点?
非常感谢!
没有好的方法可以做到这一点,因为使用像 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 等管理操作覆盖。
很抱歉在问题发生后这么长时间才发布答案,我实际上不久前就解决了这个问题,但忘记在这里发布我的解决方案。
正如詹姆斯在回答中所说,您可能应该避免这样做,但就我而言,我必须这样做,因为监管规则规定,如果没有日志运行,系统永远无法执行。但如果日志关闭,我们也不能不执行系统,因为它是一个关键系统,永远不应该离线。 这可能不是最好的解决方案,但如果您也有同样的情况,我是这样做的:
首先,您的项目中需要 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"));
}
}
我希望这对那里的人有帮助!
使用 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();
}
}