I'm developing a Java application that uses java.util.logging for its logging needs. This application uses a multitude of external libraries (JDBC, JMS clients, JSR-160 implementation, etc), some of which also use java.util.logging.
I want to set the log level for my Loggers to ALL when I specify a flag on the command line, but so far I have only found ways to set the level for all loggers, not just mine.
My loggers are all called "com.mycompany.myapp.SomeClass" and when I set the level for "com.mycompany.myapp" to ALL, no extra information is logged. When I set the level for the root logger to ALL, all information for all loggers is logged to the console, which is way too much information!
How can I set my own loggers to ALL without having all those other loggers flood my logfiles?
Actually, I'm not sure why your having the problems you've described. I've created a simple JUnit test (below) and setting the log levels works exactly as I expect (which also seems inline with the way you expected them to work).
Are you trying to log messages with levels set below INFO in your custom logger? As you can see from the tests I've included, the default logging handler is set to INFO by default. You need to change that Handler's level to see FINE messages (also shown).
import java.util.logging.Handler;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.junit.Test;
public class SimpleLoggerTest {
private void logMessages(Logger logger) {
logger.warning(getLoggerName(logger) + ": warning message");
logger.info(getLoggerName(logger) + ": info message");
logger.fine(getLoggerName(logger) + ": fine message");
}
private String getLoggerName(Logger logger) {
String loggerName = logger.getName();
if (loggerName.isEmpty()) {
return "[root logger]";
}
return loggerName;
}
private void listHandlerLevels(Logger logger) {
for (Handler handler : logger.getHandlers()) {
logger.info(getLoggerName(logger) + ": handler level = " + handler.getLevel());
}
Logger parentLogger = logger.getParent();
if (null != parentLogger) {
for (Handler handler : parentLogger.getHandlers()) {
logger.info("parent logger handler (" + getLoggerName(parentLogger) + "): handler level = " + handler.getLevel());
}
}
}
private void setHandlerLevels(Logger logger, Level level) {
for (Handler handler : logger.getHandlers()) {
handler.setLevel(level);
}
Logger parentLogger = logger.getParent();
if (null != parentLogger) {
for (Handler handler : parentLogger.getHandlers()) {
handler.setLevel(level);
}
}
}
#Test
public void testLoggingLevel() {
Logger myLogger = Logger.getLogger(SimpleLoggerTest.class.getName());
Logger rootLogger = myLogger.getParent();
// list the default handler levels
listHandlerLevels(myLogger);
listHandlerLevels(rootLogger);
// log some messages
logMessages(myLogger);
logMessages(rootLogger);
// change the logger levels
myLogger.setLevel(Level.ALL);
rootLogger.setLevel(Level.WARNING);
// list the handler levels again
listHandlerLevels(myLogger);
listHandlerLevels(rootLogger);
// log some messages (again)
logMessages(myLogger);
logMessages(rootLogger);
// change Handler levels to FINE
setHandlerLevels(myLogger, Level.FINE);
// list the handler levels (last time)
listHandlerLevels(myLogger);
listHandlerLevels(rootLogger);
// log some messages (last time)
logMessages(myLogger);
logMessages(rootLogger);
}
}
Produces this output...
May 13, 2009 10:46:53 AM SimpleLoggerTest listHandlerLevels
INFO: parent logger handler ([root logger]): handler level = INFO
May 13, 2009 10:46:53 AM java.util.logging.LogManager$RootLogger log
INFO: [root logger]: handler level = INFO
May 13, 2009 10:46:53 AM SimpleLoggerTest logMessages
WARNING: SimpleLoggerTest: warning message
May 13, 2009 10:46:53 AM SimpleLoggerTest logMessages
INFO: SimpleLoggerTest: info message
May 13, 2009 10:46:53 AM java.util.logging.LogManager$RootLogger log
WARNING: [root logger]: warning message
May 13, 2009 10:46:53 AM java.util.logging.LogManager$RootLogger log
INFO: [root logger]: info message
May 13, 2009 10:46:53 AM SimpleLoggerTest listHandlerLevels
INFO: parent logger handler ([root logger]): handler level = INFO
May 13, 2009 10:46:53 AM SimpleLoggerTest logMessages
WARNING: SimpleLoggerTest: warning message
May 13, 2009 10:46:53 AM SimpleLoggerTest logMessages
INFO: SimpleLoggerTest: info message
May 13, 2009 10:46:53 AM java.util.logging.LogManager$RootLogger log
WARNING: [root logger]: warning message
May 13, 2009 10:46:53 AM SimpleLoggerTest listHandlerLevels
INFO: parent logger handler ([root logger]): handler level = FINE
May 13, 2009 10:46:53 AM SimpleLoggerTest logMessages
WARNING: SimpleLoggerTest: warning message
May 13, 2009 10:46:53 AM SimpleLoggerTest logMessages
INFO: SimpleLoggerTest: info message
May 13, 2009 10:46:53 AM SimpleLoggerTest logMessages
FINE: SimpleLoggerTest: fine message
May 13, 2009 10:46:53 AM java.util.logging.LogManager$RootLogger log
WARNING: [root logger]: warning message
This is what I was trying to convey in my other response.
Yeah, the JDK’s own logging framework can be a real bitch sometimes. As you correctly noticed the log levels of the root logger’s handlers are the problem. The solution you are proposing in your question is almost a good one:
Logger logger = Logger.getLogger("com.mycompany.myapp");
Handler handler = new ConsoleHandler(); /* or whatever you like. */
handler.setLevel(Level.ALL);
logger.addHandler(handler);
logger.setLevel(Level.ALL);
logger.setUseParentHandlers(false); /* <- important. */
When you create logger “below” that logger, i.e. with names like “com.mycompany.myapp.foo.Foo", they will log only to the logger you created. The parent logger of that logger (the root logger) will not get any log messages from your application but will receive messages from other parts of the JDK such as Swing or AWT.
Each Logger has a Handler with it's own log Level.
Is it possible that the Handler for your logger is not also set to ALL and is ignoring the messages? (This is messy, I know).
Here's a 2002 article on Java logging from O'Reilly.
Setting the property
com.mycompany.myapp.level = ALL
should do what you want.
But all the loggers will need to be named correcly with the relevant class names! E.g.
package com.mycompany.myapp;
public class MyClass{
private static Logger theLogger =
Logger.getLogger(MyClass.class.getName());
...
}
Another possible explanation is that your configurations aren't being passed correctly to the logging framework. Try feeding
LogManager.getLogManager().readConfiguration(InputStream);
your logging configuration right at startup. That is what I do and this works for me.
Related
I'd like to override the logging level for a specific package.
It works when the level is more restrictive, but it does not work when the level is less restrictive.
Here is an example:
public class Main {
private static final java.util.logging.Logger JDK_LOGGER = java.util.logging.Logger.getLogger(Main.class.getName());
public static void main(String[] args) {
JDK_LOGGER.fine("Hello fine (jdk)...");
JDK_LOGGER.info("Hello info (jdk)...");
JDK_LOGGER.severe("Hello severe (jdk)...");
If the specified package has a more restrictive level, it works:
handlers = java.util.logging.ConsoleHandler
.level = FINE
java.util.logging.ConsoleHandler.level = FINE
java.util.logging.ConsoleHandler.formatter = java.util.logging.SimpleFormatter
com.ice.level = SEVERE
It prints:
août 19, 2019 10:44:25 PM com.ice.foo.Main main
GRAVE: Hello severe (jdk)...
But if the specified package has a less restrictive level, it does not work as what I was expecting:
handlers = java.util.logging.ConsoleHandler
.level = INFO
java.util.logging.ConsoleHandler.level = INFO
java.util.logging.ConsoleHandler.formatter = java.util.logging.SimpleFormatter
com.ice.level = FINE
It prints:
août 19, 2019 10:55:50 PM com.ice.foo.Main main
INFOS: Hello info (jdk)...
août 19, 2019 10:55:50 PM com.ice.foo.Main main
GRAVE: Hello severe (jdk)...
But, because FINE > INFO > SEVERE, I was expecting to see the 3 logs (fine, info and severe).
Where is my mistake?
Thx.
Your mistake is in not realizing that the package filter and the handler filter are applied independently, i.e. as-if they were AND'd.
The purpose of the ConsoleHandler.level filter is to reduce the console output, while allowing e.g. a file handler to log everything. It is mainly used when you are logging to both console and file at the same time.
As such, the handler level cannot be overridden.
The reason console output is usually filtered more than file output, is that console output is relatively expensive, performance-wise. You don't want large volume of output to the console, so finer-grained log messages are usually filtered out.
When I log a message in the code the server prints twice the same message with the only difference of the date at the beginning.
I'm using the default log configuration that comes with the server Wildfly 10.
Server.log
09:43:09,122 INFO [es.myapp.business.scheduler.boundary.Job] (default task-91) ----------INIT Job Mon Nov 20 10:05:08 CET 2017
2017-11-20 09:43:09,122 INFO [es.myapp.business.scheduler.boundary.Job] (default task-91) ----------INIT Job Mon Nov 20 10:05:08 CET 2017
Job.java
import org.apache.log4j.Logger;
...
public class Job {
protected Logger logger = Logger.getLogger(getClass().getName());
public void execute() throws IOException {
logger.info("----------INIT Job " + new Date());
}
}
Wildfly logging.properties
# Note this file has been generated and will be overwritten if a
# logging subsystem has been defined in the XML configuration.
# Additional loggers to configure (the root logger is always configured)
loggers=sun.rmi,org.jboss.as.config,com.arjuna
logger.level=INFO
logger.handlers=FILE,CONSOLE
logger.sun.rmi.level=WARN
logger.sun.rmi.useParentHandlers=true
logger.org.jboss.as.config.level=DEBUG
logger.org.jboss.as.config.useParentHandlers=true
logger.com.arjuna.level=WARN
logger.com.arjuna.useParentHandlers=true
handler.CONSOLE=org.jboss.logmanager.handlers.ConsoleHandler
handler.CONSOLE.level=INFO
handler.CONSOLE.formatter=COLOR-PATTERN
handler.CONSOLE.properties=enabled,autoFlush,target
handler.CONSOLE.enabled=true
handler.CONSOLE.autoFlush=true
handler.CONSOLE.target=SYSTEM_OUT
handler.FILE=org.jboss.logmanager.handlers.PeriodicRotatingFileHandler
handler.FILE.level=ALL
handler.FILE.formatter=PATTERN
handler.FILE.properties=append,autoFlush,enabled,suffix,fileName
handler.FILE.append=true
handler.FILE.autoFlush=true
handler.FILE.enabled=true
handler.FILE.suffix=.yyyy-MM-dd
handler.FILE.fileName=/home/u24282/servers/wildfly-10.1.0.Final/standalone/log/server.log
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
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
Are you perhaps piping your WildFly process output to the log file? Or, are you running in domain mode maybe?
I have used java util logging for my application. I noticed that certain properties such as the month name and even certain log levels are getting printed in German.
Dez 10, 2015 8:50:26 AM com.kube.common.HidCommunication readFromHidDevice
SCHWERWIEGEND: Time - Barcode Message read from the Device: 2015/12/10 08:50:26:992
Though I have specified the level as Level.SEVERE, why is it printing it as "SCHWERWIEGEND" in German? Please advice.
How can multiple log levels added to the same log file in log4j?
For example:
log4j.rootLogger=INFO,WARN,stdout,file
It gives the log4j error when application start as:
Could not instantiate appender named WARN.
The purpose of the threshold is to tell log4j to ignore all logging requests with a priority lower than what you specify. Specifying a given threshold does not limit you to logging with that threshold.
FileAppender fa = new FileAppender();
fa.setThreshold(Level.INFO);
fa.setAppend(true);
Logger.getRootLogger().addAppender(fa);
In the above code, the appender has been configured to operate with a threshold of INFO. This means that the following code will not log, because DEBUG is a lower priority than INFO:
Logger logger = Logger.getLogger(SomeClass.class);
logger.debug("This will not log");
But this code will log:
logger.warn("This debug message will log.");
logger.error("And this error message will also log.");
In this case, both WARN and ERROR have a higher priority than INFO.
The first piece of code is doing almost exactly the same thing as the second one. But the hierarchal propagation of Log record is different. Can someone please explain why its happening. Thanks
Logger log1 = Logger.getLogger("Test1");
Logger log2 = Logger.getLogger("Test1.Test2");
Logger log3 = Logger.getLogger("Test1.Test2.Test3");
log2.setLevel(Level.WARNING);
log3.setLevel(Level.INFO);
log2.addHandler(new ConsoleHandler());
log3.addHandler(new ConsoleHandler());
log1.log(Level.INFO, "Message By: {0}",log1.getName());
log2.log(Level.INFO, "Message By: {0}",log2.getName());
log3.log(Level.INFO, "Message By: {0}",log3.getName());
OUTPUT: Nov 27, 2014 8:32:51 PM Test main
INFO: Message By: Test1
Nov 27, 2014 8:32:51 PM Test main
INFO: Message By: Test1.Test2.Test3
Nov 27, 2014 8:32:51 PM Test main
INFO: Message By: Test1.Test2.Test3
Nov 27, 2014 8:32:51 PM Test main
INFO: Message By: Test1.Test2.Test3
Logger logger = Logger.getLogger("d");
Logger logger1 = Logger.getLogger("d.1");
Logger logger1_2 = Logger.getLogger("d.1.2");
logger1 .setLevel(Level.WARNING);
logger1_2.setLevel(Level.INFO);
logger .info("msg:");
logger1 .info("msg: 1");
logger1_2 .info("msg: 1.2");
OUTPUT:
Nov 27, 2014 8:33:34 PM Test main
INFO: msg:
Nov 27, 2014 8:33:34 PM Test main
INFO: msg: 1.2
The lowest logger INFO message should not have propagated to the top as the middle one is set to Warning
That assumption is the source of your confusion. Record propergation is decsribed in the java.util.logging.Logger class documentation. Per the documentation:
By default, loggers also publish to their parent's Handlers, recursively up the tree.
The child logger is directly logging to the parent handler not the parent logger. So the level of the parent handler is what comes in to play not the level of the parent logger in this case.