1

In my app, I would like some way of formatting. For that purpose, I wrote a SingleLineFormatter extends Formatter.

Now I am trying to set all Loggers to use it, but can't figure that out.

        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");

This reads the config, applies it to all handlers that are found.

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

However the rest of the Loggers still use whatever they were configured with. Probably just JUL's default.

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

I know I can manage this from JUL's logging.properties within my JVM.
But I want to distribute the app, and want all the log messages to be formatted the same way.

How can I force all messages going to JUL to be formatted with my Formatter?

There is -Djava.util.logging.config.file=/path/to/app.properties, but that's out of scope for my particular case. (And doesn't work anyway.)

Update: It looks like the third party logging doesn't go through JUL. So the question is - if that's true, how do I configure the other frameworks?

Here is the file that's being loaded to LogManager. There are quite some experiments so not everythign is correct.

# 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
Ondra Žižka
  • 43,948
  • 41
  • 217
  • 277

3 Answers3

1

In my app, I would like some way of formatting. For that purpose, I wrote a >SingleLineFormatter extends Formatter

Since JDK 7 the java.util.logging.SimpleFormatter supports a one line format.

This reads the config, applies it to all handlers that are found.

JUL will only load handlers when the logger is demanded by code. It is therefore possible to miss handlers because the loggers themselves haven't been created yet.

How can I force all messages going to JUL to be formatted with my Formatter?

There is -Djava.util.logging.config.file=/path/to/app.properties, but that's out of scope for my particular case. (And doesn't work anyway.)

You are already accessing the LogManager so you can set properties from Java like so:

 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);
    }
}

If you are running JDK 9 or newer then you should use LogManager.updateConfiguration(java.util.function.Function) instead.

It looks like the third party logging doesn't go through JUL. So the question is - if that's true, how do I configure the other frameworks?

You'll have to determine if the frameworks are routing to one another. You should only have to change the format of the framework that is publishing records to a output source.

Community
  • 1
  • 1
jmehrens
  • 10,580
  • 1
  • 38
  • 47
0

In attempts to conform to what the lib might want me to use for logging, I switched to SLF4J and Logback. Didn't help.

So I looked at the particular library that causes the logging issues - HSQLDB.

The problem is that it does some attempts to master all common frameworks and bypasses my attempts to configure it externally. Here is an example: FrameworkLogger

Then I found in the HSQLDB manual:

HyperSQL also supports log4J and JDK logging. The same event information that is passed to the internal log, is passed to external logging frameworks. These frameworks are typically configured outside HyperSQL. The log messages include the string "hsqldb.db." followed by the unique id (a 16 character string) of the database that generated the message, so they can be identified in a multi-database server context.

As the default JDK logging framework has several shortcomings, HyperSQL configures this logging framework for better operation. If you do not want HyperSQL to configure the JDK logging framework, you should include the system level property hsqldb.reconfig_logging=false in your environment.

I tried setting the hsqldb.db. Logger but that didn't work.

So I guess I'll stick with JUL, and turn off the hsqldb.reconfig_logging=false.

By the way, here is a good review of JUL config.

Community
  • 1
  • 1
Ondra Žižka
  • 43,948
  • 41
  • 217
  • 277
0

One way is to a static String across application such as

private static Logger logger = Logger.getLogger("some_value");
double-beep
  • 5,031
  • 17
  • 33
  • 41
Pank
  • 1