Implementing Logging Functionality in Open Event Webapp

  • INFO: Info statements give information about the task currently being performed by the webapp
  • SUCCESS: Success statements give the information of a task being successfully completed
  • ERROR: Error statements give information about a task failing to complete. These statements also contain a detailed error log

Along with the type of the statement, the object also contains information about the task. For all types of statements, there is a field called smallMessage containing short information about the task. For the ERROR statements where more information is required to see what went wrong, the message object has an additional field called largeMessage which holds detailed information about the event.

We also create a new file called buildlogger.js and define a function for creating log statements about the tasks being performed by generator and export it. The function creates a message object from the arguments received and then return it to the client under the buildLog event via the socket IO.

exports.addLog = function(type, smallMessage, socket, largeMessage) {
 var obj = {'type' : type, 'smallMessage' : smallMessage, 'largeMessage': largeMessage};
 var emit = false;
 if (socket.constructor.name === 'Socket') {
   emit = true;
 }
 if (emit) {
   socket.emit('buildLog', obj);
 }
};

Most of the steps of the generation process are defined in the generator.js file. So, we include the logging file there and call the addLog function for sending logs messages to the client. All the different steps like cleaning temporary folders, copying assets, fetching JSONs, creating the website directory, resizing images etc have multiple log statements for their inception and successful/erroneous completion. Below is an excerpt from the cleaning step.

var logger = require('./buildlogger.js');
 async.series([
   (done) => {
     console.log('CLEANING TEMPORARY FOLDERS\n');
     logger.addLog('Info', 'Cleaning up the previously existing temporary folders', socket);
     fs.remove(distHelper.distPath + '/' + appFolder, (err) => {
       if(err !== null) {
         // Sending Error Message when the remove process failed
         logger.addLog('Error', 'Failed to clean up the previously existing temporary folders', socket, err);
       }
       // Success message denoting the completion of the step
       logger.addLog('Success', 'Successfully cleaned up the temporary folders', socket);
       done(null, 'clean');
     });
   }
 )]

But we have only done the server side work now. We also have to handle the message on the client side. We send the message object to the client under the event buildLog and set up a listener for that event to catch the sent message. After the message object is received on the client side, we extract the information out of that object and then display it on the website. We have a div having an id of buildLog for displaying the log information. The content of the message is dynamically added to it as soon as it is received from the server. All the client side logic is handled in the form.js file.

socket.on('buildLog', function(data) {
   var spanElem = $('<span></span>'); // will contain the info about type of statement
   var spanMess = $('<span></span>'); // will contain the actual message
   var aElem = $('<button></button>'); // Button to view the detailed error log
   var paragraph = $('<p></p>'); // Contain the whole statement
   var divElem; // Contain the detailed error log
   spanMess.text(data.smallMessage);
   spanElem.text(data.type.toUpperCase() + ':');
   paragraph.append(spanElem);
   paragraph.append(spanMess);
   divElem.text(data.largeMessage);
   paragraph.append(aElem);
   paragraph.append(divElem);
   $('#buildLog').append(paragraph); // Div containing all the log messages
};

This is how the logs look on the client side. They are loaded on the go in real time as and when the events occur.

image (1).jpg

Resources: