Not compile code blocks when publishing? - java

I have many lines i just use for debugging and helpers. Is there a way i can mark these so they do not compile when publishing a project but still can use when running/debugging my program within Eclipse? Even better would be to mark a certain field as debug only and discard everything that has to do with that field completely when publishing.
I understand this might get one in trouble when using fields like that and using that in critical parts of the code. But i often find myself initializing a lot of debug fields then comment them out which results in errors down the line if i do not comment those out as well.
So is there some way to handle this in a better and more efficient way?

Put your code inside an if statement that refers to a final static boolean constant in another class. An if statement like if (DEBUG) that effectively says if (false) (because DEBUG is false) is not compiled by the Java compiler.
public class Debug {
public final static boolean DEBUG = true; // or false
}
public class X {
public m() {
if (Debug.DEBUG) {
// Do some timing or displaying mouse positions, or whatever.
}
}
}
If you want to verify that this works, you can use the javap disassembler: the compiler won't generate code if your DEBUG constant is false, but if DEBUG is true it will.
For further reference, the Java Language Specification (linked) has a section on conditional compilation, "Example 13.4.9-2". This explains what I've described above.

Use the trace level of your favorite logger, e.g. log4j.

Yes. Use a logging framework.
A logging framework exists to allow developers to write out important events to either the standard command line, to a file, or anywhere else they desire. Java comes with a built-in (albeit primitive) logging framework: java.util.logging.
Here's a sample of it in action.
Logger logger = Logger.getLogger("foo-logger");
logger.log(Level.INFO, "This is a log statement at a rather standard logging level - use when you want to log information out.");
logger.log(Level.WARNING, "This is a log statement at a rather moderate logging level - use when things warrant looking into but aren't mission critical.");
logger.log(Level.SEVERE, "This is a log statement at a rather high logging level - use when an (often irrecoverable) error has occurred.");
If you use that, then you'll see something similiar to this in your terminal:
Aug 23, 2014 10:05:24 AM com.stackoverflow.sandbox.Formatting main
INFO: This is a log statement at a rather standard logging level - use when you want to log information out.
Aug 23, 2014 10:05:24 AM com.stackoverflow.sandbox.Formatting main
WARNING: This is a log statement at a rather moderate logging level - use when things warrant looking into but aren't mission critical.
Aug 23, 2014 10:05:24 AM com.stackoverflow.sandbox.Formatting main
SEVERE: This is a log statement at a rather high logging level - use when an (often irrecoverable) error has occurred.
Other frameworks such as Log4J2 are more intuitive as to what the levels mean, as well as offer simpler options to log out to wherever you desire.

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

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

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.

How to remove debug statements from production code in Java

Is it possible for the compiler to remove statements used for debugging purposes (such as logging) from production code? The debug statements would need to be marked somehow, maybe using annotations.
It's easy to set a property (debug = true) and check it at each debug statement, but this can reduce performance. It would be nice if the compiler would simply make the debug statements vanish.
Two recommendations.
First:
for real logging, use a modern logging package like log4j or java's own built in logging. Don't worry about performance so much, the logging level check is on the order of nanoseconds. (it's an integer comparison).
And if you have more than a single log statement, guard the whole block:
(log4j, for example:)
if (logger.isDebugEnabled()) {
// perform expensive operations
// build string to log
logger.debug("....");
}
This gives you the added ability control logging at runtime. Having to restart and run a debug build can be very inconvenient.
Second:
You may find assertions are more what you need. An assertion is a statement which evaluates to a boolean result, with an optional message:
assert (sky.state != FALLING) : "The sky is falling!";
Whenever the assertion results in a false, the assertion fails and an AssertionError is thrown containing your message (this is an unchecked exception, intended to exit the application).
The neat thing is, these are treated special by the JVM and can toggled at runtime down to the class level, using a VM parameter (no recompile needed). If not enabled, there is zero overhead.
public abstract class Config
{
public static final boolean ENABLELOGGING = true;
}
import static Config.*;
public class MyClass
{
public myMethod()
{
System.out.println("Hello, non-logging world");
if (ENABLELOGGING)
{
log("Hello, logging world.");
}
}
}
The compiler will remove the code block with "Hello, logging world." in it if ENABLE_LOGGING is set to true because it's a static final value. If you use an obfuscator such as proguard, then the Config class will vanish too.
An obfuscator would also allow things like this instead:
public class MyClass
{
public myMethod()
{
System.out.println("Hello, non-logging world");
Log.log("Hello, logging world.");
}
}
import static Config.*;
public abstract class Log
{
public static void log(String s)
{
if (ENABLELOGGING)
{
log(s);
}
}
}
The method Log#log would reduce to nothing in the compiler, and be removed by the obfuscator, along with any calls to that method and eventually even the Log class would itself be removed.
Another possibility is to put the if statement within your logging function, you get less code this way, but at the expense of some extra function calls.
I'm also not a big fan of completely removing the debug code. Once you're in production, you'll probably need access to debug messages if something goes wrong. If you remove all of your code level debugging, than this isn't a possibility.
This "trick" seems to make your debug statements vanished
public static final boolean DEBUG = false;
if (DEBUG) { //disapeared on compilation }
The post said that javac is smart enough to check the static final boolean and exclude the debug statements. (I did not personally try it)
For logging, I personally donot like to see code like:
if (logger.isDebugEnabled()) {
logger.debug("....");
}
realImportantWork();
The logging things distracts me from the realImportantWork(). The right way for me is:
logger.debug("....");
realImportantWork()
plus the config which excludes all debug messages on Production.
I mean that the logger.isDebugEnabled() control should be the job of the logging framework, not my job. Most logging framework support concepts like "logger", "LogLevel".. which can do the trick.
Use Java Preprocessor? (google foo low but this is a link to the old Joel forums discussing it)
Java contains some sort of preprocessor of its own. It's called APT. It processes and generates code. At the moment I'm not sure how this should work (I haven't tried it). But it seems to be used for these kind of things.
I would also highly recommend using a logging framework.
The logger.IsDebugEnabled() is not mandatory, it is just that it can be faster to check whether the system is in the debug level before logging.
Using a logging framework means you can configure logging levels on the fly without restarting the application.
You could have logging like:
logger.error("Something bad happened")
logger.debug("Something bad happend with loads more detail")
To directly answer your question: I don't know.
But here is another solution to your problem:
In my mind, there are two statements that collide with each other here: "debug statements" and "production code".
What is the purpose of debug statements? Help to get rid of bugs while (unit) testing. If a piece of software is properly tested and works according to the requirements, debug statements are nothing else but OBSOLETE.
I strongly disagree with leaving any debug statements in production code. I bet nobody bothers testing side-effects of debug code in production code. The code probably does what it's supposed to do, but does it do more than that? Do all your #defines work correctly and really take ALL of the debug code out? Who analyzes 100000 lines of pre-processed code to see if all the debug stuff is gone?
Unless we have a different definition of production code, you should consider taking out the debug statements after the code is tested and be done with it.

Categories

Resources