There is a new requirement that the server use Nodejs to type log files and capture request logs. And then I came up with log4js…
Without further ado, go to the code
Install log4js
npm install log4js --save
Copy the code
Unfamiliar with the log4js view document log4js;
Create log_config.js file in config folder:
var log4js = require("log4js");
var path = require("path");
var fs = require("fs");
var basePath = path.resolve(__dirname, ".. /logs");
var errorPath = basePath + "/errors/";
var resPath = basePath + "/responses/";
var errorFilename = errorPath + "/error";
var resFilename = resPath + "/response";
/** * determine if the directory exists and create a directory */ if it does not
var confirmPath = function(pathStr) {
if(! fs.existsSync(pathStr)) { fs.mkdirSync(pathStr);console.log("createPath: "+ pathStr); }}; log4js.configure({appenders: {
errorLog: {
type: "dateFile".// Log type
filename: errorFilename, // Log output position
alwaysIncludePattern: true.// Is there always a suffix
pattern: "-yyyy-MM-dd.log" // suffix, a new log file is created every hour
},
responseLog: {
type: "dateFile".filename: resFilename,
alwaysIncludePattern: true.pattern: "-yyyy-MM-dd.log"}},categories: {
errorLog: { appenders: ['errorLog'].level: 'error' },
responseLog: { appenders: ["responseLog"].level: "info" },
default: { appenders: ['responseLog'.'errorLog',].level: 'trace'}},// pm2: true,
// pm2InstanceVar: 'INSTANCE_ID',
disableClustering: true
});
// create root directory 'logs'
if (basePath) {
confirmPath(basePath);
// Create different file directories based on different logtypes
confirmPath(errorPath);
confirmPath(resPath);
}
module.exports = log4js;
Copy the code
This code is explained in the official document configuration line;
Create a new log.js file under config:
var log4js = require("./log_config");
var errorLog = log4js.getLogger("errorLog"); // The category value is used here
var resLog = log4js.getLogger("responseLog"); // The category value is used here
var log = {};
log.i = function(req, resTime) {
if(req) { resLog.info(formatRes(req, resTime)); }}; log.e =function(ctx, error, resTime) {
if(ctx && error) { errorLog.error(formatError(ctx, error, resTime)); }};// Format the request log
var formatReqLog = function(req, resTime) {
let getClientIp = function (req) {
return req.headers['x-forwarded-for'] ||
req.connection.remoteAddress ||
req.socket.remoteAddress ||
req.connection.socket.remoteAddress || ' ';
};
let ip = getClientIp(req).match(/\d+.\d+.\d+.\d+/);
var logText = new String(a);// Access methods
var method = req.method;
logText += "request method: " + method + "\n";
// Request the original address
logText += "request originalUrl: " + req.originalUrl + "\n";
// Client IP address
logText += "request client ip: " + ip + "\n";
// Request parameters
if (method === "GET") {
logText += "request query: " + JSON.stringify(req.query) + "\n";
} else {
logText += "request body: " + "\n" + JSON.stringify(req.body) + "\n";
}
// Server response time
logText += "response time: " + resTime + "\n";
return logText;
};
// Format the response log
var formatRes = function(res, resTime) {
var logText = new String(a);// The response log starts
logText += "\n" + "*************** response log start ***************" + "\n";
// Add the request log
logText += formatReqLog(res, resTime);
// Response status code
logText += "response status: " + res.res.statusCode + "\n";
// Response content
logText += "response body: " + "\n" + JSON.stringify(res.body) + "\n";
// The response log ends
logText += "*************** response log end ***************" + "\n";
return logText;
};
// Format error log
var formatError = function(ctx, err, resTime) {
var logText = new String(a);// Error message starts
logText += "\n" + "*************** error log start ***************" + "\n";
// Add the request log
logText += formatReqLog(ctx, resTime);
// Wrong name
logText += "err name: " + err.name + "\n";
// Error message
logText += "err message: " + err.message + "\n";
// Error details
logText += "err stack: " + err.stack + "\n";
// The error message ends
logText += "*************** error log end ***************" + "\n";
return logText;
};
module.exports = log;
Copy the code
I’m just going to write three functions here,
- Request log formatReqLog;
- Format response log formatRes;
- Log formatError;
Configure and use in app.js
const log = require("./config/log");
// logger
app.all("*".async (req, res, next) => {
// Response start time
const start = new Date(a);// Response interval time
var ms;
try {
// Start going to the next middleware
await next();
// Record the response log
ms = new Date() - start;
log.i(req, ms);
} catch (error) {
// Record the exception log
ms = new Date() - start;
log.e(req, error, ms);
}
console.log(`${req.method} ${req.url} - ${ms}ms-${res.statusCode}`);
});
Copy the code
There’s nothing to say about the code, just use it, and I’m going to talk about potholes
Fault 1: Pm2 + Log4JS fails to start the project
Nodejs application Error: bind EADDRINUSE when use pm2 deploy
sudo lsof -i -P | grep 3000
Copy the code
To solve the problem stamp here;
Fault 2: Log4JS with pM2 cluster exception log
For details, see the following link: Log4JS with PM2 Cluster Exception log solution
Pm2 is started in cluster mode, resulting in abnormal output of log4JS logs. Are there two solutions?
- Simply add the following command to log_config.js
disableClustering: true
Copy the code
I. Install the PM2-Intercom interprocess communication module ii of the PM2. Then add the following command to log_config.js
pm2: true,
pm2InstanceVar: 'INSTANCE_ID'
Copy the code
Iii. The pm2. Json as follows
{ "apps": [ { "name": "testing", "script": "pm2.js", "instances": 0, "instance_var": "INSTANCE_ID", // add the line exec_mode: "cluster"}]}Copy the code
The difference between the two solutions is :(from the author of log4js, I am so happy to have his help 😊)
It is better if you don't need 'disableClustering' and 'pm2' in your config. 'pm2: true` turns on support for using pm2-intercom, `disableClustering: True 'turns off all clustering support so it won't use PM2-intercom. Use one or the other, but not both.Copy the code
When deployed to the server, logs can be output normally, as shown below
The final reference article is as follows:
Official document link
Pm2 Official document PM2 usage analysis
log4js
- Log4js translation;
- Log4js with pM2 cluster exception log solution
- PM2 & log4JS && Winston Log management
- Vim’s command;
- Log4js configuration;