Capture, Log, Message, Monitor, Record


Developer Story

Dave's search engine keeps giving a blank result for certain queries. Fortunately, he previously added some Logging commands to see how the query is processed, so he makes the console visible and sets log level to verbose. After entering the query again, he now sees that one of the regular expressions is not matching the query as expected.


How can you track program process?


Instrument your JavaScript with log messages. Typically, the page contains a div element especially for Logging, and each significant action is appended there, e.g.:

  $("log").innerHTML += "User searched for " + query + ".<br/>";

Even this simple implementation offers several benefits over the common alternative, debugging with an alertbox. Most importantly, the log element can be a Popup (Chapter 15): you can easily toggle visibility by dynamically switching CSS properties such as display, or even make it partly transparent. Further, Logging is unobtrusivethat is, there's no impact on application flow. Another benefit is that you have a history to consult if something goes wrong; there's no need to try replicating the problem.

Inspired by libraries such as Java's log4j (http://logging.apache.org/log4j/docs/), JavaScript Logging libraries usually provide some sort of filtering. Typically, a message is tagged with a priority level, e.g., "debug," or "info," or "error." You can then choose to only see messages above a certain level.

Logging impacts performance, not just in DOM manipulation but also in producing the messages themselves. You can end up with a memory problem as well unless some measure is taken to clear old messages, e.g., using a buffer to discard old messages.

Instead of Logging to a console on the page, some developers output messages to the browser status bar (using window.status), and Firefox developers also have the option of outputting to the browser console. However, this limits portability and requires some configuration (http://www.make-believe.org/posts/05/10/24/0).

Another approach that is gaining traction is to embrace Web Remoting (Chapter 6) and upload the data to a Logging web service.[*] This allows for permanent storage of the logs and can also be combined with server-side logs to paint a detailed picture of each interaction. Eric Pascarello, for example, has proposed the technique for usability testing (http://radio.javaranch.com/pascarello/2005/11/01/1130878004388.html). And log4js (http://jroller.com/page/stritti?entry=logging_in_javascript_log4js) supports an XMLHttpRequest-driven Logging strategy. The benefits of remote Logging must be balanced against concerns for users' privacy and consent.

[*] Ajaxmore specifically, XMLHttpRequesthas been labelled a technique for "spying on users" (http://www.devx.com/webdev/Article/28861). However, techniques for remote Logging have been available for a long time. The main impact of Ajax is to increase rich activity in the browser, which might create further incentives to log user activity. See http://www.softwareas.com/spying-on-users-with-xmlhttprequest.


Will you log during production?

Most servers are configured to perform Logging during production as well as development, so should the browser log too? In the past, the answer was usually no. But Ajax makes the case for browser Logging more compelling for two reasons. Firstly, with more logic in the browser, there are more things that can go wrong and that need to be logged. Secondly, Web Remoting (Chapter 6) makes it possible to accumulate logs on the server in a completely unobtrusive manner. Still, remote Logging does consume application processing time as well as bandwidth, so you'll need to decide whether it's worth it, and if so, how much to log. In doing so, you'll also need to consider the user's privacy.

How will you change log settings between development and production?

In server-side Logging systems, log settings are usually altered by applying environment-specific filters. For example, in development, all messages are shown, whereas in production, only messages at information level and above are shown. But a familiar performance problem then arises: even though debug messages aren't being logged, the arguments must nevertheless be constructed, which takes time. A common solution is to include "if-then" statementsan unfortunate idiom that obscures the real point of codeto check the log level. Since JavaScript is generated by the server, you can do better than that: configure things so that log commands aren't even spit out in the first place. How you do this depends on the server-side environment. For example, a JSP developer could develop a JavaScript Logging tag whose implementation dynamically inspects the Logging configuration.

Tool Support


Corey Johnson's Lumberjack (http://gleepglop.com/javascripts/logger/) is a JavaScript Logging framework that supports Logging at different levels. There's no setup required because it creates the Logging div itself, so you can immediately issue calls such as Logger.info("User logged in."). The console is initially hidden, and you can toggle visibility with Alt-D.


David Miller's fvLogger (http://www.fivevoltlogic.com/code/fvlogger/) works similarly to Lumberjack. To use it, you just include a div with optional log level and make calls such as error("No such record.");.


log4js (http://jroller.com/page/stritti?entry=logging_in_javascript_log4js) is based more closely on log4j than other frameworks. In addition to various log levels, it supports pluggable Logging strategies. Logging strategies include: do nothing; log to pop-up window; and upload via XMLHttpRequest Call.


Bob Ippolito's Mochikit framework (http://mochikit.com/doc/html/MochiKit/Logging.html) has an API similar to those mentioned earlier and also adds features such as log listeners and a configurable message buffer. Interestingly, the standard way to launch the console is with a bookmarklet.

Code Example: Using Lumberjack

The Basic Ajax Pattern Reader (http://ajaxify.com/run/reader/) is refactored here to include Logging with Lumberjack (http://gleepglop.com/javascripts/logger/)(Figure). Lumberjack's logger.js is included, and the code is then instrumented to include log messages:


    Logger.info("Received " + patternNames.length + " pattern names.");
    Logger.debug("Received summary: " + summaryHTML.substring(0, 100) + "...");
    Logger.info("Adding " + patternOption.value + " to playlist");

 Python   SQL   Java   php   Perl 
 game development   web development   internet   *nix   graphics   hardware 
 telecommunications   C++ 
 Flash   Active Directory   Windows