Usually my logging is as follows:
private final Logger LOGGER = org.slf4j.LoggerFactory.getLogger(this.getClass());
Question: if I deploy my app as a war to a tomcat webserver, is the logging sync or async by default?
I'm asking because the tomcats logging.properties file defines the AsyncFileHandler throughout, like .handlers = 1catalina.org.apache.juli.AsyncFileHandler.
My question is, if all of my log statements are "passed" to that tomcat async file handler, and then logged async automatically?
Tomcat's logging is irrelevant if you are using a separate logging framework (such as SLF4J) in your web application. The SLF4J docs should tell you what is synchronous and what is asynchronous in that framework.
For the record, Tomcat's internal logging is synchronous until it gets to the AsyncFileHandler where it is buffered and written asynchronously on a separate thread (because writing to the file system is usually the slowest part of the logging call).
Related
I'm running a web application in a Weblogic server (Im not realy familiar with ).
Via JVM args a log4j config is passed with log level DEBUG to the application.
In the log file I can also find some log entries of DEBUG level.
So far so good.
During debugging I found some calls to logger.debug() that are not in the log file.
private static final org.slf4j.Logger logger = LoggerFactory.getLogger(ActionCtr.class);
The method call is definitely hit but nothing is written to a file.
If I do a step into during debugging I see in the logger:
org.slf4j.impl.JDK14LoggerAdapter(com.example.application.ActionCtr)
"java.util.logging.FileHandler.pattern" -> "%h/java%u.log"
And this leads to some questions for me (as I can not change the running application):
1) how could it bee that it uses the application is using a mixed up log4j and java.util.logging
2) How could I determine what is used in what classes?
3) There is no %h/java%u.log (~/java*.log) so I've tried to provide a java.util.logging conform properties file,
but this changed nothing - how an I determine where the running logger got its config from to configure it right?
1) how could it be that it uses the application is using a mixed up log4j and java.util.logging
Any of those logging frameworks could be used by the application directly or a dependent library that the application is using. It doesn't take too many dependencies to end up with a bunch of logging framework hitchhikers.
The SLF4J manual explains how that logging framework wrangles all of these other frameworks. This why you are seeing the org.slf4j.impl.JDK14LoggerAdapter.
How could I determine what is used in what classes?
Assuming you mean direct usages you can use Jdeps or Javap.
how an I determine where the running logger got its config from to configure it right?
The JConsole tool can access the JUL loggers at runtime. It will also show you all of the system properties which may include paths to logging.properties files.
If the application is pragmatically configuring the logging in an non-standard way then one option would be to use the java.security.debug using the access option. Run the application under a security manager will all or all required permissions but then enable access tracing.
I got a pecurliar behaviour when we stop a war in Weblogic 12c and then start it again. For some reason beyond my understanding Log4j2 stops writing to the log. It creates a new logfile but no entries are written.
I have debugged and sees that Log4jServletContainerInitializer and Log4jServletContextListener gets called just like they do when installing the war. I didn't notice any differences (unfortunally thats only a test of my attention span).
So do you have any idea of what might differ between install and start in regards of Log4J2 in Weblogic 12c and perhaps where to look for errors?
Your problem:
For some reason beyond my understanding Log4j2 stops writing to the log. It creates a new logfile but no entries are written.
Root Cause Analysis:
It is actually happen for some issues.
If your configuration for log4j is not correctly done in
log4j.properties file.
If your append properties are not made true.
If you use two loggers like Log4J and JUL, which uses the same
appneder(Stdout).
If your log4j jar file is not properly set to your classpath.
Solution:
Ans-1:
In your classpath, there is a setting of library that intercepts Log4J calls and converts them to JUL calls. Then it may cause this issue. So specify correctly that which importing is actually needed. java.util.logging.Logger or org.apache.log4j.Logger
Ans-2:
Properties are case sensitive. so your file name would be same with appender. and don't forget to make the appender to true.
log4j.appender.mainAppender.File=yourLogFile.log
log4j.appender.mainAppender.Append=true
Ans-3:
for Hibernate in particular, include slf4j in order to ensure that all the loggers co-operate with it.
Ans-4:
Sometimes this problem occurs for tomcat. If tomcat security enabled, and there were several permissions missing from the policy files, then this type of issue occurs. After giving permissions, it will work fine.
What Log4J does actually?
Log4J will only print messages which are info and up, and it will print them to both console and file. You can change this behaviour by changing INFO to ALL in log4j.rootLogger. If that doesn't work, add -Dlog4j.debug=true to your JVM arguments - that will make Log4J emit debug messages about itself (to System.out), so you can see what's going on.
Credit goes to #Isaac
Resource Link:
Log4J creates log file but does not write to it
Issue with log4j log not writing to file
UPDATE for log4j2:
Thanks a lot to rgoers for pointing the issue for log4j2. I am updating.
Root cause analysis from P.O.V of wilkinsona
When a restart is triggered, DevTools runs and then clears all registered shutdown hooks. One such hook is Log4J2's DefaultShutdownCallbackRegistry. Log4jContextFactory maintains a reference to the DefaultShutdownCallbackRegistry and LogManager holds a static reference to Log4jContextFactory. Log4J2's classes are loaded by the app classloader which means that there's a single LogManager, Log4jContextFactory, and DefaultShutdownCallbackRegistry shared across restarts.
When DefaultShutdownCallbackRegistry is run as part of a restart it stops the LoggerContext and sets its own state to STOPPED. As the restart proceeds a new LoggerContext is created and an attempt is made to register a shutdown callback for it with the registry. This fails as the registry's state is still STOPPED.
Solution:
Wilkinsona offered a hack method to solve the issue. That is given below. Try to cope with it.
Clearing out the callbacks in the registry before the Restarter runs the JVM's shutdown hooks is better. It prevents the exception from occurring, and logging continues to work after a restart.
private void prepareLog4J2ForRestart() throws Exception {
if (ClassUtils.isPresent("org.apache.logging.log4j.LogManager",
getClass().getClassLoader())) {
LoggerContextFactory factory = LogManager.getFactory();
Field field = ReflectionUtils.findField(factory.getClass(),
"shutdownCallbackRegistry");
ReflectionUtils.makeAccessible(field);
ShutdownCallbackRegistry shutdownCallbackRegistry = (ShutdownCallbackRegistry) ReflectionUtils
.getField(field, factory);
Field hooksField = ReflectionUtils
.findField(shutdownCallbackRegistry.getClass(), "hooks");
ReflectionUtils.makeAccessible(hooksField);
#SuppressWarnings("unchecked")
Collection<Cancellable> state = (Collection<Cancellable>) ReflectionUtils
.getField(hooksField, shutdownCallbackRegistry);
state.clear();
}
}
Resource Link:
Log4j 2.4 breaks rc1 devtools
Call context.close() rather than shutdown hook in DevTools restart
UPDATE2:
What kind of listener to add to my JEE application, to get the
expected behaviour?
For writing a listener, you can follow the tutorials
ServletContextListener Example
Writing a Listener Class
Servlet Listener Example – ServletContextListener,
HttpSessionListener and ServletRequestListener
I am using JULI logging framework in current Tomcat 7, providing a webapp specific logging.properties in my WEB-INF/classes folder.
Now I am looking for a way to change the log level of a logger at runtime.
I found several sources saying that changing the level of a logger at runtime might be possible via MBean Server. Unfortunately the appropriate MBean "java.util.logging.Logging" does not list my webapp specific logger, so I cannot execute the method "setLoggerLevel".
Does anyone know how to accomplish this? Thanks for any hints - excluding those suggesting to use log4j, that is... ;-)
Connecting JConsole to Tomcat and using the MBean tab to change the logger level is the ideal way. One issue is that the logger names don't exist unless the code has triggered the creation of a logger. You can't use the MBean to create a logger ahead of the code running. You should use JConsole to double check that the MBean itself doesn't exist.
Tomcat installs a custom LogManager that filters by the current class loader. JMX would be using the system class loader so it is possible that ClassLoaderLogManager won't return the logger names because the current classloader is not the web app classloader.
You could always create a servlet/jsp form or webservice deployed with the application to get the logger and set the level. You might have to pin each modified logger in memory to keep your logger level active. You can free the logger once the level is set back to null. You'll have to deal with security concerns with including such a page.
I wouldn't do this on a production server but you can configure a WatchedResource in tomcat that points to your logging.properties. Then any time that file is updated the web app is redeployed with the new settings. Watch out for ClassLoader leaks going that route.
I'm trying to essentially configure logging in three places, independently. Ideally, each component that is logging is fully unaware of the others. I'd like to use logback for this, as it seems to have some decent features and performance.
Here are the places from which I would like to log from and to:
Tomcat (7) should log to ${catalina_home}/logs/catalina.out, and should only log Tomcat events (deployments, server startup, etc)
A web application hosted in Tomcat should log to ${catalina_home}/logs/application.log, and should only log application things, like results of request validations or errors
A library that is included in the web application should log to ${catalina_home}/logs/library.log, and should only log things specific to that library, like time it takes to interact with some other web-service or library-specific errors
I know this is probably not the way it would work, but I would think I need to have a logback.xml file for each concern. Actually, I have created them and added to the classpath such that I get a "logback.xml occurs multiple times on the classpath" error.
I can see why I would need to consolidat my application and my library logback configuration to a single logback.xml file, but how would I keep the container logging config separate from the application+library logging config? Adding a logback config file to my application, as well as logback enabling Tomcat as described here, still yields a "multiple logback.xml" error. And, Chapter 9 of the logback user manual, which talks about separation of logging, doesn't really show how to separate the container and applications (just multiple applications), unless I am missing something there.
Enviroment: JSF 2.0, RichFaces 3.3.3, Facelets 1.1.15B1, Spring Framework 3.x, WebFlow 2.1, MyBatis 3.0.1, Oracle 10/11 g backend, SLF4j into Log4j. Well thats probably TMI since my issue is only a logging problem but better to be too thorough than not.
Anyways... I just setup SLF4j & log4j so now all of the internal facelets log msgs are being dumped into log4j & I can actually see them. In addition I setup Tomcat to also dump to log4j instead of it's custom version of JULI. Upon doing this everything appeared to be working great.... until i shut down the app.
Midway through the shutdown process my app started barfing up errors left 'n right because (which makes sense) Tomcat is trying to grab a logger instance AFTER spring has already cleaned up the logger bean.
Anyone familiar with this? I imagine it must be a common problem for anyone who has Tomcat using the non-standard logging mechanism. What is the best way around this?
I thought maybe if I just raised the log level then Tomcat wouldn't even try to log msgs because of the level req.s but the problem occurs when tomcat is trying to retrieve a logger instance so that didn't work.
I would move the Logger higher in the food chain.
I personally never configured log4j with spring relying on its own configuration mechanism (and hunting for where the heck it finds the properties file it is using in the process).
If you can you can opt to completely remove log4j from your war and rely on the log4j in the common tomcat library classpath. Then of course you are at the mercy of the tomcat configuration and you cannot access the log from inside your app, but it is always there during the complete lifecycle of your app.