Click here to Skip to main content
14,643,156 members
Articles » Web Development » Client side scripting » General
Tip/Trick
Posted 2 Dec 2015

Stats

15K views
10 bookmarked

Logging JavaScript Errors at Server Side

Rate this:
4.78 (12 votes)
Please Sign up or sign in to vote.
4.78 (12 votes)
2 Dec 2015CPOL
Capturing JavaScript errors occured in user's browser at Server side

Introduction

When an exception occurs in the code which is running on the server, either from log file (if handled and logged) or from event log (unhandled exception in case of Windows), we would be able to get error details for investigation. It's fine on the server side but capturing JavaScript errors occurring at client browser is not that easy. At times, we get complaints from users saying a web page or a functionality in it is not working properly. As a web developer, we find it hard to find out the issue.

I personally ran into such a situation recently and thought how easy it would be if we were able to track the JavaScript errors occurring at users' browser.

Will go step by step to implement a solution for this.

1. Create a HTTP Service

To send error details from browser to server, a simple http service is required. Just create a Web API project in VS and copy paste the below piece of code inside the Web API controller.

static readonly string logFile=WebConfigurationManager.AppSettings["LogFilePath"];
static readonly object _syncObject = new object();
// api/<your_controller>/trackLog
public void trackLog()
{
    try
    {
        string exData = Request.Headers.GetValues("Data").FirstOrDefault();
        Log(exData);
    }
   catch (Exception e) { }
}
private static void Log(string msg)
{
    if (!System.IO.File.Exists(logFile))
        System.IO.File.Create(logFile).Dispose();
    lock (_syncObject)
    {
        System.IO.File.AppendAllText(logFile, msg + " " + 
        DateTime.Now + Environment.NewLine + Environment.NewLine);
    }
}
  1. Create a key 'LogFilePath' inside appSetting in .config file and assign it with absolute file path.
    Example: D:\somefolder\log.txt
  2. Since we are performing I/O operation by writing data to single file, synchronization needs to be applied. Especially, in our scenario, multiple http requests may be invoked which in turn will call our controller method trackLog() by different process.
  3. In this example, Custom HTTP Header (Data) is used to carry the error data. POST can also be used based on our convenience. Please note that HTTP GET request using query string will expose the data that are being passed in the URL which I don't want. Prefer to be a silent task.
  4. Extract data from header and write the same to the disk or any other source, say SQL.

Once all is done, Web API address should be something like below

protocol://<your_site_name>/api/<your_controller_name>/trackLog

2. Detect JS Exceptions and Fire a Request to Server

It's pretty simple, Just subscribe to window.onerror event on the web page. So, whenever an exception occurs, assigned function will be invoked with error details which in turn will fire AJAX call.

var browserDetails=getBrowser();
var errList=['SyntaxError','TypeError','RangeError','URIError'];//ReferenceError excluded
window.onerror = function(error) {
    logErr(error);
};
function logErr(error){
    if(errList.indexOf(error.name)>=0){
       $.ajax({
             url: 'api/<controller_name>/trackLog',
             async: true,
             type: "GET",
             beforeSend: function(xhr){xhr.setRequestHeader
             ('Data', browserDetails + ' : ' + error);},
             success: function() { console.log('error logged : '+error); }
          });
    }
}
function getBrowser(){
    var ua=navigator.userAgent,tem,M=ua.match
    (/(opera|chrome|safari|firefox|msie|trident(?=\/))\/?\s*(\d+)/i) || []; 
    if(/trident/i.test(M[1])){
        tem=/\brv[ :]+(\d+)/g.exec(ua) || []; 
        return 'IE'+' '+(tem[1]||'');
    }   
    if(M[1]==='Chrome'){
        tem=ua.match(/\bOPR\/(\d+)/)
        if(tem!=null) 
            return 'Opera'+tem[1];
    }   
    M=M[2]? [M[1], M[2]]: [navigator.appName, navigator.appVersion, '-?'];
    if((tem=ua.match(/version\/(\d+)/i))!=null) {M.splice(1,1,tem[1]);}
    return M[0]+' '+ M[1];
}

Pack the above code into a js file and include reference in master page if you require logging for the entire website or in a specific page based on your requirement. By placing it in a separate js file, we can switch logging on/off adding/removing this js file reference.

  1. In addition to the exception details, browser name & version can also be sent as illustrated above. Make sure that this code will be executed only once by placing it inside PageLoad or document.ready, so that browser details will be get only once and not everytime when exception occurs.
  2. JS Exceptions are classified into various kinds. We can include only those exceptions which we target to log. I have excluded Reference error as I don't want to track it.
  3. As and when an exception occurs, window.onerror will invoke the assigned function which will invoke logErr() ultimately.
  4. A note here. I have placed AJAX call in a separate JS function, making not tightly coupled with onerror(). So that, in case if we want to log our own messages to the server, logErr() can be invoked programmatically.

Example: logErr('data is null');

Captured JS Exceptions in Log File

logging snapshot

 

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

Share

About the Author

Kanivalan Raju
Software Developer (Senior) Microsoft Global Delivery
India India
Yet another software developer who works on various Microsoft and Web technologies but curious to try something beyond an usual

Comments and Discussions

 
GeneralMy vote of 4 Pin
Santhakumar M5-Dec-15 19:12
professionalSanthakumar M5-Dec-15 19:12 
SuggestionNice but... Pin
Nitij4-Dec-15 21:38
professionalNitij4-Dec-15 21:38 
SuggestionSecurity and file management Pin
ahagel3-Dec-15 14:43
Memberahagel3-Dec-15 14:43 
GeneralMy vote of 4 Pin
Abhishek Kumar Goswami2-Dec-15 19:07
professionalAbhishek Kumar Goswami2-Dec-15 19:07 
GeneralMy vote of 5 Pin
rosdi2-Dec-15 15:05
Memberrosdi2-Dec-15 15:05 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.