Log4j - Logging to multiple log files based on the project modules - java

Consider this scenario:
I have a project with two modules and one common module as below (the package structure):
com.mysite.moduleone
com.mysite.moduletwo
com.mysite.commonmodule
In the above, the commonmodule classes can be used by other two modules.
The question:
I need to configureLog4J such a way that the log messages from moduleone and moduletwo goes to different log file. I can always do this using using category.
But the real problem is when I want to log the messages from the commonmodule also. So, when the commonmodule classes are called from moduleone the commonmodule log messages should go to the moduleone log file. If the commonmodule is accesse from moduletwo the commonmodule log messages should go to moduletwo log file.
Is it possible to configure Log4J in this fashion? Any comments?
PS: I think I made my question clear. If any confusion, leave a comment, wil try to clear it. :)

Is it possible to configure Log4J in this fashion?
In short, it is not with log4j unless you write a custom filter. And that filter would need to capture and analyse the call stack for each log event that makes it to each log appender ... which would be expensive.

I'm in agreement with #Stephen C about not being able to do so with Log4j without an expensive custom logger.
Another similar logging framework called Logback supports two options which may be enough to remove the need for a custom appender. They are called MDC (Mapped Diagnostic Contexts) and Markers.
Markers provide a way to add a custom piece of information to a logging statement, and you could (depending on how the common package is used) pass in a Marker to use depending on which module is using it.
MDCs could be used by setting them just before going into code in the common module and then unsetting them when leaving.
It also has a filter which can filter by appender on either.

Related

java.util.logging stops working when I incorporate a library that uses Log4j 2

I have an existing application that logs messages using the java.util.logging API. As far as I can see, there are no configuration files for it in the framework, though there is some code to create a file appender. When I run the application, I get log messages to the console and to a file.
Now, I need to incorporate a library that uses Log4j 2. When I do so, I lose the console logging from the main application (though log messages still get written to the file appender that is created programmatically).
I imagine that, since the file appender is working in the original application, that I can solve my problem by also programmatically creating a console appender in the main application. However, I don't know if that's right or a kludge.
So, my question: is there anything general that I need to know about making java.util.logging and Log4j 2 interoperate? If the original application is not coded properly or according to best practices, I can change it.
Now, I need to incorporate a library that uses Log4j 2. When I do so, I lose the console logging from the main application (though log messages still get written to the file appender that is created programmatically).
The
Log4jBridgeHandler will remove handlers if the install method is called from code. You can always print the log tree to see what handlers are attached or attach a tool like JConsole to inspect the logger tree with and without the 3rd party lib.
I imagine that, since the file appender is working in the original application, that I can solve my problem by also programmatically creating a console appender in the main application. However, I don't know if that's right or a kludge.
Programmatic configuration of the logger tree should be done with the LogManager config option:
A property "config". This property is intended to allow arbitrary configuration code to be run. The property defines a whitespace or comma separated list of class names. A new instance will be created for each named class. The default constructor of each class may execute arbitrary code to update the logging configuration, such as setting logger levels, adding handlers, adding filters, etc.
Create a stand alone named class that just installs the handlers in the constructor.
Set the java.util.logging.config.class system parameter to the name of your class.
Otherwise if you have a logging.properties you set config to your class name.
So, my question: is there anything general that I need to know about making java.util.logging and Log4j 2 interoperate? If the original application is not coded properly or according to best practices, I can change it.
The java.util.logging.LogManager can only see classes on the system class loader. In that case log configuration in code is required to gain access to the correct classloader.
It might be easier to remove all JUL configuration and bridge to Log4j2. You can then leverage the configuration needed through that framework.

configuring slf4j to store logs in different files based on log level

I am using slf4j+log4J in Spring.
I want to store logs in different files based on log levels and also in one common file,so that I will first check this common log file and later review individual level logs files.
In short all level logs in one log file and then individual level logs in individual files.
Please guide me how to do this?
Also ,suggest suitable purpose of the levels keeping live projects in view.like where to use info,debug etc.
It should be straight forward. I am not giving the config directly but I think it should be easy for you to figure out the real config.
First, in the root logger (or the parent logger you want), point to several appenders, e.g. FILE_ALL, FILE_ERROR, FILE_WARN etc
Then declare FILE_ALL as normal file appender, which accept log event of all levels.
For other "level-specific" appender, it is still a normal file appender, PLUS a filter config. You may make use of LevelMatchFilter and declare the "level to match" as the corresponding level of the file.

logging frameworks and logback.xml

While creating an example using Java and the com.alvazan.orm.api library, the use of "System.out.println" is prohibited.
One of the first and most simple Java exercises learned is "Hello World", also using the
"System.out.println" (...also known as logging, or returned requested data found in the console?)
When using Eclipse, logging is turned off by modifying the logback.xml file (ctrl-shift-R and typing in logback.xml)
From there;
<logger name="com.alvazan.orm" level="WARN"/>
is the line to add to the logback.xml file so that only startup logs appear.
In addition, two more logs such as....
2012-09-14 22:05:08,067 com.alvazan.test.FactorySingleton createFactory
INFO: CREATING FACTORY FOR TESTS
2012-09-14 22:05:08,809 com.impetus.annovention.ClasspathDiscoverer processFile
INFO: adding folder to scan=file:/C:/AAROOT/workareas/area1/playorm/eclipsegen/
are used.
Just clarifying that all information is typed into the logback.xml file?
Is there a diffrent file to use(other than logback.xml)?
Or is the end-user to use, for instance, "com.alvazan.test.FactorySingleton createFactory"; and "com.impetus.annovention.ClasspathDiscoverer processFile"?
Finalizing this question, is the file path for the preceeding necessary?
Thanks for your time,
Ryan
In response to Brett, and additional information/questions,
How is your root logger configured? You are only setting WARN for com.alvazan.orm, so if your root logger is INFO, then com.alvazan.test INFO's will be logged.
Hey Brett, thanks for the reply...
As for the root logger configuration, I believe the value is set at "INFO".
That being said, I would want to set "INFO" to "WARN", to prevent the use of
"System.out.println"
Also in the previous question, I mentioned:
2012-09-14 22:05:08,067 com.alvazan.test.FactorySingleton createFactory
INFO: CREATING FACTORY FOR TESTS
2012-09-14 22:05:08,809 com.impetus.annovention.ClasspathDiscoverer processFile
INFO: adding folder to scan=file:/C:/AAROOT/workareas/area1/playorm/eclipsegen/
com.alvazan.test.FactorySingleton
and
com.impetus.annovention.ClasspathDiscoverer (diffrent package within same library)
Different locations found within the same library...
Do i need to do the logback process for the other files, or *package, or doing it one time within the same library, should suffice for all? Or do I adjust additional values?
Your first statement....
"While creating an example using Java and the com.alvazan.orm.api
library, the use of "System.out.println" is prohibited."
In general, no one uses in System.out.println. Hibernate does not, JBoss does not, tomcat does not. They all use a logging framework so you can configure each and every log in production and each company using tomcat or jboss or hibernate can configure it differently. If these programs use System.out.println, customers would have no control and your server would ALWAYS run slow as you NEVER want "all" logging and there is no way to turn System.out.println's off!!!!! they are always on. log.info can be turned off and on.
The most complete answer on configuring logback can be found in their documentation
http://logback.qos.ch/manual/configuration.html
Just clarifying that all information is typed into the logback.xml
file?
I am not sure what you mean by this question. logback.xml is the configuration for a logging library called logback which you can find at the link above.
Is there a diffrent file to use(other than logback.xml)?
logback has other options like a groovy file to configure it, but playOrm is using only logback.xml though any client can decide what configuration file they use since playOrm discards the logback.xml file that is checked in when delivering to other projects.
Or is the end-user to use, for instance, "com.alvazan.test.FactorySingleton createFactory";
and "com.impetus.annovention.ClasspathDiscoverer processFile"?
I am very confused by this question. The end user should not be using FactorySingleton(neither directly nor indirectly AND that class is not even in the jar because it's in the test package). The end-user will be using ClasspathDiscoverer only indirectly...in fact, end-user won't even know about these classes.
Finalizing this question, is the file path for the preceeding necessary?
Are you trying to ask is the file path in logback.xml necessary? If you want to know more about how logback works, you need to read alot of the documentation. Basically, you can do stuff like com.alvazan level=WARN to turn any classes in com.alvazan.** to warn level(This is recursive and applies to children, grandchildren, etc. etc.). The ROOT logger is always defined as well in logback.xml and is the level for ALL classes in a all packages unless overridden.
yes, the root logger in playorm is set to warn.
At the bottom of the picture you show(your picture is cut off so not in that picture), there is a "source" tab and you may want to click that to view the xml better and it would match up with logback's documentation better as well. Here is a link to the file I bet you are looking at..
https://github.com/deanhiller/playorm/blob/486079cfefbd2b4b79e99652b24c146572663dda/input/javasrc/logback.xml
root logger is clearly set to info and could be set to warn if you want.
So, what do you want. Do you want those two log statements to go away and be turned off? Do you want ALL log statements to be turned off except WARN?
If you want all to be turned off in ALL software libraries, just change the root logger to "WARN". If you want to turn just FactorySingleton off you can add this line
<logger name="com.alvazan.test.FactorySingleton" level=""WARN"/>
If you want all of com.alvazan logging turned off instead of just everything in com.alvazan.orm as you also want com.alvazan.test off as well, BUT you want all other libraries to still be on(BUT always want WARN on which you generally should want), then you could change this
<logger name="com.alvazan.orm" level=""WARN"/>
to the following instead
<logger name="com.alvazan" level=""WARN"/>
Your best bet to understand logback though is to read logback documentation.
How is your root logger configured? You are only setting WARN for com.alvazan.orm, so if your root logger is INFO, then com.alvazan.test INFO's will be logged.

LOG4J as a singleton, anyway to avoid log4j logging conflicts in web environment

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.

log4j.xml in client jars

I have some jar files that will be distributed to clients that are using log4j for logging. My question is should I include a log4j.xml configuration in the jar file or have the client provide one if they want logging?
My feeling is to leave the log4j.xml configuration file out of the client jars, since the apache jar files all come with log4j logging, but sans log4j.xml.
Yes, leave it out. It's an utter nuisance when your log4j configuration file is ignored because one of the 60 third-party libraries of your app contains its own.
The good thing about log4j in your case is that your jar really shouldn't have to worry about it. The basic use case of log4j is:
Obtain a logger object for the current class
Call one of the methods on that logger, such as debug("some message");
If the jars you are shipping are to be used by a larger application, then ideally your code will only do the two steps listed above. In this way, your code will simply obtain logger objects from the already-configured log4j instance in the client's application. Your production code is then decoupled from having to know how to configure log4j.
Any logging you need to see for your development of the jars can be accomplished by configuring a log4j instance in unit test setUp() methods or something similar that won't get bundled with the production code going to the client.
I would put a default log4j configuration that you expect will be useful to your clients in the documentation. This way interested people can see what logging options you have (usually certain classes have more interesting log messages, from the user's perspective). I find it annoying when I have a third-party lib using log4j and it has no documentation, and there are log messages filling my screen and I have to try to figure out how to enable or suppress certain log messages.
If you are using log4j in your application then you include it in your project. If you are not, then why would you put it in there? What if client A wants log4j version 1.2 and client B wants log4j version 1.3.
Let them decide what they need for their projects and worry about what you need for yours.
I would add the configuration xml and load it up with instruction for the user showing different configuration and options. This will make it easier for either them or support to enable addition logging.

Categories

Resources