Printing stacktrace only if level is debug - java

We are maintaining two different log files, one to log only error messages, and other for debug information. I don't want to clutter the error file with exception stack trace, so I have to add following two lines each time on catching any exception
try{
...
}
catch(Exception e){
log.error("Error during SOME_SERVICE {}" , e.getMessage());
log.debug("Exception ", e);
}
Is there any simpler way to do this, may be in a single line of code?

As suggested in the comments, I have two options, either live with it, or write my own custom logger that would do the expected behavior. For now, I leave it as is.
For custom logging there are tons of resources, so won't post the solution here.
Implement Custom Logger with slf4j

Related

Exception Handling in JS using Graal

I work on a Java application that makes fairly heavy use of Javascript to form the business logic/glue. It runs using Graal. This all works fine, but we struggle with effective error handling.
This is essentially how the JS is executed:
try {
Context context = Context.newBuilder("js").allowAllAccess(true).build()
Source s = Source.newBuilder("js", src, "script").build();
context.eval(s);
} catch (Exception e) {
LOGGER.error("Exception occurred in JavaScript:...", e);
}
So when errors happen we log them somewhere so we can do some postmortem, etc. It's possible to get the JS stack trace in these logs out of the PolyglotException that Graal throws, which is great. However, things are more complicated when some JS code has called back into Java-land, and a Java exception has been thrown:
var x = callJavaFunction("invalid parameter"); // Throws a NoSuchElementException, for example
The PolyglotException has an asHostException() method that returns the original Java-land exception, and my code that executes the JS files is smart enough to understand this and produce a useful error log. The problem arises when the JS code has tried to catch this itself, for whatever reason:
try {
var x = callJavaFunction("invalid parameter"); // NoSuchElementException
} catch (e) {
doSomeCleanup();
throw e;
}
Now we have lost the original Exception, and even worse, the JS-stack trace now just shows us the catch block, instead of where the cause was. isHostException() returns false, because this is just a JS error now. I cannot find a way to get at the original cause, which makes diagnosing errors quite difficult, especially when they have come out of a production system. The original Java exception message ends up in the JS-error object, which is helpful, but we don't have the stack trace, which is not.
What approaches can I take to try and address this?
One thought I had: Can I hook into the GraalVM and get a callback whenever a host-exception is thrown? At least that way I could have a log saying "the following Java Exceptions were thrown during execution" which I could attach to the error report. So far I've not been able to find a way to achieve this.

Logging Exceptions with Opentracing and Jaeger

I've set up Jaeger with Opentracing in a Java environment and it works nicely with logging messages with spans and tracing. But I am a bit stuck when it comes to catching and logging exceptions.
try
{
span.log(ImmutableMap.of("Exeption", "ex"));
throw new IllegalArgumentException("Expecting one argument");
}
catch(Exception ex)
{
span.log(ImmutableMap.of("Error", ex));
span.log(ImmutableMap.of("Event", "error", "Error-object", ex, "message", ex.getStackTrace()));
}
But this way does not format error logging in a good readable way.
I have looked around for information about this as it feels pretty obvious there should be as this is one of its components for logging. But I have somehow never seen anything about this. It is mostly about building and structuring spans.
Hope anyone can help me with this when it comes to capturing and logging exceptions.
This issue looks more to have to do with Java it self then either Opentracing and Jaeger. as ex.getStackTrace() is more of the problem. As it should be more like
StringWriter errors = new StringWriter();
ex.printStackTrace(new PrintWriter(errors));
span.setTag("error", true);
span.log(ImmutableMap.of("stack", errors));
Problem solved.

how to code with debug options in java

I am trying to learn the trick on how to run the code which prints a lot of stuff when the debug flag is on.
How is that done in java.
A very naive way I can think of is have the debug flag in all the methods i write
and write something like
if (this.debug == true){
System.out.println("blah blah");
}
But there should be much more elegant way rather than having all these ifs in code?
Also, is there a way I can get the line number of certain execution in code:
For example if there is an exception
try:
/* line number 22 */
catch Exception e{
//print that exception occured in above line number??
}
Probably very lame questions.
THanks
Use logging framework that will do it for you - for example : log4j, slf4j
For example:
log.debug("some text");
now in logging configuration properties file choose to enable disabled debug logging statements
See
log4j manual
slf4j
Simple example from log4j API
private Logger _debugLogger = Logger.getLogger(yourClassName.class);
//For info mode
_debugLogger.info("Some Messages");
//or for debug mode
_debugLogger.debug(MessageFormat.format("Some message {0},{1},{2}",variable0, variable1,variable2));

Java 7: throw exception without stack trace

EDIT2
#paradigmatic made a good point in suggesting to redirect rather than throw the exception; that solves the logging issue. The problem in Play 2 is that redirects need to occur within so-called Action scope, which is not always the case with date parser calls.
As a workaround, I went with Play's global interceptor, presumably the equivalent of a Java servlet filter.
val ymdMatcher = "\\d{8}".r // matcher for yyyyMMdd URI param
val ymdFormat = org.joda.time.format.DateTimeFormat.forPattern("yyyyMMdd")
def ymd2Date(ymd: String) = ymdFormat.parseDateTime(ymd)
override def onRouteRequest(r: RequestHeader): Option[Handler] = {
import play.api.i18n.Messages
ymdMatcher.findFirstIn(r.uri) map{ ymd=>
try { ymd2Date( ymd); super.onRouteRequest(r) }
catch { case e:Exception => // kick to "bad" action handler on invalid date
Some(controllers.Application.bad(Messages("bad.date.format")))
}
} getOrElse(super.onRouteRequest(r))
}
EDIT
Here 's a little context to work with:
// String "pimp": transforms ymdString.to_date call into JodaTime instance
class String2Date(ymd: String) {
def to_date = {
import play.api.i18n.Messages
try{ ymdFormat.parseDateTime(ymd) }
catch { case e:Exception => throw new NoTrace(Messages("bad.date.format")) }
}
val ymdFormat = org.joda.time.format.DateTimeFormat.forPattern("yyyyMMdd")
}
#inline implicit final def string2Date(ymd: String) = new String2Date(ymd)
and a test custom exception handler:
public class NoTrace extends Exception {
static final long serialVersionUID = -3387516993124229948L;
#Override
public Throwable fillInStackTrace() {
return null;
}
public NoTrace(String message) {
super(message);
}
}
Calling the date parser on an invalid yyyyMMdd string logs 30 line stack trace to the log (this occurs upstream by Play framework/Netty container, better than default 100 line trace):
"20120099".to_date
ORIGINAL
Have an issue where my application.log is getting filled with errors related to a uri date parser operation that should succeed given a valid yyyyMMdd uri date.
However, some users try to circumvent this by entering invalid dates in hopes of gaining free access to paid subscriber-only content. It's pointless, as it simply won't work, but regardless, I have MBs of these error traces in my application log.
Is there a way to throw a truly trimmed down Exception to the log? I found this SO answer, but in my application it looks like the container (Play framework on Netty) gets into the mix and logs its own 30 line stack trace to the log (30 lines is better than 100, but still 29 too many)
Similarly, I found this thread in regard to Java 7 and the new option to suppress stack trace; however, for some reason, despite being on Java 1.7, with Eclipse configured for Java 1.7, only the old 2 param method of Throwable is available (and I do see the 4 param method when I click through to the Throwable class; maybe a Scala 2.9.2 library issue?)
At any rate, ideally I can simply log a 1-line exception message and not the kitchen sink.
Simply override this method in your custom exception class:
#Override
public Throwable fillInStackTrace() {
return this;
}
after adding this method your trace method will not print
Your trouble is that although you can suppress the stacktrace of the exception your own code threw, there is nothing you can do about the exception it will be wrapped into by the framework. The only avenue I can see is not allowing the framework to catch your exception at all (doing your own top-level handling) or tweaking the logging configuration.
I think you have two options:
Control the logging to not save stack traces for some exceptions.
Write a post-processor that filters out the traces from the log file.
Unless you are in danger of running out of disk space, I think #2 is the better option, because if you do have a bug you can go back to the full log and have all the exception history.
The philosophy behind idea #2 is that disk space is cheap, but information can be precious during debug. Log a lot of data. Normally, use scripts to examine the log after it has been written to disk.
For example, if there is a type of log entry that you never expect to see, but that demands immediate action if it does appear, write a script that searches for it, and send you an e-mail if it finds one.
One of the most useful forms of script in this approach is one that drops stack trace lines. Usually, you only need to know what exceptions are happening, and the stack trace takes up a lot of screen space without telling you much. If you do need to investigate an exception, go back to the full log, find the exception line, and look at the stack trace and at what was happening immediately before the exception.
If there are too many of your date exceptions, have the script drop even the exception line. If you want to track how often they are happening, run a script that counts date exceptions per hour.
That sort of script typically costs a few minutes of programming in your favorite regex-capable script language.

controlling if exceptions are swallowed by a static boolean

So we are a few guys developing this product that is communicating with a really unstable server. It often returns very strange and corrupt data. During testing we want the resulting crashes to be loud, so we discover them. But every other day we need to demonstrate our product for a potential customer. To the customer the errors will go undiscovered if we just swallow them. I am thinking about implementing something like this around all server communication to quickly switch between swallowing exceptions and crashing:
try {
apiCall();
} catch (Exception e) {
if(!SWALLOW_EXCEPTION) {
throw e;
}
}
Is this an awesome idea, or can it be done in a better way?
I would recommend using a Logger like SLF4J, java.util.logging or Log4j. Any log messages that are 'debugging' but you still want tracked you can put to the DEBUG, INFO or WARN levels based on their severities. Real errors you can save for the 'Error' level.
When you do demos to customers, set your log level to Error so they don't see everything. When you are running normally though, set it to a level to capture the logging level you need.
Swallowing exceptions is never a good practice. By using a logger, you can hide them if it is giving you too much detail. You can always get access to them if you need without recompiling.
This is not pretty. How about implementing a top level (whatever that means in your context) error handler[s] that does that?
Did you intend your code to do this?
try {
apiCall();
} catch (Exception e) {
if(!SWALLOW_EXCEPTION) {
throw e;
} else {
e.printStackTrace();
}
}
If so, if this is the only place that this API is called, it seems ok to me, as long as you realize you will need to recompile for the change to take effect. You could abuse a logging framework to get that done without a recompile like this:
if (logger.isInfoEnabled()) {
throw e;
} else {
logger.error(e.getMessage(), e);
}
But I think most people looking at such a piece of code would be very taken aback. If you want to avoid the recompile, just use a System property:
if (Boolean.getBoolean("development")) {
throw e;
} else {
e.printStackTrace();//you should really use a logging framework anyway and not this.
}
You could use an 'uncaught exception handler' instead. Check out the code at http://stuffthathappens.com/blog/2007/10/07/programmers-notebook-uncaught-exception-handlers/ and http://www.javapractices.com/topic/TopicAction.do?Id=229. You can also write your handler to put the exceptions into a logger.

Categories