Skip to main content


December 13, 2005


Client-Side Logging
Client-to-Server-Side Logging
Network Optimizations
Client Optimizations

As you have undoubtedly heard, the latest and greatest four-letter acronym in the web-based software development world is
AJAX. Despite the tidal wave of excitement and hype,
there is another four-letter word that can be associated with AJAX:
pain. The dirty little secret is that there are many
reasons developing AJAX applications can hurt. Some of these
reasons are the browsers' fault, due to the fact that each browser
version offers differing levels of DOM and JavaScript compliance.
Memory leaks in all existing browsers compound the problem. A
portion of the responsibility also falls onto the "J" of AJAX: the
loosely typed JavaScript has a syntax that is familiar to Java
developers but is filled with gotchas you will inevitably run into.
Arguably, the advent of AJAX is pushing JavaScript beyond its
intended use and definitely beyond the skill set of the average web
UI designer.

An additional reason writing AJAX applications can be difficult
is the lack of tools that are considered standard for server-side
development, including a logging system. "Logging equips the
developer with detailed context," according to the website for the
popular Java logging framework "">Log4j.
Because your AJAX application executes on the client machine and
you have no detailed context of its state, how do you know when an
error occurs? How do you know what events and application defects
lead to the error? Thorough testing before a release increases your
confidence in the product, but you can't prove a negative; just
because bugs are not reported does not mean your end users are not
experiencing them. Through logging, you have enough detailed
context that you can be confident your application is not
experiencing errors and is running smoothly.

When starting an AJAX project and writing a lot of JavaScript,
the alert function is your new best friend and, for
the short term, is sufficient as a debugging tool. But as the
complexity of your AJAX applications increase, using alerts becomes
tedious, irritating, and time-consuming. Worse, when working on
event-driven code, alerts have the potential to disrupt the normal
flow of program execution. At some point, the cons of using alerts
in debugging begin to outweigh the pros, and the need for an
improved logging mechanism becomes clear.

Joshua Gitlin's article "">"Errors and
details an error-handling system for transmitting
JavaScript errors to the server and will ease some of the pain
you'll experience while working with AJAX. While a step in the
right direction, his solution is concerned only with improving
error handling. By using Mr. Gitlin's concept as a foundation and
expanding the scope of the problem, a client- and server-side
logging solution can be developed. By using this solution, all of
the advantages and benefits of traditional logging systems,
including improved error handling, become available to AJAX
applications. Because the system I describe relies on the use of
AJAX and Log4j, I have given it the name "">Log4Ajax.

Before diving into the details of Log4Ajax, this article assumes
the reader has some level of familiarity with AJAX and DHTML. If
not, the Web contains a wealth of information that would be
redundant to duplicate here. Links to several good sources,
including Joshua Gitlin's "Errors and AJAX," are included in the
Resources section.

Client-Side Logging

While creating software, developers typically use an integrated
development environment (IDE), within which a console displays log
information. Seeing this log information as the code is executed
provides immediate feedback that the code does or does not work as
intended. To provide this IDE-ish console capability, Log4Ajax
creates a div inside of the browser dedicated to
display log information (from here on referred to as the
console div). By appending debug text to the
innerHTML of the div, the look, feel, and
utility of an IDE logging console is available within your AJAX

Let's dive into the sample code. The content of
Example1.html is HTML and JavaScript typical of most web

  <title>Log4Ajax Example</title>
  <link rel="stylesheet" href="style.css" type="text/css" />
  <script type="text/javascript" src="js/request.js"></script>
  <script type="text/javascript" src="js/log4ajax.js"></script>

  <h2><code>Log4Aajax Example</code></h2>
  <br />
     <input type="button" id="button1" value="Button 1" 
         onclick="LOG.debug('Clicked button: ' +;" 
         onmouseover="LOG.debug('Mouseover button: ' +;" />
     <input type="button" id="button2" value="Button 2" 
        onclick="LOG.debug('Clicked button: ' +;" 
        onmouseover="'Mouseover button: ' +;" />

  <!-- Log Console -->
  <table align="center">
     <div class="consoleDiv" id="logConsole"></div>
   <tr align="center">
     <input type="button" id="clearLogConsole" value="Clear Debug Console" 
         onclick="getElementById('logConsole').innerHTML='';" />

  <script type="text/javascript">
      LOG.debug("Initilization complete");


Nothing in Example1.html probably jumped out as
particularly exciting. The section of interest, however, is just
after the Log Console comment. By creating an HTML div with a
well-known id, we're allowing the content of this
div to be manipulated through JavaScript. The position
and size of the console div within the browser is
arbitrary, but the css scroll style attribute is set to a value of
AUTO to enable scrolling. The id of this
div is then put to use within log4ajax.js:

// log4ajax.js
 * Provide logging capabilities to AJAX applications.
function LOG()
  throw "Do not instantiate LOG";

LOG.consoleDivId = "logConsole";
LOG.transmitToServer = true;

LOG.debug = function(msg)
   LOG._log(msg, "debug");
} = function(msg)
   LOG._log(msg, "info");

LOG.warn = function(msg)
   LOG._log(msg, "warn");

LOG.error = function(msg)
   LOG._log(msg, "error");

LOG.fatal = function(msg)
   LOG._log(msg, "fatal");

LOG._log = function(msg, logLevel)
   LOG._logToConsole(msg, logLevel);
   // ....

LOG._logToConsole = function(msg, logLevel)
   var consoleDiv = document.getElementById(LOG.consoleDivId);
   if (consoleDiv)
     consoleDiv.innerHTML = "<span class='log_" + logLevel + "'>"
                + logLevel + "</span>: " + msg + "<br />"
                + consoleDiv.innerHTML;

log4ajax.js defines a JavaScript object named
LOG. This object provides the five standard log
functions: debug, info,
warn, error, and fatal.
These functions are very straightforward and simply pass a string
representing the log level and the string argument msg
to an internal function (indicated by the underscore in the
function name) named _log. The _log
function in turn, passes both the msg and
logLevel arguments to another function named
_logToConsole, which uses the well-known
id contained within the variable
LOG.consoleDivId to acquire a reference to the console
div. Through the use of this reference, the function
argument msg is appended to the existing content of
the console div. To pretty up the output, the log
level is wrapped by a span tag to change the

Now that we have a console to display log information and the
plumbing code in place, what does this buy us? As we have done in
Example1.html, pepper your code with
LOG.debug() (or any of the various levels) statements,
refresh your browser, and watch the information accumulate in the
console div as your JavaScript executes. The familiar
log console you are accustomed to having inside of your IDE is now
right inside of your browser.

You can already see examples of the console div concept in the
wild. While looking over the Google Maps API, the following line of
code is sprinkled throughout their project:

document.getElementById("message").innerHTML = latLngStr;

Google is using the exact same technique and is creating a
div in the browser (not shown), getting a reference to
that div through the use of
getElementById and a well-known id, and
modifying the innerHTML to display the contents of the
string latLgnStr.

Although these examples are extremely trivial, you can begin to
see why this useful. You are now able to execute your JavaScript
and see the individual steps of its execution without the use of
alerts or a debugger. As your JavaScript and AJAX applications
become increasingly complex, the utility of this console
div only increases, saving you time and making you more

Client-to-Server-Side Logging

Beyond using logging as an aid during development, it is also
used to provide a history of what events occurred as actors used
the system in your deployed environment. At any time, this history
can be analyzed to assess the health of the application. While a
standard capability in "traditional" software development, AJAX
applications run in the client browser and lack the ability to
persist client-side history. As the name implies, Log4Ajax solves
this problem by using AJAX transmissions of the client-side context
to the server, where they are persisted. Again, let's dive into some
sample code. This time, we add additional functionality to the
previously discussed log4ajax.js:

// log4ajax.js revised
LOG._log = function(msg, logLevel)
   LOG._logToConsole(msg, logLevel);

   if (LOG.transmitToServer)
      LOG._logToServer(msg, logLevel);

LOG._logToServer = function(msg, logLevel)
   var data = logLevel.substring(0, 1) + msg;
   // Use request.js to make an AJAX transmission to the server
    url: "log",
    method: "POST",
    body: data,
    callback: LOG._requestCallback

LOG._requestCallback = function()
   // Process any return value data here

The additional code passes the variable msg and the
log level to the function _logToServer. Within
_logToServer, we concatenate these function parameters
into a string and transmit this string to the server. To try to
help isolate AJAX inconsistencies between different browsers, I
chose to use "">Http, a freely
available AJAX library written by Adam Vandenberg, for our AJAX
transmissions. Once our transmission is received by the server, it
is parsed and the relevant information is captured using any
logging framework available on your server. Although this article
is Java-centric, there is nothing that ties the Log4Ajax or AJAX
concepts to Java. The server-side process that accepts the AJAX
transmission can be implemented with any number of technologies; for examples in this article, I have chosen to implement this
process with a Java servlet filter. Here is the sample code:

public void doFilter(ServletRequest req, 
                     ServletResponse resp, 
                     FilterChain chain) 
                     throws IOException, ServletException
   String s = "";
      s = this.readInput((BufferedReader) req.getReader());
      if (s.length() > 0)
         HttpSession session = ((HttpServletRequest) req).getSession();
         String userId = (String) session.getAttribute("userId");
         if (userId == null)
            userId = "anonymousUser";
         String logLevel = s.substring(0, 1);
         String message = s.substring(1);
         this.log(logLevel, userId + "\t" + message);
  catch (Exception e)
     PrintWriter pw = resp.getWriter();
 * Log the message at the specified level using the underlying log
 * mechanism.
 * @param logLevel
 *            The category to log the message at, ie: debug, info, etc.
 * @param msg
 *            The message to log.
private void log(String logLevel, String msg)
   if ("d".equalsIgnoreCase(logLevel))
   else if ("f".equalsIgnoreCase(logLevel))
   else if ("i".equalsIgnoreCase(logLevel))
   else if ("e".equalsIgnoreCase(logLevel))
   else if ("w".equalsIgnoreCase(logLevel))

Using the filter, the client-side context is captured on the
server. Since this implementation is using Log4j, the actual output
format is configurable. Depending on your choice of configuration,
the output will be similar to Figure 1:

Figure 1. Sample output log

Transmitting client-side information to the server to be
captured by a standard logging mechanism is at the heart of
Log4Ajax. The code is simplistic and trivial, but the capability it
offers is powerful. You are now able to capture debug and event
information from AJAX applications, just as you would expect to be
able to do from a thick client. There are probably dozens of
areas in your AJAX applications that could benefit from
this concept.

Network Optimizations

The provided code samples demonstrate the basic Log4Ajax concept
and are not extremely sophisticated. As with all software, there
are several opportunities for improvement beyond the basic working
system that are centered on wisely taking advantage of the
available processor and network resources.

Overhead is associated with establishing and tearing down
network connections. Making an AJAX transmission for each log
statement is highly inefficient and could possibly saturate your
network. To minimize this problem, reduce the number of
transmissions by buffering log statements. Each time a log method
is invoked, increment a counter and write the statement to both the
console div and a statement cache. Once the counter has reached or
exceeded some integer threshold, read the entire statement cache,
bundle it into a single transmission, transmit it, and clear the
statement cache. For maximum flexibility, the design of the
receiving process, likely a servlet or filter, should support both
the bundled and individual log request formats. As a word of
caution, error and fatal log statements should not be cached and
should be sent without delay, or you'll risk encountering a fatal
error before these statements are transmitted.

Depending on the value of the integer transmission threshold,
buffering statements opens the possibility that a large period of
time might pass before enough statements accumulate to warrant a
transmission. By using a timer, provided by JavaScript's
setInterval() method, the statement cache can be
periodically transmitted and flushed to reduce the amount of
logging data lost, should your application suffer an unrecoverable

A client-side performance improvement over the demonstrated
Log4Ajax example is to take advantage of the asynchronous
capabilities of the browser's AJAX support. Since the flow of
logging information is unidirectional, there is no need to
synchronously transmit log statements and have the browser wait for
an empty or nearly empty response from the server. Asynchronously
fire and forget.

Client Optimizations

The use of Log4Ajax, as that of any logging system, has performance
implications that you need to consider. Fortunately, there are a
few enhancements that can be made to minimize the impact on your

Constantly appending text to the console div will
have a negative impact on browser performance. I have no hard
numbers for you, but as your application runs, you'll inevitably
notice that the logging code takes longer to execute than does the
"meat" of your application. How much time will pass before you
experience this will vary from system to system, but it's on the
order of minutes and not hours. Consider adding the ability to
periodically empty the display div and the overall
performance impact of this problem will be negligible.

A standard feature of all logging systems is the ability to
reduce or filter the amount of information logged. While in early
development, most projects log at the debug level and
transition to less-verbose levels as the project progresses toward
production. This log-level threshold concept could be implemented
into Log4Ajax on both the writing of messages to the console
div and the transmission of these messages to the
server. These two settings could then be adjusted independently,
allowing only error- and fatal-level
information to be displayed in the console div while having all
debug, info, warn,
error, and fatal information transmitted
to the server, for example.

No matter how many optimizations you implement, the hard fact is
that any use of AJAX has the potential to increase congestion on
your network and can impact the client browser performance. Keep
this in mind as you design your application and your targeted
network infrastructure.


None of the concepts used in Log4Ajax are earth-shattering or
overly complex. It is the combination of simple solutions that
provides a flexible yet powerful client- and server-side logging
system. With the implementation of the described advanced features,
the value added by Log4Ajax becomes quite high. It won't "">rid the world of disease, but I
believe it will help you deliver a higher quality AJAX application
in a shorter amount of time.


width="1" height="1" border="0" alt=" " />
Eric Spiegelberg is a Minneapolis-based Java/EE consultant specializing in Spring, Hibernate, and web-based software development.
Related Topics >> Programming   |