Logger vs. System.out.println - java

I'm using the PMD plugin for eclipse and it gives me an error when using System.out.println() with the explanation:
System.(out|err).print is used, consider using a logger.
My question is - What is a Logger? How is it used to print to the screen? Why is it better?

See this short introduction to log4j.
The issue is in using System.out to print debugging or diagnostic information. It is a bad practice because you cannot easily change log levels, turn it off, customize it, etc.
However if you are legitimately using System.out to print information to the user, then you can ignore this warning.

If you are using System.out|err.println(..) to print out user-information on console in your application's main()-method, you do nothing wrong. You can get rid of the message via inserting a comment "//NOPMD".
System.out.println("Fair use of System.out.println(..).");// NOPMD
There is a "Mark as reviewed"-Option in the PMD-Violations Outline for this purpose.
Of course you can trick PMD with following code snippet:
PrintStream out=System.out;
out.println("I am fooling PMD.");
Outside of your main()-Method use a Log-System like eg Log4j.
UPDATE:
You can also modify the PMD-Rule "SystemPrintln" to use the following XPath:
//MethodDeclaration[#MethodName!="main"]//Name[
starts-with(#Image, 'System.out.print')
or
starts-with(#Image, 'System.err.print')
] | //Initializer//Name[
starts-with(#Image, 'System.out.print')
or
starts-with(#Image, 'System.err.print')
]
This will ignore System.out.println etc in any method named 'main' in your code, but check for System.out.println in initializer code.
I like this, because from my point of view, System.out.println is safe in method 'main(String args[])'. But use with caution, I have to check, where in the AST a System.out.println can occur also and have to adapt the XPath.

Loggers has multiple levels for logging.
If we are writing a real short program, just for learning purposes System.out.println is fine but when we are developing a quality software project, we should use professional logger and SOPs should be avoided.
A professional loggers provides different levels for logging and flexibility. We can get the log message accordingly. For example, group X messages should be printed only on PRODUCTION, group Y messages should be printed on ERROR, etc.
We have limited option for redirecting the messages in System.out, but in case of a logger you have appenders which provides numbers of options. We can even create a custom output option and redirect it to that.

This link provides more concise information about how to use Log4j: Don't use System.out.println! It has however only one little flaw, you should rather not put the library in /jre/lib/ext, but just in the runtime classpath of your application and ship it along.
The advantage is that you can use logging levels to indicate the importance of the information, so that you can configure externally which levels to show/hide in the output (so that you don't get annoyed by the -after all- useless information), how the output should look like (e.g. include a timestamp, thread ID, classname, methodname, etc) and where the output should be written to (e.g. the console, a file, an email, etc) and in case of for example files also how they should be created (e.g. group by year, month and/or day).
There are several logger implementations like the Java SE's builtin java.util.logging.Logger, the convenienced Apache Commons Logging, the popular Apache Log4j, its successor Logback, etc. You can use Slf4j as an extra abstraction layer to switch between any of those loggers whenever needed.

It appears that PMD is assuming that you are calling System.out.println() for debugging purposes; stuff like "Im in ur method, executing ur codez".
If you're doing that, you're going to have a much better time writing to a logger like Log4J, as it'll have multiple streaming options than just to screen.
If, however, you're doing a console application and are calling System.out as part of that, ignore the warning.

System.out.println is not good to use as it cannot be configured. In stead, Logger can be configured to log on various levels. It has whole lot of other features.

Related

Avoid Log4j/Slf4j debug enabled checks

Almost in every project I use either Log4j or Slf4j with logback to log events and almost everywhere I have to write something like
if (log.isDebugEnabled()) {
log.debug("I'm here doing this stuff");
}
Sometimes you don't see actual method logic with all these logging code.
I cannot remove log.isDebugEnabled() checks because even if I use Slf4j with {} feature some log information might be calculated and dropped if debug (or whatever level) is not enabled.
log.debug("Here is the data: {}", calculateDataFromSeveralDataSourcesDuh());
Here is the question: Is there a way to postpone log info calculation, so it is calculated only when appropriate log level is enabled without checks in application code?
What are possible options if I cannot use Java 8 and I'm using Slf4j api, so Log4j2 is not available?
By using Log4j2 and Java 8, you can easily make use of lambdas as described here, so in your case using debug(Message, Supplier) e.g.
log.debug("Here is the data: {}", () -> calculateDataFromSeveralDataSourcesDuh());
In case you can't use log4j2 or java 8, have a look at the concept of object rendering in log4j. You can set up your own object renderer for specific classes, whose construction would be cheap in comparison to rendering it (involving your calculateDataFromSeveralDataSourcesDuh call).
Assuming only parts of your debug information is costly to compute, it might be worthwhile to identify those situations and create custom classes (and corresponding object renderers) for them.

Java modifying console outputs for debugging

I've lately been overwhelmed by a large amount of messages being printed out to my console and not knowing where they are coming from.
is there any way to easily make a custom class similar to system.out.println that will print out a custom message along with
print the location of code the message is coming from
be toggleable by importance level
not be a pain to use
other helpful stuff?
Is there any way to easily make a custom class similar to
system.out.println that will print out a custom message along with
print the location of code the message is coming from
be toggleable by importance level
not be a pain to use
other helpful stuff?
You basically just described the usefulness of a logger. Java has pretty good logging frameworks like log4j, logback etc. Go with any one of those with a facade like sl4j. Using sl4j logging is as easy as System.out.println().
Just create a logger instance
private static final Logger log = LoggerFactory.getLogger(YourClassName.class);
And then print log like this
log.debug("Some log");
You can also write parameterized log messages with different levels (levels are used to denote importance level)
log.debug("Username={}", username);
log.trace("Username={}", username);
log.warn("Username={}", username);
This might be a good place to get started
http://www.javacodegeeks.com/2012/04/using-slf4j-with-logback-tutorial.html
Apache, does provide a logging class, along with its different levels. when using these you can actually specify the level you need to be printed and it would also help you identify the location from where it got invoked.
take the below line for example,
[2015-03-31 12:51:29,426] DEBUG {org.springframework.beans.factory.support.DefaultListableBeanFactory} - Retrieved dependent beans for bean '(inner bean)#1b534211#2': [org.springframework.web.servlet.mvc.method.annotation.ExceptionHandlerExceptionResolver#0] {org.springframework.beans.factory.support.DefaultListableBeanFactory}
It says, it got logged on 31st march at 12:51 hrs. The logger was used to debug some logic and it was invoked from org.springframework.beans.factory.support.DefaultListableBeanFactory class.
maybe you can use a OuputStream where you customize the output in the console

Is there a simple way to log everything in Java?

In teaching myself about Java errors and warnings, I have been exploring the documentation for java.util.logging.Logger. It seems as if everything within the Logger class is geared toward logging specific items--which makes sense from a practical persepctive.
However, I would like to be able to log everything that can be logged. It fits my learning style to look at everything that can be logged for a working program, then break things to see how the logfile changes. From there, it's easier for me to understand how to control what does and doesn't get logged.
I saw this post and this post with which I'm going to be starting, but I'm wondering if there are other resources that'd help me implement a "log everything" solution to increase my understanding of the class?
The logging classes will add messages to one or more appenders. You have to give it messages - it seems you're asking how you can log everything so I don't have to give a message to log. This isn't what loggers do. I think what you want is a debugger, and then step through your code.
Nothing logs on its own.
Given that you have two options:
Use a debugger instead. It matches more with your requirements. Step through the code and inspect variables on the fly. To use debugger, you can use any standard IDE like IntelliJ Idea or Eclipse.
Use AOP : Define an aspect which keeps logging all method parameters and return types. You could use Spring AOP for that
If you are a beginner, I would recommend option 1.
I am with the two other guys, but if you wanna see errors, you could use Exceptions with try-catch blocks like this:
try
{
//enter your code here
Test f = new Test();
}
catch(Exception e){
e.printStackTrace();
}

How to get condensed logging 'spring style'

Our logs, like most logs, get a bit verbose and most of that noise includes the fqcn of the class that did the logging.
I would like to have it log just the first letter of each package/subpackage until it gets to the class.
Example
com.mycompany.client.magensa.MockMagensaClient
Under normal circumstances this would log as:
c.v.c.m.MockMagensaClient
I can obviously write a custom logger but I am certain there is one I can already use. As I don't even know what this style is I am at a loss for what I am even looking for.
Anyone just wanna say: "Oh, you're looking at ... and you can find it ..."?
If you are familiar with log4j I would use use logback:
http://logback.qos.ch/
http://logback.qos.ch/manual/layouts.html#conversionWord
EDIT:
Apparently also supported in log4j:
http://logging.apache.org/log4j/1.2/apidocs/org/apache/log4j/EnhancedPatternLayout.html

Is it possible to prevent a class from using a method in java?

Suppose I have a class called Foo. This class will be modified by many people, and WILL print information to the console. To this effect, we have the following method:
private void print(String message){ ... }
which prints out to the screen in the format we want.
However, while reviewing code from other devs I see that they constantly call System.out.println(...)
instead, which results in barely-readable printouts.
My question is the following: is it possible to prevent any and every use of System.out.println() in Foo.java? If so, how?
I've tried looking this up, but all I found had to do with inheritance, which is not related to my question.
Thanks a lot!
N.S.
EDIT: I know that whatever I have to do to prevent the use of a method could be removed by a dev, but we have as a policy never to remove code marked //IMPORTANT so it could still be used as a deterrent.
EDIT2: I know I can simply tell the devs not to do it or use code reviews to filter the "errors" out but 1) I'm already doing it and it costs a lot of time and 2) the question is whether this is possible or not, NOT how to deal with my devs.
public methods are just that - public. There is no way to restrict access to them.
This kind of problem is usually "solved" by setting up some code-checker like PMD or checkstyle and integrating them into the continuous integration build. So violations of these stuff will be emailed to someone with a big hammer :-)
Although communicating that developers should not use System.out directly would be preferred, you could set System.out to another PrintStream, then use the alternative PrintStream in the private method. That way, when people use System.out.println they won't output anything but you'll still be able to use the alternative PrintStream... something like they do here: http://halyph.blogspot.com/2011/07/how-to-disable-systemout.html
Pre-commit hooks for your revision control system (SVN, Git, Mercurial) can grep for uses of System.{err,out} and prevent commit if they occur.
http://stuporglue.org/svn-pre-commit-hook-which-can-syntax-check-all-files/ is an example that takes an action for different changed files based on file extension for SVN. You should be able to modify that example to take an example based on some subset of Java files and reject if something like the following is true
egrep -q '\bSystem\.(err|out)\b'
You can redirect System.out calls to a streams that ignores the output or that redirects it to your logging system.
System.setOut(printStream);
You can also kill those using System.out.println in a production environment.
You can replace the OutputStream of System with your own implementation that would either throw an exception, or redirect the call to your own print implementation (which you would need to make public).
No, it's not possible to 100% prevent a class from ever using a specific method in Java.
Having that said...
My suggestion would be to add code analysis to your build process and failing the build on any occurrence of System.out.println. A good place to start if you're interested in going this route would be to check out PMD.
Also... have some constructive discussions with your developers and talk about why they're doing what they're doing. Good luck.

Categories

Resources