Robust Javascript Exception Handling - javascript

I am developing a DHTML/Javascript application which relies on some advanced features (DOM manipulation, AJAX, Flash communication, and more). I'm very concerned about functionality -- if problems occur, even after the application is deployed, I want to make sure I know why and how to fix them -- and also, I want to make sure the user is able to continue using the application, possibly with reduced functionality if the exception was severe.
I currently have a logging and exception handling system built whereby functions can generate logs, and if an exception is caught, all logs are emailed to me. The system works well but I'd like to make it more robust. I'm looking for suggestions.
One idea I have is to wrap the body of every javascript function in a try/catch block and upon catching an exception, log the name of the function and then throw the error to the global handler. But that's a lot of code just to track down the function the exception occurred in.
Any ideas to make runtime exceptions easier to find and reproduce?

Rather than dealing with adding N try/catch blocks to N functions, it might be easier to use the window.onerror event.
JavaScript Kit has a series of examples you could use. Especially the 3rd:
window.onerror = function (msg, url, line) {
alert('Error message: ' + msg + '\nURL: ' + url + '\nLine Number: ' + line);
return true;
}
If you'd prefer a stack trace, you might check out Eric Wendelin's (or Luke Smith's update). It's one of the few I know of that attempts to work cross-browser.

Related

How to fix 'thrown exception caught locally' when using instanceof to determine internal errors type

I have a block of code that loads a set of plugins. For each plugin, a list of functions is called inside of a try catch block to determine if the plugin has failed or not and act accordingly. At the same time, one of the multiple functions of the plugin can return a specific error that mean that the plugin has not failed but is not valid to execute the next functions with the data.
Let's see an example (the code is Typescript, but I am going to make it as language agnostic as possible):
for each plugin:
try:
plugin.function1(data)
plugin.function2(data)
plugin.function3(data)
try:
plugin.function4(data)
catch error:
if error instanceof PluginNotValidForThisKindOfDataError:
continue
else:
throw error
plugin.function5(data)
plugin.function6(data)
catch error:
log(plugin has failed)
(I hope the code is clear enough. I'll update it if required)
As can be seen, I execute function4 and I parse the possible errors because one of them (there are multiple) is "tolerable" and just means that it is not valid for function5 and function6 with that specific set of data. However, I still have to throw the other errors because they are not good. At the end, I catch the global set of errors to determine if the plugin has crashed or not.
What I get in my IDE, JetBrains (WebStorm specifically) is a thrown exception caught locally warning. But I am not able to reimagine how to redo that block to act differently. I am not using throws as flow control but just passing the error.
I admit that the main problem is that in Javascript I can not do catch PluginNotValidForThisKindOfDataError, which would be the optimal situation (hope its added some day). But, with the tools I have, how can I refactor this?
Thank you very much.
Added to both language-agnostic and javascript because of the specific Javascript try-catch method
I see three options:
Ideally, the plugin wouldn't throw an error for a non-error condition like that. Instead, have it return a value that tells the code in your question whether it should run functions 5 and 6.
If you want to keep it the way it is, though, you can either:
Ignore the warning (and probably there's a way to disable it for one line), or
Don't re-throw; instead, do the same thing you're doing in the outer catch (log(plugin has failed)) followed by continue. Provided that's just a single function call or similar, the duplication isn't ideal, but isn't horrible either. If there's any complexity to that step, isolate it into a function (perhaps even a local function) and call that from both places.

Ignore throw $break in Chrome JavaScript debugger

I'm using Prototype in a web app, and I'd like to break when exceptions are thrown (including handled ones). However, I don't want to break on exception used for flow control, specifically the throw $break pattern used in Prototype's each implementation.
function detect(iterator, context) {
var result;
this.each(function(value, index) {
if (iterator.call(context, value, index)) {
result = value;
throw $break; // I want to ignore this one
}
});
return result;
}
Does anyone know how to get Chrome's debugger to ignore specific exceptions? Or to get it to ignore exceptions thrown from specific lines? Or even to get it to not break in specific files?
I'm fairly certain there is no such feature. The documentation, which seems fairly complete, doesn't mention it. Also, the Chrome Developer Tool uses the Remote Debugging protocol, whose Debugger.setPauseOnExceptions command does not have a "file" parameter. That said, I have not grokked the source code.
Getting Chrome's debugger to ignore specific exceptions or files would also help when working with jQuery. It catches and re-throws any exception in an event callback (search for "resolveWith"), making the message in the console essentially useless. jQuery throws and catches exceptions internally all the time, so breaking on all exceptions produces too much noise.

JavaScript try/catch and ajax reporting

There's something I'd like to do with my JavaScript deployments, and I'm looking for a really slick way to do it.
I'd like to run a try/catch on my code, which shouldn't be super impressive or complicated, but here's what I would like to do when I have a failure: let the dev team know, rather than waiting for that one-off customer that cares enough to write an email on the chance he notices something that breaks.
My initial thought was to write a support submission object which I could code to take any random data (i.e., report.submit(issue_data);), and create an ajax call to my server that silently adds the data to an inbox or a database or whatever.
I thought I could do it something like:
try {
some_code();
} catch(e) {
do_instead();
report.submit(issue_data);
report.update(); //Could perhaps show the users a history of errors
}
But, I'd like to see if there's a better solution...better as in solving an unseen flaw here, doing things more seamlessly, advice on how to deal with failures of the submission system, perhaps using the prototype in some exciting way, etc.
Also, my simple solution here has a lot of limitations that could make the whole thing semi-useless, such as not being able to indicate the specific part of the code that failed, line numbers, conditions to create failure, browser version, etc.
The big problem with these is that you have to be able to get those reports back. What we've done on my project is to have a logger REST resource and use log4javascript's AjaxAppender.
A little more info:
}catch(e){
alert(e.description);
}
But other than that your implementation looks pretty good to me my friend.

A JavaScript frontend logging system that logs to our backend?

We have an established logging system for our server-side services. Specifically, our Django project makes heavy use of the Python logging module, so call calls to logger.info(), logger.warn() and logger.error() get picked up by our centralized logging system.
I would like an equivalent on our frontend, and I've got a few ideas:
There would be some sort of custom logging object exposed via JavaScript that would send messages to backend via an XmlHttpRequest.
I'd like to have equivalent logging levels on the client-side: debug, info, warning and error.
When we're developing locally (debug mode), I'd like those logging messages to be logged to the browser/Firebug console via console.log().
In production, debug messages should be dropped completely.
I recall seeing a way to capture all uncaught JavaScript exceptions, so these should be logged at the error level.
We're already using Google Analytics event tracking, and it'd be nice for whatever system we create to tie into that somehow.
Is this a good idea? How would you do this? Are there existing solutions?
(FWIW, we're using jQuery on the frontend.)
Update: Simplified question here: https://stackoverflow.com/questions/1423267/are-there-any-logging-frameworks-for-javascript
First, I wrote and maintain log4javascript, so I'm declaring my interest up front. I also use it every day in my work, so I have some experience of it as a user. Here's how I would deal with your questions, specifically relating to log4javascript:
Use log4javascript's AjaxAppender for server logging;
debug, info, warning and error are all supported, as well as trace and fatal;
Use a BrowserConsoleAppender to log to FireBug or the native browser console;
If you don't want to remove all debug logging calls from you production code, you can either adjust your logger's threshold (using log.setLevel(log4javascript.Level.ERROR), for example, which will suppress all log calls with priority less than ERROR). If you want to suppress all logging calls, you can drop in a stub version of log4javascript in your production code.
You'll need to write a bit of code to do this using window.onerror. Something like window.onerror = function(msg, file, line) { log.error("Error in " + file + " on line " + line + ": " + msg); }
I'm not sure how you want to tie in with Google Analytics. log4javascript has no particular support for it.
The idea sounds good here. Just be aware of what exactly it is you are looking to log client-side and have at it.
I would recommend using log4javascript for logging. The log4 api is pretty straight foward.
Here is another question from here on SO about this very issue.
Some recommendations are: log4js, log4javascript, and Blackbird.
FWIW, log4js was the accepted answer there. I don't have experience with any of these platforms, so I can't really recommend one over the other.

Is this a suitable case in which using dynamic function creation would be justified?

I'm currently developing a tutorial site for teaching the fundamentals of Web development (HTML, CSS, and JavaScript, for starters). I'd like a setup where I could give in-depth coverage of all sorts of topics and then provide a basic sandbox environment where the user could write code which solves the question asked at the end of each tutorial section.
For example, if I'd covered multiplication in a previous tutorial, and the user had just finished a lesson on functions being capable of returning values, I might request that they submit a function which returns the product of two parameters.
Is this not the perfect instance in which using dynamic function creation would be considered a good idea? Let's look at an example.
<script>
function check()
{
eval('var f = ' + document.getElementById('user_code').value);
if (f(5, 10) == 50)
{
// user properly wrote a function which
// returned the product of its parameters
}
}
</script>
Is this at all a bad idea? If so, please explain.
This sounds like it could work. However, the biggest challenge in your environment might be error handling. Students will surely make all sorts of errors:
Compile time errors, that will be detected in eval()
Run time errors, that will be detected when you call the function
Undetectable run time errors, such as an infinite loop or a stack overflow
A more elaborate approach might parse the entered Javascript into a parse tree representation, then compare it to an expected parse tree. If it does not match, then point out what might be wrong and have the student try again. If it does match, then you can eval() and call the function, knowing that it will do what you expect.
Implementing a lexer and parser for Javascript in Javascript would be challenging but certainly not impossible.
Should work as long as you're operating this in a closed environment. Eval opens you up to code injection attacks so I wouldn't put this on a publicly accessible web site, but if it's completely contained within your class room you should be ok.
The code would work, but what if there is an error both syntactically or otherwise ? Perhaps use a try block to catch any error and display it to the user would help things a little...
Not sure if this helps.
Sounds like you want to remake Firebug or even the new Developer Tools in IE8. Due to that, I'm going to have to say there is never a useful case. Not to mention the possibilities of script injection if this site goes public.
In your case, I feel that there is nothing wrong with this. Alternatively you can run the code by using new Function() to build stuff first and then run it. In theory, this would separate the stages of "compiling" and executing. However eval will check the code first and throw errors anyway:
var usercode = document.getElementById('user_code').value;
try {
var f = new Function( 'a','b','return (' + usercode + ')(a,b);' );
if ( f( 5, 10 ) ) {
// user properly wrote a function which
// returned the product of its parameters
}
else {
// user wrote code that ran but produced incorrect results
}
}
catch ( ex ) {
// user wrote something really bad
}
The problem with doing things in this manner is that the exceptions thrown may be nonsensical. "foo;;=bar" will report a "missing ) in parenthetical" error while eval will throw a propper syntax error. You could bypass this by (regexp) grabbing the parameters and body from the user code first and then building it. But then, how would this be any better than an eval?
I think that your real problem will be helping users avoid the pitfalls of implicit globals. How are you going to help users avoid writing code that only works the second time it runs because a global was set the first time? Will you not need to implement a clean sandbox every run? I would take a look at how jsbin.com, firebug and similar tools handle these things.
My feeling is that you should go with eval for now and change it for more elaborate stuff later if the need arrises.

Categories

Resources