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.
Related
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.
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
At the moment I am developing a website while using the Playframework2. I am just a beginner in programming. I read some books about exceptions but now in the real world , exception handling is really strange.
To be honest I don't really care what exceptions are thrown I handle all exceptions the same way.
return badrequest(); . I only use exceptions for logging.
try{
...
}
catch(Exeption e){
//log
return badrequest();
}
But this is so much boilerplate and it's really annoying to write, because every method throws the same exceptions.
Any tips , hints or resources that you could give me?
edit:
An example would be my "global" config file. Because I need to connect to the db every time I thought i could write a singleton for this problem.
private Datastore connect() throws UnknownHostException, MongoException,
DbAuthException {
Mongo m = new Mongo(dbUrl, dbPort);
Datastore ds = new Morphia().createDatastore(m, dbName);
boolean con = ds.getDB().authenticate(username, password.toCharArray());
if (!con)
throw new DbAuthException();
return ds;
}
This also results in a try and catch every time I want to connect to the db. My problem is I don't think I can handle them diffidently.
A code example :
public static Result addComment(String title) {
try {
Datastore ds = DatabaseConnect.getInstance().getDatastore();
Form<Comment> filledForm = commentForm.bindFromRequest();
Comment userComment = filledForm.get();
userComment.setUsername(Util.getUsernameFromSession(ctx()));
User.increasePointsBy(ctx(), 1);
UserGuides.addComment(title, userComment);
} catch (Exception e) {
return badRequest();
}
return redirect(routes.Guides.blank());
}
In this case I was to lazy to write the same try and catch over and over again, and this is duplicated code.
Maybe there is a book that explains how to design a big application with exception handling?
When you invoke a method, you do not necessarily have to catch the exceptions right there. You can let your callers handle them (declaring a throws clause if it is a checked exception). In fact, the ability to pass them on to the callers without any additional work is the distinguishing feature of exceptions.
My team has adopted the following coding standard: We throw checked exceptions for those rare cases when we want to recover from a failure, and unchecked exceptions for anything else. There is only a single catch block for the unchecked exceptions in a method so high in the call stack that all requests pass through it (for instance in a ServletFilter). This catch block logs the exception, and forwards the user to the "Sorry, this shouldn't have happened" page.
Have you looked at your code to examine why you're throwing all these exceptions? Exceptions are there for a reason- to tell you that something went wrong. If you're writing too much "boilerplate" try-catch code and you're not in a thousand line application, you have to refactor.
try-catch can be irritating when you have a complex block and can become very monotonous and boilerplate (Marc Gravell even said he usually uses try-finally) but as a new programmer, it would be helpful for you to examine the code that you write and figure out how to either handle or avoid those exceptions.
As akf mentions, ignoring exceptions can also be hazardous to debugging. It will be harder to track down where something catastrophic went wrong if you're missing exceptions leading up to it.
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.
ok, im working in a j2ee project that has 2 branches in the repo and i'm ordered to mix them.
i was coding and then netbeans ask me "unreported exception blah bla bla must be caugth or declared to be thrown" and gives me the choice of just handle each exception or just throw it hoping someone else catches.
The classes i'm working with are these:
DataBase - DataObject - PersonDB(I'm working here)
DataBase an abstraction of the DBMS(supports a couple of them)
DataObject is just the CRUD, type conversion between the DBMS and java , and some reflection things for generality, it uses Database as a member variable
PersonDB is a map of the fields in the table called person to java types, this class extends DataObject
Now in the version 1(just the name actually worked in parallel) catch all the exceptions where they are produced for example in the class DataBase:
try {
Class.forName(this.driver);
} catch (ClassNotFoundException ex) {
Logger.getLogger(BD.class.getName()).log(Level.SEVERE, null, ex);
}
or in the DataObject class catching:
SQLException, NoSuchFieldException, IllegalArgumentException
now on version 2 all that is left to the up caller like this:
public BD (String Adriver, String Ahost, String Abase, String Alogin, String Apassword)
throws java.lang.ClassNotFoundException { ... }
which is the best way to go in your oppinion in this kind of issues, specially if i'm using struts
I apologize for my English
Well the first question I have to ask is: if this is a J2EE application, what are you doing manually loading JDBC drivers? This is what data sources are for.
Secondly, if you do need to dot his then ask yourself this: what is the result of this exception happening? Is it recoverable? Or is the failure so catastrophic your application can't run?
If it's so catastrophic your application can't run do this:
try {
...
} catch (SomeCheckedException e) {
throw new RuntimeException(e);
}
There is no point polluting your interfaces with "throws ..." clauses.
Alternatively if it is recoverable or potentially recoverable then you do need to handle it more nicely. It's hard to give an answer as to how though. Really it depends on the circumstances.
For example, if you're loading modules/plugins this way, you just log that plugin XYZ could not be loaded (logging the exception) and move on. If this is the direct result of a user action you need to somehow report to the user that the action failed (and also log the error), etc.
Exception handling is always a question of "Can i handle it?" - where handle means more than log and rethrow.
Sometimes it is worth to catch just to throw an exception of an other abstraction level ("Can i produce a more clear error for the caller?").
In both cases you have to think about passing the cause or not ("Has it useful informaton for the caller?") - not just do it any time, you will get tons of useless log files. When catching an exception, you would normally log the catched exception, maybe with debug level only, but in case of debugging a customers system, good log information is often the only chance to "debug" the system.
Exception handling and logging is often not done well. But for a product or longtime project it would be a good investment.