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.
Related
I need to create jar/library that does some stuff and writes some logs. For logs I was thinking about java.util.logging.Logger vs Logback. So the question is:
Should I prefer using java out-of-the-box logging or it's totally fine to include some third-party tools?
Or it should be purely the matter of my needs and which one to use doesn't really matter?
Use a facade, like slf4j. Think of it from the point of view of the person using your jar in their application. They will want all the logging going to one place, whether it is logging for your jar or for the rest of the application, they will not want to configure your library's logging separately.
Using a logging facade means your library writes to whatever log the rest of the application uses. The application should be in charge of logging, not your jar.
For which facade to use, slf4j seems like a better choice, commons logging can get in trouble where multiple classloaders are involved. See Difference between Simple Logging Facade for Java and Apache Commons Logging
One can use System.Logger
System.Logger instances log messages that will be routed to the underlying logging framework the LoggerFinder uses. System.Logger instances are typically obtained from the System class, by calling System.getLogger(loggerName) or System.getLogger(loggerName, bundle).
Loggers across libraries always were a pain. Java.util.logging incorporated Logging into the Standard Edition. Since Java 9 there is a Standard Edition way to integrate loggers.
This leaves the choice to the library user. No longer a mix, version blues, etcetera. The exact logger in a straight application could be java util Logger.
I'm starting a java project using slf4j for logging, gradle for building, and intellij for the IDE. How do I have intellij show the logs in the IDE when I run the project?
I've been attempting to find out how to put slf4j-simple in the classpath without declaring it in build.gradle. I would think that outputting logs to System.err would make them show in intellij. Do you think this is on the right track?
If you're familiar with slf4j, you know that the point of slf4j is to avoid declaring compile-time dependencies on logging frameworks.
In order to show output, there needs to be both slf4j-api as well as exactly one slf4j implementation binding (such as slf4j-simple or logback or whatever) in the classpath. This means:
If you're writing some kind of library (either for internal use by other modules you maintain, or "for the public"), you should depend only on slf4j-api and not have a compile- or runtime-declared implementation binding dependency.
If you're writing some end application, you need to include the implementation binding dependency, though it can probably be runtime-scoped rather than compile-scoped.
If you're expecting to "see" something when you "run the project", then either:
This is some kind of library, and you're doing some kind of unit or integration testing on your library, and so you should include an implementation binding dependency (like slf4j-simple) in your testing classpath (so that you see output while testing, but it's not used by whatever depends on your library). Or,
This is some kind of end application, so there should be an implementation binding dependency defined in compile or runtime scopes. If you're not sure what you want to use eventually, that's fine, just pick something to use for now that does simple logging to the console, since SLF4J makes it easy to replace later. Many logging frameworks easily support having separate configurations for "production" as opposed to testing, and I think it's fairly common to have the testing configuration basically just log to console.
IntelliJ IDEA will automatically display anything printed to the console. Also, many run configuration types have a "Log" tab that lets one specify log files to scan and also display while an application is being run. So, if you do want a testing logging configuration that has logging to multiple files and the like, you can generally configure IDEA to be able to let you see those as well while your application is running.
My experience is much more with Maven than with Gradle, but I believe the concept of dependency scope of compile, runtime, and test translate fairly straightforwardly to Gradle. Please ask if you need more specific clarification.
I want to log information to a file and want to know is there any advantage in using the Java Logger class versus my own personal method of logging?
I know using a logger I just add my own FileHandler to the logger. My personal method is just using a FileOutputStream.
Honestly your logger may be as good, it's pretty easy to put in log levels, filtering, etc.
The problem is when you start to put together code from 10 different groups each with their own logging. Some use System.out, some use some custom logger, some use log4j, ...
How do you parse or redirect the output? How do you filter all that output to just show your messages (For instance, filtering options in log4j won't prevent messages being sent straight to System.out).
It's a pretty big bulk change depending on which system you are moving from/to. Better just to use one very common one from the beginning and hope that it's the one everybody else on the project chooses.
The real question is: why would you bother writing your own logger when there are already existing libraries for doing that? Does your logger do something that the others don't? I kind of doubt it.
Standardization is another big issue - see Bill K's answer.
For most scenarios, a standard logging framework is the way to go. They are pretty flexible. But using your own implementation can also be a valid option, specially if we are not speaking of traditional logging (global debugging, problems, warning messages) but about specific informational meesages or accounting.
Among other factors, bear in mind that the standarization of logging allows third party libraries to cooperate. For example, if you have a standard web application using (say) Hibernate, and you have configured a standard Java logging lib, then you can not only log from your own code but also tell Hibernate to log debugging info to your log files (not necessarily the same files). That is very useful - almost a must.
If you code your own logging library with a plain FileOutputStream, you must decide -among other things- if you are going to keep the file opened, or reopen-append-close in each write - and you must take of synchronization and related issues. Nothing terribly complicated, though.
The logger gives to ability to define different levels of importance of the logged messages and the ability to use different sink for the output - the console, a file, etc.
Also it's easy to enable or disable only some type of message when using a logger - for example you don't want to see every debug message in production.
A logging framework allows you specify logging levels (e.g. log only critical messages, log only debug messages etc.). It also allows you to log to multiple destinations (e.g. to a file, to syslog etc.) and you can do this even after your application is fully built by just changing a config file and not changing any code. It can also format your logs easily depending on various parameters.
There are numerous other advantages since proper logging is a rather involved problem and these packages have been written to solve them. I think the important question, why would you not use them?
Well I would always prefer tested thing and approved by community over something which still need a lot of test. Logger allows you many things which will consume you some time to implement and to test the robustness of your solution. A big plus will be the know-how of the next person who will do something with your code, in case it will be your logger, normally it would take more time to learn how its working out, since there is much more examples and documentation for java.util.logger.
Like all others mention, there are more advantages to using a more common logging system over writing your own. To be honest, the Java util logging api is not nearly as extensive and configurable as other libraries you might find out there on the internet.
Bare in mind that rolling your own always has the disadvantage of being less tested and therefore more prone to break or skip some potentially crucial messages.
Personally I prefer using SLF4J since it allows me to plug in adapters for more commonly used logging frameworks and then let's me pick my own actual logging implementation, this solves most of the problems with different library writers preferring different logging frameworks. And if you consider yourself up for the task you could writer an implementation for SLF4J yourself ;)
I was wondering how should I proceed to debug while working with frameworks. Like specifically how can i tell which method is being called when a particular event happens.
thanks
raja
There are multiple ways to do this
1) Adding eclipse debug points (as described above)
2) Enable log statements. Most frameworks use logging (log4j, slf4j etc). So write a log4j.xml and create a category for "com.xxx" where all your framework classes have a package structure of com.xxx.yyy or com.xxx.aaa. Set the logging to be debug level and run the program (which uses the framework) analysing the log files should tell you
3) In eclipse if you cant run the program (so option 1 is not really possible) you can do a "Search usage" for an API to get who is using this. This option is however limited by the fact some frameworks use reflection, interfaces etc.
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.