java.util.如何强制所有记录器在应用程序的运行时中服从给定的格式?(高青旅)



在我的应用程序中,我想要某种格式化方式。 为此,我写了一篇SingleLineFormatter extends Formatter.

现在我正在尝试设置所有Logger使用它,但无法弄清楚。

LogManager.getLogManager().readConfiguration((InputStream) configIS);
Collections.list(LogManager.getLogManager().getLoggerNames()).forEach(
loggerName -> {
List<Handler> handlers = Arrays.asList(Logger.getLogger(loggerName).getHandlers());
System.out.println(" * Logger " + loggerName + ": " + handlers.size());
handlers.forEach(handler -> System.out.println("   HF: " + handler.getFormatter()));
//handlers.forEach(handler -> handler.setFormatter(new SingleLineFormatter()));
}
);/**/
log.info("Logging test");

这将读取配置,将其应用于找到的所有处理程序。

Oct 02, 2018 10:42:10 PM cz.dynawest.logging.LoggingUtils initLogging
INFO: Log config file not found: #/logging.properties  Using LoggingUtils' default.
* Logger cz.dynawest.csvcruncher.App: 0
* Logger global: 0
* Logger cz.dynawest.logging.LoggingUtils: 0
2018-10-02 22:42:10 INFO cz.dynawest.logging.LoggingUtils initLogging:   Logging test
* Logger : 2
HF: cz.dynawest.logging.SingleLineFormatter@34c45dca
HF: cz.dynawest.logging.SingleLineFormatter@52cc8049

但是,其余的Logger仍然使用它们配置的任何内容。可能只是 JUL 的默认值。

Oct 02, 2018 10:42:10 PM org.hsqldb.persist.Logger logInfoEvent
INFO: checkpointClose start

我知道我可以在我的 JVM 中从 JUL 的logging.properties中管理它。
但是我想分发应用程序,并希望所有日志消息都以相同的方式格式化。

如何强制所有发送到 JUL 的消息都使用我的Formatter格式化?

-Djava.util.logging.config.file=/path/to/app.properties,但这超出了我的特定情况的范围。(反正也行不通。

更新:看起来第三方日志记录没有经过 JUL。所以问题是 - 如果这是真的,我该如何配置其他框架?

这是加载到LogManager的文件。有很多实验,所以不是每个实验都是正确的。

# Handlers
handlers = java.util.logging.ConsoleHandler java.util.logging.FileHandler
# Console
# The logging of the app actually reacts to this line.
java.util.logging.ConsoleHandler.formatter = cz.dynawest.logging.SingleLineFormatter
#java.util.logging.ConsoleHandler.formatter = cz.dynawest.logging.SimplestFormatter
java.util.logging.ConsoleHandler.level = ALL
# File
java.util.logging.FileHandler.level = ALL
java.util.logging.FileHandler.pattern = app.log
java.util.logging.FileHandler.formatter = cz.dynawest.logging.SingleLineFormatter
java.util.logging.FileHandler.limit = 0
java.util.logging.FileHandler.append = true

# Default global logging level.
.formatter = cz.dynawest.logging.SimplestFormatter
.level = INFO
#global.formatter = cz.dynawest.logging.SimplestFormatter
#root.formatter = cz.dynawest.logging.SimplestFormatter
#cz.dynawest.csvcruncher.App.formatter = cz.dynawest.logging.SimplestFormatter
#cz.dynawest.csvcruncher.App.handlers = java.util.logging.ConsoleHandler
#.useParentHandlers = false
# Various customizations.
org.apache.commons.beanutils.converters.level=INFO

在我的应用程序中,我想要某种格式化方式。为此,我写了一个>SingleLineFormatter扩展格式化程序

从JDK 7开始,java.util.logging.SimpleFormatter支持单行格式。

这将读取配置,将其应用于找到的所有处理程序。

JUL 仅在代码需要记录器时才加载处理程序。 因此,可能会错过处理程序,因为记录器本身尚未创建。

如何强制所有发送到 JUL 的消息都使用我的格式化程序进行格式化?

有-Djava.util.logging.config.file=/path/to/app.properties,但这超出了我特定情况的范围。(反正也行不通。

您已经在访问日志管理器,因此您可以从 Java 设置属性,如下所示:

private static void loadProperties() {
Properties props = new Properties();
props.put("java.util.logging.ConsoleHandler.formatter", "cz.dynawest.logging.SingleLineFormatter");
props.put("org.apache.commons.beanutils.converters.level", "INFO");
try(ByteArrayOutputStream out = new ByteArrayOutputStream()) {
props.store(out, "");
LogManager.getLogManager().readConfiguration(new ByteArrayInputStream(out.toByteArray()));
} catch (IOException ioe) {
throw new AssertionError(ioe);
}
}

如果您运行的是JDK 9或更高版本,则应改用LogManager.updateConfiguration(java.util.function.Function(。

看起来第三方日志记录没有通过 JUL。所以问题是 - 如果这是真的,我该如何配置其他框架?

您必须确定框架是否相互路由。 您只需更改将记录发布到输出源的框架的格式。

为了符合库可能希望我用于日志记录的内容,我切换到 SLF4J 和 Logback。没帮助。

所以我查看了导致日志记录问题的特定库 - HSQLDB。

问题是它尝试掌握所有常见的框架,并绕过我在外部配置它的尝试。下面是一个例子:FrameworkLogger

然后我在HSQLDB手册中找到:

HyperSQL还支持log4J和JDK日志记录。传递给内部日志的相同事件信息将传递到外部日志记录框架。这些框架通常在 HyperSQL 外部配置。日志消息包括字符串"hsqldb.db.",后跟生成消息的数据库的唯一 ID(16 个字符的字符串(,因此可以在多数据库服务器上下文中标识它们。

由于默认的JDK日志记录框架有几个缺点,HyperSQL配置此日志记录框架以获得更好的操作。如果不希望 HyperSQL 配置 JDK 日志记录框架,则应在环境中包含系统级属性 hsqldb.reconfig_logging=false。

我尝试设置hsqldb.db.记录器,但这不起作用。

所以我想我会坚持使用 JUL,并关闭hsqldb.reconfig_logging=false.

顺便说一下,这是对 JUL 配置的良好评论。

一种方法是跨应用程序的静态字符串,例如

private static Logger logger = Logger.getLogger("some_value");

最新更新