log4j.xml in client jars - java

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.

Related

Java: How to Show Only System.out.print Calls?

I have built a console program in Java that uses external jars. I would like to observe my own System.out.println logs in the console, but they are being for the most part overwhelmed by messages on the console generated by some Logger (from the package org.slf4j;) which outputs massive amounts of text.
My issue is I cannot change the code that uses the Logger, because it is wrapped up in a jar and do not have its source. Is there a way to only show MY System.out.println calls? Or to otherwise quiet the messaged produced by this code I don't have source for?
Thanks!
There are a couple of approaches.
Change the log level or location. Unless it is set programatically, there is a configuration file for the SLF4j system. Modify the level so it displays only warn or only error. Alternatively, change the logger so that it goes to a file instead of stdout.
If you on a *nix system, and depending upon how you invoke the program, it is possible to do something akin to java PROGRAM | grep -v "org.slf4j" (or whatever the package is). This approach will remove any lines that match from the display.
It sounds like you're using a library that uses SLF4J for its logging, which is a fairly standard library. As helpful as it can be that there are all those libraries out there that do useful things, one of the challenges of using them is that one needs to integrate their logging into the one used by your application. SLF4J provides a standard logging interface that many libraries use, and allows them to bind to a standard logging implementation like Logback or log4j.
I would expect that most SLF4J-using libraries would depend on the slf4j-api only, and not have a specific logging implementation binding in their dependencies. By default, SLF4J uses the "no-op" logger, meaning that no logging is output (other than an initial warning that that's what it's doing). You could add the slf4j-nop library if that's what you want for your testing, to remove all logging.
But since you're actually seeing output, it seems that the library you're using is also for some reason including a binding to an actual logging framework. At that point, your options are:
Figure out how that binding and actual logging framework is getting into your classpath and remove it. (If you're using Maven to manage your dependencies, for example, you might add an <exclude> element for them.), or
Figure out what logging framework is being used (If you're using Maven, I find the dependency:tree output useful), essentially adopt using it for your application as well, and configure it to log the way you want, hiding the messages that you find irrelevant.
If we had more details on how you were getting this library's dependencies in your application (I've given information for Maven as it's what I'm most familiar with and it's rather standard), or what logging framework you thereby unwittingly added to your application, somebody may be able to direct you further.

Isn't it possible to configure logging INSIDE the application when using jboss AS 7.1.1.Final?

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.

add logging to a utility package

I'm creating a java open source utility package and I would like to know if it is ok to include logging (like log4j) into that package.
The dilemma is if I include log4j into my package, where will i output the log file, I wouldn't want the log file to be at a wrong place for the user, but i would still want to create logs for debugging.
As well there is the issue of the user wanting to integrate my logs into the project itself.
and how will he be able to do that.
What would you recommend is the best way of doing this?
Thanks.
I think the normal way to do it, is not include the Log4j Jar in the package and let the library user to decide which version of Log4j to use.
Also you don't have to worry about where to output the log file, since the user will have its own log4j.properties or log4j.xml configuration.
The library user can also decide which level of logging to use from your library or whether to suppress it. For instance with Amazon AWS libraries, I can tell that I only want warning messages or the output will be too verbose. In that case I add to my log4j.properties:
log4j.logger.com.amazonaws=WARN
Said that, I'd also remind you that a modern alternative to log4j is SL4J.

SLF4J, Common Logging, console output

I have this 3rd party library that has:
slf4j-api-1.5.5.jar
slf4j-jdk14-1.5.5.jar
jcl-over-slf4j-1.5.5.jar
I want to write some tests against this library and see its log output, and I don't want to add any more logging libraries (no log4j or anything else).
I understand that SLF4J and Common Logging are both logging abstractions so I probably need to write my own simple concrete logger (or maybe not, since jcl-over-slf4j includes org.apache.commons.logging.impl.SimpleLog?). If so, what interfaces should I implement, and more importantly, how do I set up SL4J/Common Logging to use my logger in my test? I read in the SLF4J docs that I have to modify the StaticLoggerBinder class... does that really mean that I actually have to download SLF4J sources, modify the class and recompile it?
We use SLF4J. It's very useful but several of the jars have confusing names and it's not real clear starting out to know which ones are incompatible.
SLF4J is the API you use for logging in your code (e.g. log.info("blah"). However, SLF4J has no configuration aspect to it. At runtime you add exactly one jar to the classpath that binds the API to the 'real' logging subsystem. If you want to use Log4J, add slf4j-log4j.jar or the StaticBinder jar for Simple or JDK, or Logback. You configure any of these logging implementations as you normally would without SLF4J.
There are several SLF4J modules available to redirect existing logging statements written using the APIs of Log4J, Apache Commons Logging, and java.util.logging to SLF4J. This allows you to setup a single logging configuration for all these disperate implementations. (This is very useful to avoid configuring both, say, Log4J and JUL if you have libraries that bind directly to any legacy logging framework.)
The SLF4J legacy page explains these concepts in depth. Heck, there is even a module to redirect Sysout.out/err to SFL4J.
To more directly answer your question: sure you can write your own logging implementation to go under SLF4J; but the only reason to do so is because you are already locked into some homegrown craptastic logging framework.
If you want to keep it simple, use the built-in (as of jdk 1.4) logger
https://docs.oracle.com/en/java/javase/19/docs/api/java.logging/java/util/logging/Logger.html
the jdk binding jar comes with slf4j. you want to make sure the jar is deployed to your webapp WEB-INF/lib dir or just in your classpath otherwise. See (slf4j.org/faq.html#where_is_binding) and this (slf4j.org/faq.html) for more information.
the jar you want to add to your classpath is slf4j-jdk14.jar. Note that the jdk logger is already available, this jar is the link between the slf4j interfaces and the chosen logger implementation. the jdk logging binding jar comes with the slf4j distribution. this should do it for you.
Your question leds me to believe that you have not read the the SLF4J user manual. It's a very short document. If after reading the document you still have the same question, then the document fails its purpose and needs to be clarified.
Anyways, you don't need to implement your own Logger class. Just use slf4j-simple which ships with SLF4J.

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.

Categories

Resources