Logger.setLevel() doesn't enable logging correctly - java

Situation: I have this log4j logger:
private static final Logger logger = Logger.getLogger(ThisClassName.class);
And am trying to set it programatically through:
Logger.getLogger(ThisClassName.class).setLevel(Level.DEBUG);
Still, DEBUG level prints are swalloed (while INFO prints are printed successfully).
Even this bit has no effect: Logger.getRootLogger().setLevel(Level.DEBUG);
Calling logger.debug("foo") reaches Category.forcedLog() and ConsoleAppender.doAppend(), and then fails (quits) at:
if(!isAsSevereAsThreshold(event.getLevel()))
Any idea why this is happening?

Your appender is configured with a threshold greater than debug, so while the logger doesn't ignore the entries, your appender doesn't record it. You need to configure the threshold of your ConsoleAppender to be DEBUG as well, either through your config file or programatically:
((ConsoleAppender)someLogger.getAppender("CONSOLE")).setThreshold(Level.DEBUG);
Config files are usually the more elegant solution for this sort of thing.
Edit: Note that apparently, any subclass of AppenderSkeleton (including ConsoleAppender) shouldn't have a threshold filter set by default. So it's likely that somewhere in your configuration you're actually manually assigning a threshold ( > Debug) to that appender, as #justkt hints.

Related

How do I suppress specific loggers in java.util.logging?

I'm trying to get processable logs of deep issues occurring with a JavaFX WebView.
This configuration (unsurprisingly) gives me masses of events unrelated to my problem:
handlers= java.util.logging.ConsoleHandler
.level= FINEST
java.util.logging.ConsoleHandler.level = FINEST
java.util.logging.ConsoleHandler.formatter = java.util.logging.XMLFormatter
I specifically get many events like this obscuring the real issue I am trying to find:
<record>
<date>2019-02-23T15:05:45</date>
<millis>1550946945429</millis>
<sequence>12936</sequence>
<logger>com.sun.javafx.webkit.prism.WCPathImpl</logger>
<level>FINE</level>
<class>com.sun.javafx.webkit.prism.WCPathImpl</class>
<method>addLineTo</method>
<thread>18</thread>
<message>WCPathImpl(1,361).addLineTo(600,516)</message>
</record>
I tried to suppress logging com.sun.javafx.webkit.prism.WCPathImpl by adding this to logging.properties:
com.sun.javafx.webkit.prism.WCPathImpl = OFF
That didn't work. That logger still logs a firehose of messages I don't need to solve this problem.
I'm trying this to debug okta-aws-cli.
How do I suppress specific loggers in java.util.logging?
The logger name isn't sufficient. You need to specify which property you are changing on the logger, in this case level.
Instead of this broken configuration:
com.sun.javafx.webkit.prism.WCPathImpl = OFF
Use this configuration specifically referencing the level property of the logger:
com.sun.javafx.webkit.prism.WCPathImpl.level = OFF

Why are my logs being removed?

I have an app in java using log4j as my logging jar, but when I try to debug my app and open the log file I find it short and with only the last lines I logged and the rotation files don't show any of the logs that I have seen before.
Is there something wrong with my configuration file? I have multiple projects pointing to the same log file, Could this be the problem?
Here is my log4j.properties:
log4j.rootLogger=ERROR,logfile
log4j.appender.logfile=org.apache.log4j.RollingFileAppender
log4j.appender.logfile.File=/opt/tomcat7/logs/mylogs.log
log4j.appender.logfile.MaxFileSize=500KB
# Keep one backup file
log4j.appender.logfile.MaxBackupIndex=2
log4j.appender.logfile.layout=org.apache.log4j.PatternLayout
log4j.appender.logfile.layout.ConversionPattern=%d %5p (%F:%L) - %m%n
Thanks
You specified level of root logger to be ERROR, while in most cases there won't be a lot of ERROR messages - maybe one-two per many INFO level messages, while you suppressed them: ERROR level allows only ERROR and FATAL messages to be logged. And it filders out any INFO, WARN, DEBUG, TRACE level. Usually you don't use such setup in development. And in production you usually suppress only some verbose classes/packages, but not everything like in config you posted (meaning here ERROR level applies to every class).
So I suppose you should replace ERROR with INFO in your config.
UPDATE: Also likely log4j simply doesn't see your config file. I encountered this issues several times personally and each time I had a workaround like this:
public class Log4JProperties {
public static void setupLog4j(){
String log4jPathFile = Log4JProperties.class.getResource("/log4j.properties").getFile();
Properties props = new Properties();
try {
InputStream configStream = new FileInputStream(log4jPathFile);
props.load(configStream);
configStream.close();
} catch (IOException e) {
System.out.println("log4j configuration file not found");
}
LogManager.resetConfiguration();
PropertyConfigurator.configure(props);
}
}
This is not necessary when I run code from inside Intellij, but when I run using Maven, logging doesn't work without calling this function in the beginning of the execution.
When you specify MaxBackupIndex=2 it will only keep last 2 backups, if log file fills up quickly old backup files will be overridden.
You might have to increase the MaxFileSize or MaxBackupIndex based on your file logging behaviour…
https://logging.apache.org/log4php/docs/appenders/rolling-file.html

Unable to set log level in a Java web start application?

Some logging levels appear to be broke?
I run a Java web start (which I will begin to call JWS from now on) application straight from a GlassFish 3.1.2.2 instance. The client has a static logger like so:
private final static Logger LOGGER;
static {
LOGGER = Logger.getLogger(App.class.getName());
// Not sure how one externalize this setting or even if we want to:
LOGGER.setLevel(Level.FINER);
}
In the main method, I begin my logic with some simple testing of the logging feature:
alert("isLoggable() INFO? " + LOGGER.isLoggable(Level.INFO)); // Prints TRUE!
alert("isLoggable() FINE? " + LOGGER.isLoggable(Level.FINE)); // ..TRUE
alert("isLoggable() FINER? " + LOGGER.isLoggable(Level.FINER)); // ..TRUE
alert("isLoggable() FINEST? " + LOGGER.isLoggable(Level.FINEST)); // ..FALSE
My alert methods will display a JOptionPane dialog box for "true GUI logging". Anyways, you see the printouts in my comments I added to the code snippet. As expected, the logger is enabled for levels INFO, FINE and FINER but not FINEST.
After my alert methods, I type:
// Info
LOGGER.info("Level.INFO");
LOGGER.log(Level.INFO, "Level.INFO");
// Fine
LOGGER.fine("Level.FINE");
LOGGER.log(Level.FINE, "Level.FINE");
// Finer
LOGGER.finer("Level.FINER");
LOGGER.log(Level.FINER, "Level.FINER");
LOGGER.entering("", "Level.FINER", args); // <-- Uses Level.FINER!
// Finest
LOGGER.finest("Level.FINEST");
LOGGER.log(Level.FINEST, "Level.FINEST");
I go to my Java console and click on the tab "Advanced", then I tick "Enable logging". Okay let's start the application. Guess what happens? Only Level.INFO prints! Here's my proof (look at the bottom):
I've done my best to google for log files on my computer and see if not Level.FINE and Level.FINER end up somewhere on the file system. However, I cannot find the log messages anywhere.
Summary of Questions
Why does it appear that logging of Level.FINE and Level.FINER does not work in the example provided?
I set the logging level in my static initializing block, but I'd sure like to externalize this setting to a configuration file of some sort, perhaps packaged together with the EAR file I deploy on GlassFish. Or why not manually write in some property in the JNLP file we download from the server. Is this possible somehow?
Solution for problem no 1.
After doing a little bit more reading on the topic, I concluded that a logger in Java uses a handler to publish his logs. And this handler in his turn has his own set of "walls" for what levels he handles. But this handler need not be attached directly to our logger! You see loggers are organized in a hierarchical namespace and a child logger may inherit his parents handlers. If so, then By default a Logger will log any output messages to its parent's handlers, and so on recursively up the tree (see Java Logging Overview - Oracle).
I ain't saying I get the full picture just yet, and I sure didn't find any quotes about how all of this relates to a Java Web Start application. Surely there has to be some differences. Anyways, I did manage to write together this static initializing block that solves my immediate problem:
static {
LOGGER = Logger.getLogger(App.class.getName());
/*
* This logic can be externalized. See the next solution!
*/
// DEPRECATED: LOGGER.setLevel(Level.FINER);
if (LOGGER.getUseParentHandlers())
LOGGER.getParent().getHandlers()[0].setLevel(Level.FINER);
else
LOGGER.setLevel(Level.FINER);
}
Solution for problem no 2.
The LogManager API docs provided much needed information for the following solution. In a subdirectory of your JRE installation, there is a subdirectory called "lib" and in there you shall find a "logging.properties" file. This is the full path to my file on my Windows machine:
C:\Program Files (x86)\Java\jre7\lib\logging.properties
In here you can change a lot of flavors. One cool thing you could do is to change the global logging level. In my file, this was done on row 29 (why do we see only a dot in front of the "level"? The root-parent of all loggers is called ""!). That will produce a hole lot of output; on my machine I received about one thousand log messages per second. Thus changing the global level isn't even plausible enough to be considered an option. Instead, add a new row where you specify the level of your logger. In my case, I added this row:
martinandersson.com.malivechat.app.App.level = FINER
However, chances are you still won't see any results. In solution no 1, I talked about how loggers are connected to handlers. The default handler is specified in logging.properties, most likely on row 18. Here's how my line reads:
handlers= java.util.logging.ConsoleHandler
Also previously, I talked about how these handlers in their turn use levels for what should trouble their mind. So, find the line that reads something like this (should now be on row 44?):
java.util.logging.ConsoleHandler.level = INFO
..and in my case I swapped "INFO" to "FINER". Problem solved.
But!
My original inquiry into this matter still hasn't provided an answer how one can set these properties closer in par with the application deployment. More specifically, I would like to attach these properties in a separate file, bundled with the application EAR file I deploy on GlassFish or something like that. Do you have more information? Please share!

How to control logging by 3rd-party components in webapp in Tomcat 5.5?

We are using Tomcat 5.5 on Linux. Our webapp uses log4j for its logging (functionally-based and not many loggers), and intentionally sets the additivity of the loggers to false. Our loggers log to our own logfile. None of them log to the console.
A problem we are having is that when the level of our loggers are set to DEBUG we start getting lots of debug logging in catalina.out from 3rd party components, particularly oscache.
There is a minimal log4j.properties file in .../common/classes:
log4j.rootLogger=INFO, A1
log4j.appender.A1=org.apache.log4j.ConsoleAppender
log4j.appender.A1.layout=org.apache.log4j.PatternLayout
# Print the date in ISO 8601 format
log4j.appender.A1.layout.ConversionPattern=%d [%t] %-5p %c - %m%n
There is no log4g.properties file in .../webapps/ourapp/WEB-INF/classes.
The first thing I tried was changing to log4j.rootLogger=ERROR, A1 but that made no difference.
The next thing i tried was creating a .../webapps/ourapp/WEB-INF/classes/log4j.properties file containing the single line
log4j.logger.com.opensymphony.oscache=ERROR
to see if that would stop the oscache logging. It did, but surprisingly (to me) it stopped all the unwanted logging, not just the oscache logging. So I commented the line out and tried again. Still no unwanted logging from anything. I moved the file aside and now the unwanted logging came back. I created a zero-length log4j.properties and all the unwanted logging went away again (!) While that's short-term what I want, it makes me wonder about what other logging is being thrown away (and why!). So I'm uncomfortable just relying on that.
The "Logging" chapter in the Tomcat 5.5 docs merely says that you can do per-app configuration by putting a properties file in WEB-INF/classes but doesn't (at least not that I could find) talk about how that interacts with the configuration specified in common/classes.
So:
How are the 3rd-party components logging to catalina.out in the first place? I guess their logging could bubble up to the root logger but then why do they still log even when the root logger level is turned up to ERROR?
Why does setting the logger level on our loggers to DEBUG make this logging start? We have our own names for our loggers so there is no way the oscache and other stuff could be ancestors of our loggers.
Why does even a zero-length WEB-INF/classes/log4j.properties file stop a whole bunch of logging?
How can I do this the "right" way and limit the logging in a meaningful way rather than relying on some weird (to me) side effect to turn it off?
Curiouser and curiouser. I tried matt's suggestion of turning on debugging. I also made a more extensive log4j.properties file for the webapp:
log4j.rootLogger=INFO, SSOA1
log4j.appender.SSOA1=org.apache.log4j.ConsoleAppender
log4j.appender.SSOA1.layout=org.apache.log4j.PatternLayout
# Print the date in ISO 8601 format
log4j.appender.SSOA1.layout.ConversionPattern=%d [%t] %-5p %c - %m%n
log4j.logger.com.opensymphony.oscache=ERROR
#log4j.additivity.com.opensymphony.oscache=false
When tomcat starts up I see:
log4j: Using URL [file:/srv/www/tomcat5/base/webapps/myapp/WEB-INF/classes/log4j.properties] for automatic log4j configuration.
log4j: Reading configuration from URL file:/srv/www/tomcat5/base/webapps/myapp/WEB-INF/classes/log4j.properties
log4j: Parsing for [root] with value=[INFO, SSOA1].
log4j: Level token is [INFO].
log4j: Category root set to INFO
log4j: Parsing appender named "SSOA1".
log4j: Parsing layout options for "SSOA1".
log4j: Setting property [conversionPattern] to [%d [%t] %-5p %c - %m%n].
log4j: End of parsing for "SSOA1".
log4j: Parsed "SSOA1" options.
log4j: Parsing for [com.opensymphony.oscache] with value=[ERROR].
log4j: Level token is [ERROR].
log4j: Category com.opensymphony.oscache set to ERROR
log4j: Handling log4j.additivity.com.opensymphony.oscache=[null]
log4j: Finished configuring.
But despite the fact the oscache logger is having its level set to error, I still see stuff like this in the log:
2011-03-30 14:53:22,076 [main] DEBUG com.opensymphony.oscache.base.algorithm.AbstractConcurrentReadCache - get called (key=AUDIT_KEY_OLDEST_TIMSTAMP)
If I'm forcing the oscache logger level to ERROR (which the log4j debug output says I am), then why is this DEBUG message being sent at all? The child logger overriding the level in code?
What I did notice is that if I uncomment out the "additivity" line for the oscache logger in the webapp's log4j.properties file then the logging really does go away. So it appears the oscache logging is relying on ancestor appenders and not its own. But then it seems all the weirder that setting the oscache logger level to ERROR isn't stopping these things.
You could configure log4j.properties to get only your code logs as below and put it inot different file than catalina.out too.
handlers = org.apache.juli.FileHandler
org.apache.juli.FileHandler.level=ALL
org.apache.juli.FileHandler.directory=${catalina.base}/logs
org.apache.juli.FileHandler.prefix=yourapp-name.
com.yourproject.module.package.level=ALL
I've figured out what the heck is going on. The problem is that buried down in the bowels of another part of the webapp is the following code that is run when that component is put into debug mode:
public static synchronized void setDebugOn(boolean debugOn) {
if (isAllDebugOn() ^ debugOn) {
setAllDebugOn(debugOn);
Enumeration en = LogManager.getCurrentLoggers();
while (en.hasMoreElements()) {
setDebugOn((Logger) en.nextElement(), debugOn);
}
setDebugOn(LogManager.getRootLogger(), debugOn);
}
}
public static void setDebugOn(String name, boolean debugOn) {
setDebugOn(getLogger(name), debugOn);
}
private static void setDebugOn(Logger logger, boolean debugOn) {
logger.setLevel(debugOn ? Level.DEBUG : Level.INFO);
}
In other words, when this component is put in debug mode, it also puts EVERY SINGLE LOG4J LOGGER IN THE WEBAPP into debug mode (which I've verified by changing the code to print out the name of every logger inside of the last method of those three. So blammo -- all the 3rd-party stuff that happens to use log4j starts getting its debug output logged regardless of what log4j.properties says. Sigh.
When I change the method with that loop to only mess with the levels of specific loggers related to that component then my log4j.properties configuration starts working as expected.

log4j - set different loglevel for different packages/classes

I use log4j for logging and i want to print all logger.debug statements in a particular class / selected package.
i set the cfg as below>
log4j.category.my.pkg=info
log4j.category.my.pkg.ab.class1=debug
but still only info messages are shown..
is this not the right way ?
Instead of using 'category' use 'logger'. Hence, these level are configured for entire log4j, and does not depend on appender, etc.
Following change works:
log4j.logger.my.pkg=info
log4j.logger.my.pkg.ab.class1=debug
Copying from my current log4j.properties:
log4j.logger.org.hibernate.tool.hbm2ddl=warn
log4j.logger.org.hibernate.sql=info

Categories