Logging errors in Reactjs (Client-side) application is an important part of software development. Both in development and production mode. However, when it comes to client-side applications, logging is something that often gets overlooked, and options available for you are limited. In this article I will explain how to implement your own logging mechanism using ReactJs and node for free. No paid services are used.
When you are working with Node, ReactJs web application there are hundreds of libraries get installed. You cannot predict which library or which code cause errors. You cannot test all the test cases yourself. When application run in production mode you don’t know which JavaScript code generate errors. Due to that your customers may not get better user experience by using your application.
Introduction
If you think it is difficult or impossible to create logs for ReactJs application, you may find that how easy to setup logs using ReactJs. This article not only focus on logging errors but also logging other information required. We are using Winston for server side and log4javascript for client side. If you wish to see demo before further continuation click here to view Demo
What we are going to do ?
Catch all errors and other custom logs required on client-side by using log4javascript plugin and pass it to node server. From node server all logs will be stored to a file in systematic order. Files are stored using a rotatable structure named according to date. Create custom filter to filter only errors (not all info logs) and store them in a separate file.
Step 1: Setup node server to support logging
About Winston
Winston is designed to be a simple and universal logging library with support for multiple transports. A transport is essentially a storage device for your logs. Each instance of a winston logger can have multiple transports configured at different levels. For example, one may want error logs to be stored in a persistent remote location (like a database), but all logs output to the console or a local file.
There also seemed to be a lot of logging libraries out there that coupled their implementation of logging (i.e. how the logs are stored / indexed) to the API that they exposed to the programmer. This library aims to decouple those parts of the process to make it more flexible and extensible.
Let’s setup express server to support logging using “winston”.
var express = require("express")
var bodyParser = require('body-parser');
var path = require("path");
var winston = require( 'winston' );
var fs = require('fs');
require('winston-daily-rotate-file');
//Initialize server instance
var Server = new express();
//Set loggineg files
var infoFilename = path.join(__dirname,'..','logs','all', 'logfile.log');
var errorFilename = path.join(__dirname,'..','logs', 'errors', 'errorfile.log');
Server.use(bodyParser.urlencoded({ extended: true }));
//Log server settings
var transportInfo = new (winston.transports.DailyRotateFile)
({
name:"infofile",
filename: infoFilename,
datePattern: 'yyyy-MM-dd.',
prepend: true,
level:'info',
});
//Filter error messages from log
var transportError = new (winston.transports.DailyRotateFile)({
name:"errorfile",
filename: errorFilename,
datePattern: 'yyyy-MM-dd.',
prepend: true,
level: 'error'
});
var logger = new (winston.Logger)({
transports: [
transportInfo, transportError
]
});
//first log
logger.info('Log Server started');
logger.error('Log Server started');
// logger api
Server.post ('/api/logger', function( req, res, next ) {
logger.log( req.body.level.toLowerCase() || 'error',
'Client: ' + req.body.message);
return res.send( 'OK' );
});
//End of logger
/**
.....
*/
Server.listen(config.SERVER_PORT, function(error) {
if (error) {
console.error(error)
} else {
console.info("==> 🌎 Listening on", config.SERVER_PORT, config.SERVER_PORT)
}
})
Please note that only the configuration required for logging API is shown. Other express settings need for Reactjs not shown here. Click here to get full code setup to support ReactJs logging with express.
Now is the best part. Let’s configure Reactjs or client side to support Logging.
Step 2: Setup client-side logging
We are using log4javascript npm package for client side logging.
About log4javascript
log4javascript is a JavaScript logging framework based on the Java logging framework log4j. log4javascript is designed to work in all major browsers. Internet Explorer 5 onwards on Windows, Firefox 1.0 onwards, Safari 1.2 onwards, Opera 8.01 onwards, Konqueror 3.4 onwards and Google Chrome are all fully supported.
The default way to display log messages is in a separate log4javascript window, featuring advanced search and filtering functionality, as well as a command line. You can also log to an in-page log4javascript console, to Firebug, to Opera and Safari’s built-in error consoles or back to the server via Ajax.
Why are we waiting let’s start integrating log4javascript to ReactJs web application.
componentDidMount(){
//in debug mode replace line 4 with line 3.
//window.myLogger = log4javascript.getDefaultLogger();
window.myLogger = log4javascript.getLogger();
var ajaxAppender = new log4javascript.AjaxAppender('/api/logger');
ajaxAppender.setBatchSize(10); // send in batches of 10
ajaxAppender.setSendAllOnUnload(); // send all remaining messages on window.beforeunload()
window.myLogger.addAppender(ajaxAppender);
//report all user console errors
window.onerror = function(message, url, lineNumber) {
var errorMsg = "Console error- "+url+" : "+lineNumber + ": "+message
window.myLogger.error(errorMsg);
return true;
};
}
In above code sample you can see that we just setup our custom logger. In addition to that we catch all console errors. Using our custom logger you can create logs that are necessary for your project. We assign our custom logger to window variable in order to access our logger from anywhere. You can use react context type for that too. But I prefer this because of less code. Please note that to add our custom logger to “componentDidMount” function. If you add our custom logger to “componentWillMount” it will not run only if you are using server side rendering. Because on server side “window” variable is undefined. Therefore we need to run that code only on client side.
Lets send custom logs and errors logs to express and store them.
//Sending error message to server
window.myLogger.error("test error message");
//Sending info log to server
window.myLogger.info("test info");
Example (demo)
To run logging application in development mode
npm install
npm run start
To run logging application in production mode
npm install
npm run build
Click below link to download source code