I have 4 java/Java EE applications-
Two are server based j2ee applications running in WebSphere.
Other two are standalone java applications.
My logging framework is log4j using log4j.properties.
Question 1: Can I have a same log file for logging from all the applications. Will it cause any file writing issues even if all the applications are writing at the same time?
Question 2: If all the applications can write without any issues, how can I pre-append the application name to each of the log statement?
Question 1:
I believe by default it will NOT work.
If you are using SLF4J, consider switching to LogBack. In LogBack's File Appender, there is a prudent mode that allow multiple FileAppenders in different JVMs to write to same log file (of course, all of them need to have prudent mode turned on)
http://logback.qos.ch/manual/appenders.html#prudent
Question 2:
You should NEVER make the log message different by manually logging your app name.
There are quite some way to do. The easiest way is: As you are having two different applications, you can have different logging config files for them. Just add corresponding app name information in the log pattern used by the appender will serve what you want.
Related
We are upgrading a legacy application to use log4j2. Because the application server (Weblogic 10.3.6.0) doesn't support servlet 3.0 we are at a cap of servlet 2.5 and can go as high as version Log4j version 2.3.
We have 4 JVMs running on the application server. We have 1 log4j2 config per server, so all 4 JVMs use the same config. We can seperate out the log files by appending the JVM name.
We were wondering if it's possible we can remove the JVM name, and have all JVMs write to the same logger? We are not able to use the async logger, and think there may be synchronous file locking issues.
Can anyone confirm if we can combine the log outputs of all 4 JVMS to 1 file, or it is better to separate them out per JVM.
Thank you
If you want to have multiple JVMs write to the same file you must use file locking (locking="true" on the File Appender). However, file locking is not supported on the RollingFileAppender as it cannot be done safely. File locking will also impact the performance of writing to the log files.
I am writing a small xml transformation layer in Java. I receive xml via web service, modify it, and then send the modified xml to another system. I then wait for a response and return the response to the original caller.
System A -> Me -> System B -> Me -> System A
I want to log the request I receive, the request I send, the response I receive, and the request I send. Basically I want to log the xml where each arrow is in my diagram.
My problem is with the RollingFileAppender. I try to roll at 10MB, sometimes it does and sometimes it doesn't roll. If it rolls a couple times, and then stops, it will continue to rename the rolled files from 3 to 4 and 4 to 5 and so on.
My best guess is that when the 10MB mark is crossed, there are multiple threads writing to the log file so the file cannot me renamed. I am hoping that Log4J has an easy solution for this, but if necessary, I am open to switching to a new logging framework. Thank you in advance for any help.
EDIT
Here is my properties file.
log4j.rootLogger=DEBUG, fileOut
log4j.appender.fileOut=org.apache.log4j.RollingFileAppender
log4j.appender.fileOut.File=/logs/log.log
log4j.appender.fileOut.layout=org.apache.log4j.PatternLayout
log4j.appender.fileOut.layout.ConversionPattern=%d %-5p %c - %m%n
log4j.appender.fileOut.MaxFileSize=10MB
log4j.appender.fileOut.MaxBackupIndex=10
log4j.appender.fileOut.append=true
EDIT 2 This is essentially a bump, as this post has a low number of views. I feel like this cannot be a unique problem. Any help is much appreciated. Thanks!
Log4J initializes itself at the classloader level. Within a certain classloader and its ancestors, Log4J can only be initialized once and the same Log4J configuration applies to all Log4J calls within the classloader.
As long as all of your logging calls are performed within the same Log4J configuration "realm", Log4J knows how to synchronize access to the physical file pointed at by the rolling appender configuration; when the time comes to roll, rolling is performed with no problem.
Things become problematic once you have two (or more) Log4J "configuration realms" using the same physical file for the rolling appender configuration. That could be:
Two different web applications on the same physical JVM
Two different web applications on two distinct JVMs
Same web application horizontally clustered on two distinct JVMs
(etc)
Log4J simply has no way of knowing who else, other than itself within the same Log4J configuration realm, uses that file. So, what ends up happening is that Log4J on System A attempts to roll the file (because it thinks that no other processes are accessing that file), and fails because someone on System B is using the file at the same time.
This is a known limitation of using file appenders, and you can't really blame Log4J for this: Log4J simply doesn't have the means of monitoring who else, other than Log4J in the same "configuration realm", is using that file.
For such usage scenario, you can use the Log4J socket appender.
If your scenario doesn't involve multiple Log4J "configuration realms", then try adding -Dlog4j.debug=true to the JVM parameters and see what exactly is going on during the file rolling operation.
For others that arrive here, check you are using RollingFileAppender NOT FileAppender!
Cut and paste errors are too easy, for me at least.
I also faced the same issue in my application.
Thanks to #Isaac found that I was doing DOMConfigurator.configure for the same log configuration in 2 web applications deployed in the application server.
I commented one of them and rolling over happened as expected.
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've 2 webapplications, want to log the log messages of these two web apps into only one log file. I tried this scenario, facing the issue as "If one web app logs the message into log, the second web app is not able log the message into log file". If I stop the server, the second app is able to log.Any help?
writing to the same file from multiple independant processes is a bad idea - only one of them can get a file lock, as evident from your issues.
what you need is a centralized logging server and have all of your applications log to that server over the network. see this question
You can use Log4J's SocketAppender for that, which is much cleaner - an example can be found in this article: log4j: How to use SocketAppender.
To be honest it is a bit overkill compared to having two independent logfiles for your processes.
Btw. your approach might have problems on distributed filesystems (e.g. NFS) - don't mix logfiles.
Hope that helped a bit.
*Jost
It is not good idea to put logging of two different applications to common log. Logging module lock the log file for writing. if other application is trying to access the same log, it wont get the lock.
I would avoid such things.
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.