JavaScript Logging

by David F. Miller

43 Reader Comments

Back to the Article
  1. Can anyone tell me if the above method is better than simply using:

    p3.setAttribute(“class”,“labrat”, 0);
    p3.setAttribute(“className”,“labrat”, 0);

    Regards,

    Chris

    Copy & paste the code below to embed this comment.
  2. In my experience, yes—setting the “className” property of a DOM node will apply the class to the node in question in all modern browsers I’ve tried.

    I generally use that approach in my scripts; “class” itself is theoretically a reserved word for “JavaScript 2.0”, too.

    Copy & paste the code below to embed this comment.
  3. In my experience, setAttribute in IE will not compile the attribute’s actual action into the IE document model. For instance if you’ll try something like this:
    myElement.setAttribute(“onclick”, “doSomething()”, 0);

    IE won’t actually register this event to the object. To my surprise, Firefox will actually do this. So what I’m trying to say, that setAttribute in IE won’t do you any good with attributes like ‘class’, ‘style’, ‘maxlength’, ‘value’, etc..
    In my experience, you’ll have to use the “proper” procedure:
    myElement.className = “yourClassName”;

    Using setAttribute and getAttribute for your own custom attributes works perfectly on the latest browsers..

    Copy & paste the code below to embed this comment.
  4. Nice work! I’ll use it for sure. But there’s one improvement I’d make.
    I would add “return false;” to every onclick event in the menu to avoid annoying page leaping.
    So I’d rewrite:

    <dd class=“all”>
        [url=”#fvlogger” 
        title=“show all”]all[/url]
    </dd>

    as:

    <dd class=“all”>
        [url=”#fvlogger”  return false;”
          title=“show all”]all[/url]
      </dd>

    Copy & paste the code below to embed this comment.
  5. As someone just starting to dabble in the world of slightly more advanced Javascripting, I find the prospect of debugging scripts in non-FF browsers to be a very very scary one. So thanks for the tips.

    However, related to that awkward setAttribute loop, is object.className now a deprecated property?

    Copy & paste the code below to embed this comment.
  6. for (i = 0; i < attrs.length; i++) {
      debug(“attribute #” + i + “: ” +
      attrs.name + “=” + attrs.value);
    }

    Copy & paste the code below to embed this comment.
  7. Agreed, this is very clever.  More importantly (now that it’s here), it’s available to those doing coding that are experiencing more cross-browser issues as the Ajax approach is becoming more common.  This would have been a lifesaver on a project I completed recently, and my company hesitant about Ajax due to concerns about difficulties in maintenance and debugging.

    Thanks!

    Copy & paste the code below to embed this comment.
  8. Let’s not forget the Venkman plugin for firefox (http://tinyurl.com/cmu7j). It’s easy to use and works well.

    Copy & paste the code below to embed this comment.
  9. Looping round the attributes after already calling getAttributeNode seems a bit wasteful, this should (and does) work:

    var attributeNode = p3.getAttributeNode(“class”);
    if (attributeNode) {
      attributeNode.value = className;
    } else {
      p3.setAttribute(“class”, className);
    }

    Copy & paste the code below to embed this comment.
  10. (apologies for this double-comment; ‘comment preview’ needs a few wrinkles ironing out.)

    This comment applies to the fvlogger code, as mentioned in the ‘Solution’ section of the article, and which appears in the fvlogger function FVL_log

    var attributeNode = p3.getAttributeNode(“class”?);
    if (attributeNode) {
    attributeNode.value = className;
    } else {
    p3.setAttribute(“class”?, className);
    }

    Similarly, for getNodeClass you could do:
    var attributeNode = p3.getAttributeNode(“class”?);
    return attributeNode && attributeNode.value;

    The implementation’s good though.  I’d fallen into the habbit of using .className, which seems to work, but isn’t part of the DOM spec.  The approach in the article is more pure.

    Copy & paste the code below to embed this comment.
  11. I’m a bit confused.
    You cure the class element on IE, but when I looked at the logging, I still see the 84 attributes. I’m still learning javascript and would have trouble figuring out what is worth worrying about in those 84 attributes.  Are they a problem? Is the logging example above the fix using the fix?

    Copy & paste the code below to embed this comment.
  12. I’m always had a hard time debugging JavaScript.  The Venkman debugger is too unwieldy most of the time.  I’ll add this to my list of tools.

    I wrote a similar utility a few weeks ago.  It’s quick and dirty.  It does not have multiple error levels, although that could be added.  If anyone is interested, it’s here: http://www.connectedpixel.com/blog/javascript/trace

    Copy & paste the code below to embed this comment.
  13. I’m glad the article is being well-received; I’ve been using the code in several projects myself and have found it to be a pretty invaluable tool. Keep the thoughts/comments/improvements/suggestions/etc. coming; the more topics such as this one are discussed the better we will all be for it.

    As for the code itself… Yeah, there are a few different ways to deal with browsers and how they handle attributes and their values. Looping through the list of attributes and doing an exhaustive name comparison is by no means the most efficient (or elegant) method of finding the class name, but it does get the job done. Like most topics related to scripting browsers, it’s a matter of finding a balance between what works in every browser, what should work in every browser, and maintaining your sanity while cobbling together whatever hack you can come up with.

    Copy & paste the code below to embed this comment.
  14. Ted,

    The values of all the node’s attributes are being echoed to the debug log merely to illustrate the difference between how Internet Explorer and every other browser handles node attributes. Sorry for the confusion.

    Copy & paste the code below to embed this comment.
  15. Safari also has a javascript debugger.  You need to enable the Debug menu in safari, which can be done by typing the following into terminal (make sure safari is closed):

    % defaults write com.apple.Safari IncludeDebugMenu 1

    Then relaunch safari, and from the debug menu you can open a js console.

    Copy & paste the code below to embed this comment.
  16. I myself tend to create an extra DIV on the page, style it with position:absolute; and fill its innerHTML with various debugging values. It’s a step up from the alert() in that it does not halt the script (allowing time-bugs to expose themselves) and does not require lots of clicks in case your bug is inside a loop.

    The downside is of course the numerous bugbox[removed] = ‘such and such’; spread across the script, which need cleaning up after bugs have been zapped.

    It’s always served me well, but maybe I’ll try ouy fvlogger. See if the glove fits.

    Safari also has a javascript debugger. You need to enable the Debug menu in safari

    I think that should be a default, instead of a carefully hidden option. But then again, the JS engine of Safari does not behave strangely compared to the Gecko engine, at least not for my scripts. A Bbg fixed in Gecko equals a bug fixed in Safari.

    Copy & paste the code below to embed this comment.
  17. Yes, Safari and Firefox both include excellent JavaScript debuggers, but they only provide debugging information for that particular browser. To find out what your script is doing in another browser (typically IE), then the information gleaned from that debugger may or may not be totally useless.

    Copy & paste the code below to embed this comment.
  18. The article instructs us to use the following self-closing script tag to load the JavaScript source code:

    [removed]

    However, in my experience, Internet Explorer does not seem to “like” self-closing script tags and fails to load the script. Can anyone else confirm this or provide any additional information on the topic?

    On a side note, if you look at the actual source code of the article, you’ll notice that they don’t follow their own advice and instead use:

    [removed][removed]

    Perhaps the article example should be corrected to use a closing script tag.

    Copy & paste the code below to embed this comment.
  19. first off, this makes me so happy. Stupidly simple and brilliant. Secondly, I hope someone will beat me to it (as I am a Javascript hack, but I will take a stab this weekend at implementing this as a popup window.

    Copy & paste the code below to embed this comment.
  20. You might want to give “Lumberjack”:http://gleepglop.com/javascripts/logger/ a try. It seems less complicated to use than fvlogger (But it only has been tested to work with Firefox 1.0+ and IE 6.0+) It also has a real nice “demo page”:http://gleepglop.com/javascripts/logger/

    Copy & paste the code below to embed this comment.
  21. At about line 43 of the index.html example, the line needs to be changed to:

    <dd class=“info”>info</dd>

    The line needs the onclick to show the Info blocks. 

    Thanks for a great little tool.

    Copy & paste the code below to embed this comment.
  22. I believe it would be beneficial to add onkeypress=”?showInfo();” to those links, for keyboard users.

    Copy & paste the code below to embed this comment.
  23. IE has a JavaScript debugger too. Visual Interdev & VS.NET can be used for interactive JavaScript debugging in IE at about the same level of functionality as Venkman. There are a few options you have to enable in IE to turn on script debugging.

    Logging is powerful for tracking down problems you didn’t expect to happen, assuming logging is occuring in the right places and there’s a way to get at the log output. A nice feature for fvlogger would be “crash report” submission UI so users could report failures back to the site maintainer.

    When you know a problem exists interactive debuggers are often more efficient than trial-and-error logging, and are worth the effort spent learning thier quirks. Plus, you get to skip the frustrating “trial-and-error” step.

    Copy & paste the code below to embed this comment.
  24. This is very nice. 

    A couple of features I would add:

    1) Date/Timestamps prefixing each log, – auto generated.

    2) A global switch to turn logging on and off.

    All up, – very sweet!  Nice article.

    - James

    Copy & paste the code below to embed this comment.
  25. This logging script looks very nice and I’m certainly going to give it a try. If it’s of any use to anyone, there is another logging mechanism I have been using for several years. This is IE only, and only of use for debugging scripts running on your local box. Despite these limitations, if that’s the setup you are debugging, it is quite powerful. This is an activex dll, originally made available by Microsoft in the IIS 4 resource kit, called IISSamples.Tracer. It is a very light c++ wrapper round the printDebugString windows api call. All messages logged via this utility can be viewed in the (free) debugviewer utility from sysinternals. The main advantage of this mechanism is that the logging is very fast, particularly useful when debugging mousemovements etc where the overhead of javascript logging methods may interfere with the script you’re trying to debug. It also prints accurate timings with the messages. I don’t beleive this is available on the web anymore, and I have no means of posting it but if you want a copy, email me and I’ll send it to you.

    Copy & paste the code below to embed this comment.
  26. James,

    Thanks for your comments; you can turn logging on/off by setting the value of FVL_LOG_ON to false in logger.js. As for the timestamping of logging statements, I’ll definitely consider it for a future version, although it’s relatively simple to implement if you’re familiar with JavaScript. If you need a hand, let me know. Cheers!

    Dave

    Copy & paste the code below to embed this comment.
  27. Someone was wondering if this is correct:
    [removed]
    They were correct, script is not an empty element in the (X)HTML DTD, so must be written as:
    [removed][removed]

    Copy & paste the code below to embed this comment.
  28. Great article.

    I think that you could also use this technique to write out javascript errors to a logfile on the server. This would be a handy way to catch user-generated js errors in production. Instead of writing the errors to a document object, write them to a variable, and then pass that variable using XMLHttpRequest to a server-side script which then captures the message to a file. Only problem I can think of is that this script is then exposed to the public, and someone mischievous could write tons of messages to your server. But perhaps this would be something you would deploy only on a case-by-case basis when you want to track down elusive, idiosyncratic bugs.

    Copy & paste the code below to embed this comment.
  29. I enjoyed looking at your take on the javascript logger.  If you are looking for something that acts more like Log4J, I wrote a quick logging class for some of my own projects called log4js – “http://log4js.sf.net”:http://log4js.sf.net .  It is a little more robust in that it allows for multiple loggers per page (each is an object), and multiple targets, such as alerts, a popup dialog, or the safari javascript console…

    Then again, it is written by a java programmer returning to javascript after a long hiatus.

    Copy & paste the code below to embed this comment.
  30. Nice stuff. I have already started using it and find it quite useful.

    ALA, Keep such article coming. ALA has saved me so much time with such high class material.

    Thanks for the Good stuff,
    Venkat.

    Copy & paste the code below to embed this comment.
  31. I very much enjoyed this article, but I found the statement “The concept of logging was popularized by Apache’s Log4J package for Java” curious. I have heard of log4j but I was not aware that it has popularized the field of logging – is that to suggest that prior to log4j, logging was uncommonly used? Perhaps it depends what field you are in, but in UNIX we’ve enjoyed the syslog daemon (syslogd) for quite some time, and logging is standard practise in most applications.

    Copy & paste the code below to embed this comment.
  32. Noticed a couple bumps:

    1. Putting very simple function names like “show” and “hide” in the top-level namespace is bound to cause problems. I’m working on a web app that already has these functions defined, and adding the logger will override them. I had to change all the fvlogger functions to have a “fvl_” prefix to them.

    2. The logger won’t catch errors that occur as the page is parsed—for example, if you have a javascript in the BODY that just runs immediately (before the page finishes loading), fvlogger won’t catch it.

    What’s worse, if the offending code is placed AFTER the logger.js include, but BEFORE the fvlogger DIV, it becomes invisible, since the window.onerror is redirected: No error message shows up in the javascript console. This seems like a big flaw to me.

    Copy & paste the code below to embed this comment.
  33. I know Venkman has a cool Profile feature which I’ve used manually and which allows you to log data about which javascipt functions are being called and the min/max/avg process times per function.  Is there any way to automate this in Venkman ?

    Is anyone aware of another tool that would do this ? 

    Thx !

    Copy & paste the code below to embed this comment.
  34. The Dashboard widget API already has a great console logger built in. In fact, all alert()s go straight to the console. This works well: if you forget to remove your logging code before release users won’t be pestered by pop-up windows or other unsightly logging messages.

    Copy & paste the code below to embed this comment.
  35. We are stuck with a Javascript call creating a div and a class name. In FF it works great, but in IE it is not passing any of the class elements and as a result the effect we want, rows and columns, are lost and just one column is left.

    here is the code we are using:

    // This is the div that contains each image and it’s browse box.
    var newElement = document.createElement(‘div’);
    newElement.setAttribute(‘id’, ‘previewDiv’);
    newElement.setAttribute(‘class’, ‘uploadBox’);


    // This is the image!
    var imgDiv = document.createElement(‘div’);
    imgDiv.setAttribute(‘id’, ‘preview-img’);
    imgDiv.setAttribute(‘class’, ‘previewImgDiv’);

    I have gone through some articles here and tried some other ways of doing this and IE just won’t play nice. Any direction would be appreciated.

    thanks.

    Copy & paste the code below to embed this comment.
  36. I had been itting the problem of how to set the class attribute in Javascript and having IE render it. I found this discussion, which gave me a part of the solution.

    I had been trying to use
    el.classname = ‘someclass’;
    (el = document.getElementByID(‘divname’) was assumed here)
    But that created an attribute of classname – not class – so CSS rendering was not occurring. This discussion indicated that I could use the
    el.setAttribute(‘someclass’,‘divname’);

    I would then appendChild to the divname and – no CSS rendering.
    But the el[removed] = “<h3>somehtml</h3>” always worked.

    So I turned it on itself -  el[removed] = el[removed]
    and it rendered.

    I have been getting back into Javascript to use some Ajax techniques so I feel like I am learning this again – and these problems could be my own lack of understanding.
    It was helpful to have this discussion available – thanks.

    Copy & paste the code below to embed this comment.
  37. http://jstracer.sourceforge.net/

    jsTracer performs similar logging functionality but also allows you to denote or highlight logged messages.  It also provides a stack viewer and won’t cause slow script warnings on complex JavaScript code.

    Copy & paste the code below to embed this comment.
  38. http://www.timdown.co.uk/log4javascript

    log4javascript offers similar ease of logging to fvlogger but with far more flexibility. Logging may be done to a searchable, filterable pop-up/in-page console window and/or back to the server via Ajax. It is closely modelled on log4j and has been rigorously tested on all major browsers.

    Disclaimer: I am the author of log4javascript.

    Copy & paste the code below to embed this comment.
  39. in firefox 2.0, when I include fvlogger, it overrides my console errors, and doesn’t display them in the fvlogger div either, so I can’t see any javascript errors caught by the browser.  To see them I have to comment out the inclusion of the fvlogger script, which breaks all the manual ‘debug’ and ‘info’ entries I’ve made.. darnit!

    Copy & paste the code below to embed this comment.
  40. in firefox 2.0, when I include fvlogger, it overrides my parse errors, but doesn’t display them in the fvlogger div either, so I can’t see any javascript errors caught by the browser anywhere.  To see them I have to comment out the inclusion of the fvlogger script, which breaks all the manual ‘debug’ and ‘info’ entries I’ve made.. darnit!

    Copy & paste the code below to embed this comment.
  41. Hey David, thanks for fvlogger. I was using it to debug some Flash/Javascript integration, then, just for the hell of it, hooked up our Flash tracing to a separate window with fvlogger in it using the Flash ExternalInterface calls. Brilliant.

    We’ve had Flash debuggers inside Flash before… but at runtime they can’t really handle the volume of debug info that can come out. Hell, even the Flash IDE has the poorest output log ever.

    fvlogger was easy to get working.

    Thanks.

    Copy & paste the code below to embed this comment.
  42. Keep the great work going. The tips are really helpful, as are some of the discussions. Learnt a lot. Thank you.

    “tigi bed head”:http://www.salon-collective.co.uk/tigi_bed_head.php
    “tigi bed head dumb blonde”:http://www.salon-collective.co.uk/tigi_bed_head.php?query=dumb+blonde
    “tigi bed head shampoo”:http://www.salon-collective.co.uk/tigi_bed_head.php?query=shampoo
    “tigi bed head hair products”:http://www.salon-collective.co.uk/tigi_bed_head.php
    “tigi bed head control freak”:http://www.salon-collective.co.uk/tigi_bed_head.php?query=control+freak
    “tigi self absorbed”:http://www.salon-collective.co.uk/tigi_bed_head.php?query=self+absorbed

    Copy & paste the code below to embed this comment.
  43. Thanks Tom for the tips and inspiration. I’m beginning to dig fvlogger. Maybe I’ll share my results some time. :)

    Regards,
    Kenneth Lee
    Webmaster of
    “Make money online”:http://mrdefinite.com

    Copy & paste the code below to embed this comment.