Application logging is something we all do in our applications that get deployed on an application server, right? Using frameworks like Log4J or Logback seems like a no-brainer to most Java developers. But what about the code we’ve written that is running in those pesky browsers? I guess that, apart from the occasional console.log() statement used during debugging, we don’t give much thought to JavaScript logging. I find this situation very regrettable since nowadays the trend appears to be to move our application logic to the browser. And with it, interesting events happening in the browser might go unnoticed, or any bugs that will happen, no matter how well we’ve developed and tested our client side code, might prove needlessly hard to reproduce and therefore fix. In this blog post I’ll demonstrate a very basic setup to log messages from the browser on the server using some very basic JavaScript with jQuery, and a simple Spring controller with Slf4J.
Server side code
Assuming you already have an existing Spring web application up and running and are using SLF4J for your application logging, all we have to do is add an additional @Controller that will take care of logging any incoming messages.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 |
package it.jdev.demo; import java.lang.invoke.MethodHandles; import javax.servlet.http.HttpServletRequest; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.http.HttpStatus; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.bind.annotation.ResponseStatus; @Controller @RequestMapping(value = "/js-log") public class JSLogger { private static final Logger LOGGER = LoggerFactory.getLogger(MethodHandles.Lookup.class); @RequestMapping(method = RequestMethod.POST) @ResponseStatus(HttpStatus.NO_CONTENT) public void logError(final HttpServletRequest request, @RequestBody(required = true) final String logMessage) { final String ipAddress = request.getRemoteAddr(); final String hostname = request.getRemoteHost(); LOGGER.warn("Received client-side logmessage (" + ipAddress + "/" + hostname + "): " + logMessage); } } |
JavaScript code
For the JavaScript part of our logging solution we’ll add a JS file called jdev.js. In it we’ll define a module named JDEV.logging that will contain a method called logToServer(). This method will send an Ajax message to our controller with a little bit of help from jQuery. Just make sure that the url variable points to the endpoint configured in our controller’s @RequestMapping.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 |
var JDEV = JDEV || {}; JDEV.namespace = function(ns_string) { var parts = ns_string.split('.'); var parent = JDEV; // strip redundant leading global if (parts[0] === "JDEV") { parts = parts.slice(1); } for (var i = 0; i < parts.length; i += 1) { // create a property if it doesn't exist if (typeof parent[parts[i]] === "undefined") { parent[parts[i]] = {}; } parent = parent[parts[i]]; } return parent; }; JDEV.namespace('logging'); JDEV.logging = (function() { var logToServer = function(logMessage) { var logEventObject = { "message" : logMessage, "location" : location.href, "browser" : navigator.userAgent, }; var logMsg = JSON.stringify(logEventObject); var url = "js-log"; $.ajax({ type : "POST", url : url, data : logMsg, contentType : "application/json", cache : "false", }); } return { logToServer : logToServer, } })(); |
All that is left to do, is include jQuery and our jdev.js file in our html pages, and instead of calling console.log() use our new logging method:
1 2 3 4 5 6 7 8 9 |
<script src="//code.jquery.com/jquery-1.11.0.min.js"></script> <script type="text/javascript" src="js/jdev.js"></script> <script type="text/javascript"> $(document).ready(function() { JDEV.logging.logToServer("Hi from the browser..."); }); </script> </body> </html> |
If everything is set up correctly, you should wind up with a similar log entry:
WARN : Received client-side logmessage (127.0.0.1/localhost): {"message":"Hi from the browser...","location":"http://localhost:8080/demo/","browser":"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/38.0.2125.104 Safari/537.36"}
Wrapping up
I’ve demonstrated a very simple design making it possible to log entries in your server side log that originate from browser side JavaScript code. Of course, you can elaborate on this example, e.g. by adding the possibility to send along the Log Level with the Ajax call.
One Reply to “Server side logging from browser side JavaScript code”
Comments are closed.