Currently we have J2EE applications that run on WebSphere and log4j 1.x is our company's standard for Java logging. We'd like to investigate the ability to change the log4j configuration xml file at runtime so we can change to the DEBUG level, for example, when problems are identified, and return to the ERROR level once those problems are cleared up and DEBUG is no longer needed. We'd like to do all this without having to recycle the application to reread the config file.
I see that DOMConfigurator.configureandWatch() is an available method that would allow the config file to be reread at runtime. However, because it spawns a separate thread that won't be shut down when the application is shut down, it is unsafe to run in a J2EE environment.
http://logging.apache.org/log4j/1.2/faq.html#a3.6
Does anyone know if this was fixed in log4 2? I haven't found anything definitive yet from the documentation and was curious if it is safe to change the config file at runtime in J2EE.
Re-reading the configuration file is not something you want to do in production. It means that you're changing resources which many app servers don't expect to change. Development environments can get away with it on the grounds that blowing up the app server isn't a big deal. It also means that your app might behave differently if it has to be restarted.
You're going to want to change the log levels programmatically. You can do this by using LogManager.getLogger() for the packages you care about. Once you have the logger, change the level to debug, and change it back when you are done.
Related
I want to put the configuration file of the log4j2 (v2.17.0) outside of the war file. Therefore, I can change the logging configuration without redeploying the war file. The log4j2-web.jar provides mechanism to configure the configuration file outside of the war file along with other features.
Unfortunately, I am not allowed to use the log4j-web.jar file in web application.
According to the log4j2 FAQ, it is not recommended to use LoggerContext to load configuration file because it is not part of the public API.
Question:
Is there any valid way to use log4j2 in the web application without log4j-web.jar file?
Question: Is there any valid way to use log4j2 in the web application without log4j-web.jar file?
There are two potential ways that you could dynamically update the logging configs without using log4j2-web.jar .
Ignore the FAQ's recommendation1 and use LoggerContext.reload to reload the configuration.
It is possible that the Log4j2 team could change something in a future version so that this approach no longer works. But this is unlikely (IMO) ... and you can deal with that problem if / when it happens.
Use Log4j2's automatic reconfiguration mechanism. Basically, you tell Log4j2 to regularly check the config file to see if it has changed.
However ...
If I was you, I would want to understand why you are "not allowed" to use "log4j-web.jar". Is it for security reasons? If it is, you may need to talk to the security people so that you fully understand the security reasons.
Q: Why?
A: Because you appear to be wanting to duplicate some of the functionality of "log4j-web.jar". It may be that it is the functionality you are trying to duplicate that is the root of your security team's concerns. And if that is the case, then implementing the functionality by hand (i.e. without using "log4j-web.jar") could potentially be worse ... from a security perspective!
So ... find out! This is NOT a case where "asking for forgiveness rather than for permission" is a sound strategy.
1 - Actually, I don't read this as a "recommendation". Rather, I read it as a "warning of potential consequences". If they really thought that using LoggerContext.reload this was a bad idea, I think they would have used more explicit language.
I read a lot but I couldn't figure out how I could specify for example the log level for specific classes.
Only way I could figure out was in the standalone.xml but why should I configure some application specific setting very general in the server? This complicates the deployment process unnecessary.
Isn't it somehow possible to define the specific log level and the output files somewhere inside the war without touching the server?
Btw. it doesn't matter if log4j or commons-logging or slf4j or whatever is used.
Using a logging.properties file or a log4j configuration file in your deployment will work in JBoss EAP 6.x and WildFly (formerly JBoss AS). Note though that a log4j configuration would only work if you use log4j for your logging facade.
That said I agree with Marko that this should probably be done in the server configuration. I would also encourage you to use the CLI or web interface rather than editing the raw XML as well. You can get some more information on the documentation.
I am sorry for not providing a direct answer, but consider this: the application being in charge of logging levels is a bad idea most of the time as this is something an AS admin should be able to change at any time. For example, the point of the DEBUG or TRACE log levels is to be able to place a lot of such statements in the code without hurting the production server's performance. However, once a bug is detected, you want to be able to lower the logging level without rebuilding the application. This should be a purely administrative task.
On the other hand, I do recognize the need to at least have a decent starting point for the logging configuration and I don't know of any architecture which would allow the application to provide defaults which are overridable by the server configuration.
I have a J2EE application running under GF2 and OS X 10.8.4 which has suddenly, and without an y apparent cause stopped logging all of the information my team expects it to.
When deployed under Windows or Linux this issue does not occur. We suspect that it is either an OS update or some issue with the logging subsystem.
The application uses SLF4j and I would like to know what it's doing and where it might be getting its properties from. Under log4j there is an option "-Dlog4j.debug" which writes to STDOUT and tells where it is loading its properties from. Is there an equivalent option in SLF4J?
slf4j is just a facade - an common API - for any of several different logging backends. How to do what you want, depends on which backend you use. E.g. logback has the debug attribute in the configuration file telling it to log verbosely what it is doing.
The best approach for slf4j in a web application is to use the jdk14 bridge, allowing you to directly use the glassfish logging system. As a web application is not allowed to directly use the underlying file system this is the only way you can be fully compliant and still log.
We have a j2ee web environment. The server is configured to share session and possibly classloaders across multiple webapps. Basically, one classloader could server multiple web apps.
This seems to cause issues with log4j. Different webapps could have different log4j configurations but the logging will move to the same file.
Reading online, it looks like log4j uses singletons a lot, in terms of the appenders and other functionality.
Is there a way to completely separate the log4j configurations from one webapp from the other.
Server: websphere6+
Log4j: 1.4.2
Java: 1.5
Example log4j.properties (webapp1):
log4j.appender.R=org.apache.log4j.RollingFileAppender
log4j.appender.R.File=/usr/local/file1.log
log4j.additivity.com.app=false
Example log4j.properties (webapp2):
log4j.appender.Z=org.apache.log4j.RollingFileAppender
log4j.appender.Z.File=/usr/local/file2.log
log4j.additivity.com.app=false
Right now, logging from webapp2 may appear in the webapp1 logs and vice verse. We don't want that.
Possible Solution:
It might be possible to add a custom file appender? Would that fix the issue and what code would I add to the custom appender?
Is it possible to change the log4j initialization. E.g., could I use some startup servlet to load logj4 for each webapp.
You have two ways to solve your problem:
Configure your app. server so it doesn't share classloaders across multiple webapps. When it does do that, because of log4j's nature, only one log4j.properties file will be loaded.
If you leave the app. server so it shares classloaders, then use one "master" log4j.properties file. In it, define appenders for root of every one of your applications (example com.mycompany.webapp1, com.mycompany.webapp2)
No solution is perfect. Particularly, the second one will be problematic if your web apps share some classes that use log4j. In that case, logs from both apps will end up in the same file.
Your problem is a common one. To understand more about this topic, google for "log4j and j2ee".
Edit: since solutions 1 and 2 aren't feasible, you could try something else:
Use log4j.properties file per application. In every one of them, define an appender for their root (as explained in solution 2), and set additivity to false. This also won't be perfect if there is any class sharing between them.
Configure log4j programatically for every application. Since they're legacy applications, this could be tough. One way to do it is to use ServletContextListener for every application and configure log4j on application startup. I haven't personally tried this, so I'm not 100% sure if there will be clashes due to shared classloaders.
Log4j won't be really updated anymore. Ceki Gülcü, who created log4j, stated that he will focus his efforts on slf4j and logback, to correct some mistakes he did during development of log4j.
I am trying to configure a custom layout class to Log4J as described in my previous post. The class uses java.util.regex.Matcher to identify potential credit card numbers in log messages. It works perfectly in unit tests, also in a minimal web app containing a single servlet. However when I try to deploy it with our app in JBoss, I get the following error:
--- MBEANS THAT ARE THE ROOT CAUSE OF THE PROBLEM ---
ObjectName: jboss.web.deployment:war=MyWebApp-2010_02-SNAPSHOT.war,id=476602902
State: FAILED
Reason: java.lang.LinkageError: java/util/regex/Matcher
I couldn't even find any info on this form of the error - typically LinkageError seems to show up with a "loader constrain violation" message, like in here.
Technical details: we use JBoss 4.2, Java 5, Log4J 1.2.12. We deploy our app in an .ear, which contains (among others) the above mentioned .war file, and the custom layout class in a separate jar file (let's call it Commons). We override the default settings in jboss-log4j.xml with our own log4j.properties located in a different folder, which is added to the classpath at startup, and is provided via Sapient's Carbon framework.
Update to #skaffman's answer:
The reason we have a separate log4j.properties file is the scheme propagated by Sapient Carbon. This basically decouples the configuration and data files from the application server environment, so that they are accessible via Carbon's lookup functionality and they can be stored in a directory external to the app server. We inherited this setup, and we hate it because it causes us lots of trouble with deployment, classpath issues etc. since it does not adhere to the JEE conventions. We aim to get rid of it in the long run, but it's gonna take time :-(
Even though the separate log4j.properties file is not best practice, it certainly works. It has been functioning in our app for years, and I could also make it work with a minimalist web app containing a single servlet (not using Sapient Carbon). If log4j.properties is put into the classpath, Log4J reads it properly when the web app is launched, and reconfigures logging accordingly.
Update#2: An interesting finding is that Matcher is not even used in MyWebApp, only in the Commons module (and another module, in a separate jar). In Commons, it has been used before, in a class called StringHelper, which is used indirectly by MyWebApp, via other modules.
I guess this rules out the possibility of two different Matcher class versions loaded by different classloaders. So my only remaining guess is that Matcher is loaded by two different classloaders when it is used from the jar and the war, and then attempted to pass from one to the other. This is explained by Frank Kieviet's excellent article. However, I believe that such a setup would cause a "loader constraint violation" rather than this form of the error.
Update#3: If I add this appender (example 3.8) to jboss-log4j.xml, the error disappears, and the server runs perfectly :-o This obviously has to do something with loading log4j.jar, because this setup requires the jar to be present in the server lib directory. It works also if I change the appender type to org.jboss.logging.appender.FileAppender, and set log level to WARN, which results in an empty ucl.log file. This may suit as a temporary workaround, but I am still eager to fully understand what's going on here.
What does this error message mean, and how can I fix it properly?
Epilogue
After a long wait, I finally got to eliminate Carbon from the logging process and migrate our logging config into server/conf/jboss-log4j.xml. This required that I publish our custom log filter class in a separate jar in the server/lib directory. After this, the class loading works again, without the workaround described in Update#3 above :-)
My first reaction is that in JBoss it's not possible to override the log4j configuration like that. JBoss isn't allowing log4j to locate its own configuration, as it normally would, the location of conf/jboss-log4j.xml is specified in conf/jboss-service.xml.
To my knowledge, all log4j configuration in a given JBoss server must be centralised in to a single file, usually conf/jboss-log4j.xml.
Have you tried, as a test, moving the contents of your log4j.properties into the existing conf/jboss-log4j.xml file? If that works fine, then the problem is almost certainly caused by your attempt to override log4j. Having said that, I'd be surprised if jboss/log4j is that fragile, but perhaps in certain cases, it rejects this.
you either have two classes of different signatures but the same path in your environment or you compiled against another signature of j.u.r.Matcher. Since this is standard Java API, I think you should check your source and compilation targets and the JVM runtime version of your JBoss installation.
Edit:
After that is ruled out, I'm sure, the classloader (the server's) that manages the appenders and tries to load the appender that's using your custom layout can't see the custom layout class instance. So you have two options:
Deploy your custom layout JAR to the server's lib-directory along with log4j.
Deploy log4j along with your application and isolate the application with your own classloader (jboss-app.xml):
<jboss-app>
<loader-repository>
com.myapplication:loader=MyClassLoader
<loader-repository-config>java2ParentDelegation=false</loader-repository-config
</loader-repository>
</jboss-app>
I hope, the problem will go away then.