【问题标题】:java.util.logging - How to force all Loggers to obey given format from within the app's runtime? (HSQLDB)java.util.logging - 如何强制所有 Logger 在应用程序的运行时中遵守给定的格式? (HSQLDB)
【发布时间】:2018-10-02 20:47:12
【问题描述】:

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

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

        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

但是Loggers 的其余部分仍然使用他们配置的任何东西。可能只是 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

【问题讨论】:

    标签: java logging formatting hsqldb java.util.logging


    【解决方案1】:

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

    从 JDK 7 开始,java.util.logging.SimpleFormatter supports a one line format.

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

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

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

    有 -Djava.util.logging.config.file=/path/to/app.properties,但这超出了我的特定情况的范围。 (而且无论如何都不起作用。)

    您已经在访问 LogManager,因此您可以像这样从 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。所以问题是 - 如果这是真的,我该如何配置其他框架?

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

    【讨论】:

      【解决方案2】:

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

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

      问题在于它会尝试掌握所有常用框架并绕过我在外部配置它的尝试。这是一个例子:FrameworkLogger

      然后我在HSQLDB manual找到了:

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

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

      我尝试设置hsqldb.db. Logger,但没有成功。

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

      顺便说一句,here is a good review of JUL config

      【讨论】:

        【解决方案3】:

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

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

        【讨论】:

          猜你喜欢
          • 2013-02-12
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2017-01-01
          • 2023-03-22
          • 2011-11-20
          相关资源
          最近更新 更多