Centralise JavaScript logs using log.jod.li

log.jod.li

It often happens that we need to gather logs from several sources. Centralising them in one simple server place is the purpose of the log.jod.li initiative. The logs are then visible almost instantaneously on the log.jod.li page or can be retrieved in a format similar to CSV (raw logs). For more details, please visit https://log.jod.li .

JavaScript situation

This page aims at showing how to use log.jod.li logs centralisation solution using JavaScript code.

Let’s say you have some JavaScript code that may not always run as expected. You want to track the exceptions and centralise their reading on log.jod.li . You may start with an HTML page. This page will contain JavaScript code with for example some “try…catch…”. In the catch, you can add a call to log the exception. This is a simple GET call to a URL containing:

  • The server name to send the log to the right location. This will be en.log.jod.li .
  • The user name you created on log.jod.li .
  • The user key you received in your email box when you created your user. Make sure nobody else gets access to your key.
  • The log message that you want to record on the log.jod.li server. The maximum length of the message is 1700 characters. It must be passed using the encodeURI() function so that the string is interpreted correctly by the server.
  • Optionally the application name so that you can filter your logs more easily. Max 32 characters.
  • Optionally the client guid so that you can filter on a given client. Max 32 characters.

Here is an example of URL:

https://en.log.jod.li/?api=a&u=toto&k=1234567890123456&a=BestApp&c=123456789&m=testing

Here, the user is “toto”, the key is “1234567890123456”, the application name is “BestApp”, the client guid is “123456789” and the log message is “testing”.

Let’s consider the following page:

<html>
<head>
<title>
JavaScript leading to Exception
</title>
</head>
<body>
<a id="MyLink" href="https://example.com">example link</a>
<script>
document.getElementById("MyLonk").innerHTML="example lonk";
</script>
</body>
</html>

This simple mistake in the JavaScript code trying to get an element with a typo in the id will generate the following error in the console:

Uncaught TypeError: Cannot set property 'innerHTML' of null
    at JavaScript_exception.html:10

This can easily be corrected with the help of the console but JavaScript can relate to elements more complex than this such as server responses or user input for example.

Complete version with outcome handling

What we can do to make use of log.jod.li in this case is using a “try…catch…” with a call to a URL similar to the one mentioned above. Here is the result:

<html>
<head>
<title>
JavaScript leading to Exception
</title>
</head>
<body>
<a id="MyLink" href="https://example.com">example link</a>
<br/>
<pre id="logresult"/> 
<script>
function log(message){
        var url = "https://en.log.jod.li/?api=a&u=toto&k=1234567890123456&c=MyFriend&a=TheApp&m="+encodeURI(message);
        var lr = document.getElementById("logresult");
        const http = new XMLHttpRequest();
        http.timeout = 5000;//in milliseconds
        http.open("GET", url, true);

        http.ontimeout = function(e){
                lr.innerHTML = "Request timed out.";
        };

        http.onprogress = function () {
                lr.innerHTML = "Request in progress.";
        };

        http.onload = function() {
                var t = http.responseText;
                if(http.status!=200){
                        t = "Unexpected HTTP code: "+http.status;
                }
                lr.innerHTML = t;                
        };

        http.onreadystatechange = function(){
                if(http.readyState == 4 && this.status != 200){
                        lr.innerHTML = "Unexpected HTTP code: "+http.status;
                }
        };

        http.send(null);
}
try{
        document.getElementById("MyLonk").innerHTML="example lonk";
}
catch(err){ 
        log(err.message);
}
</script>
</body>
</html>

As the key must be present in the code, the page cannot be accessed by anyone except yourself. This means that this page can only be used in non web contexts. For example the automation through personal pages, server side JavaScript (Node.js), mobile application development (Meteor), personal bookmarklets,….

Simple version to log when possible

Since we don’t necessarily need to know what happens with the log sending, we can simplify all of this as follows:

<html>
<head>
<title>
JavaScript leading to Exception
</title>
</head>
<body>
<a id="MyLink" href="https://example.com">example link</a>
<br/>
<script>
function log(message){
try{
        var url = "https://en.log.jod.li/?api=a&u=toto&k=1234567890123456&c=MyFriend&a=TheApp&
m="+encodeURI(message);
        const http = new XMLHttpRequest();
        http.timeout = 5000;//in milliseconds
        http.open("GET", url, true);
        http.send(null);
}
catch(err){}
}
try{
        document.getElementById("MyLonk").innerHTML="example lonk";
}
catch(err){ 
        log(err.message);
}
</script>
</body>
</html>

The outcome on the log.jod.li page is:

2018-09-11 20:34:28	MyFriend	TheApp	Cannot set property 'innerHTML' of null

Here is the result on the raw CSV log from log.jod.li :

2018-09-11 20:34:28,MyFriend,TheApp,Cannot set property 'innerHTML' of null

Conclusion

This is a demonstration that you can log your messages by simply calling a url. You can then follow your logs from the https://log.jod.li page. This may be more relevant in other languages than JavaScript where the source code is not directly available so that the key is not readable to everyone. Though, there are many situations where the JavaScript code is not readable to anyone except the developer (server side Node.js, application development Meteor, personal bookmarklets,…). Please bear in mind that the logs cannot contain personal data and cannot be sent without the user consent.