Is there a simple way to log everything in Java? - 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();
}

Related

Telling javac to ignore System.out.println()

i'm using System.out.println() (sout) for debugging and general state overview purposes while programming (which is especially helpful for network stuff). Since i want my code to be efficient at the end, is there a way to tell the java compiler to ignore souts?
I already tried some googling, but the solutions where very unsatisfying, like putting all souts inside an if with a global variable. (Tripling the lines and making code very unreadable if a lot of souts are needed)
Anyone know if such a compiler option exists (if not, why not?), or if there is some other more elegant solution then the one stated above. Thank you for your answers :)
Use logging. You can indicate a log level that normally won't be displayed, and with logging properties can be made to appear. This can be done controlled etc.
Logger.getLogger(getClass().getName()).log(Level.FINE, "...");
In fact there are many examples and aspects to logging. So if you want your code to be minimalistic but mature, use logging.
An alternative way would be to use unit tests, and to not output in the production code. This requires more strictness and allows to find regression errors.
And a third alternative would be to more liberally use (unchecked) exceptions, IllegalArgumentException, IllegalStateException. To have an informative fail-fast.
First I would like to say that the real answer to this question is to use a logging framework as others have shown.
But if you are committed to using System.out, you can still achieve the desired effect. In the below class, I change System.out (by using the System.setOut method) to another PrintStream that does not actually print anything.
import java.io.*;
class Sys
{
public static void main ( String [ ] args ){
System.setOut(new PrintStream(new OutputStream(){
#Override
public void write(int b){
}
}));
System.out.println("Hello World!");
}
}
My answer can be improved upon. For example, it will still convert objects to string for printing, but you can solve that by setting out to an overrided PrintStream class that does absolutely nothing.
But the more you improve upon it, the more you are just implementing a logging utility which someone else has already done. This is why I suggest logging is the real answer.

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.

Getting stack of invoked methods in java

i need to know which methods were invoked one by one in code. Simple step-by-step debugging doesn't help (need too much time). How can i do this? It would be really great do this without changes of code and saving result in file.
Since it seems that maybe you don't want to check the stack tree, just the order, you could check out BTrace or Adding logging with Java agent.
Before your program finishes, you could Thread.currentThread().getStackTrace(); and then print each of those elements. A stack trace shows you the order of execution in your thread.
Sounds like a cross-cutting concern, especially when you talk about not changing existing code.
AspectJ is available to do this work for you using pointcuts.
http://www.eclipse.org/aspectj/doc/released/progguide/starting-aspectj.html
Do you mean you want to log every method call that occurs in your program? If so, have a look at AspectJ - there's an example here which logs particular methods, but you can easily adapt it to cover all methods.
What about when you catch a Exception you can try to use printStackTrace() function to dump out what has been invoked.
try{
//Your code
}
catch(Exception e){
e.printStackTrace();
}
Run your code in debug mode, you'll be able to set breakpoints to pause the execution, proceed line by line, inspect variables, etc.. Basically all the IDEs have debug mode.

LOG4J call only for specific function

asking this as an experiences Log4j user:
We have a pretty big class with lots of debug statements (Logger.getLogger(class).debug("Borrowed connection "+con.getId())... you know what I mean :)
Now I suspect one specific function to not work as expected and I want only this one particular function to log the debug output, the rest of the Class should keep the "error" level.
is there a solution to this? Google wouldn't satisfy my this time :)
You could use an own loger per method even though that may be a little inconvenient.
Logger.getLogger(class.getName()+"#methodName").debug(..)
will allow to define the log lever per method.

Logger vs. System.out.println

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.

Categories

Resources