I'm building a logging module that can be called by multiple callers located in different files.
My objective is to initialize the log file at the start of program and have the callers just call a function that logs to the file initialized earlier without going through the whole initialisation again.
I can't quite grasp the concept of module exports hence I'm hoping that you can help.
The actual logging occurs on the method write. On the main app.js file, I can initiate and log just fine.
However on a different file, I'm having a mental block on how I can just log to the file without going through creating the logfile again.
var fs = require('fs');
var fd = {},
log = {},
debug = false;
var tnlog = function(env, file, hostname, procname, pid) {
if (env == 'development')
debug = true;
fd = fs.createWriteStream(file, { flags: 'a', encoding: 'utf8', mode: 0644 });
log = { hostname: hostname, procname: procname, pid: pid };
};
tnlog.prototype.write = function(level, str) {
if (debug)
console.log(str);
else {
log.timestamp = Date.now();
log.level = level;
log.str = str;
fd.write(JSON.stringify(log) + '\n');
}
};
exports.tnlog = tnlog;
This is how I initialize and logging on the main file:
var logfile = '/var/log/node/www/app.log';
var tnlog = require('./lib/tnlog').tnlog,
log = new tnlog(app.get('env'), logfile, os.hostname(), appname, process.pid);
If you can suggest a better way of doing things, I definitely will appreciate that.
The simplest solution would be to put
var logfile = '/var/log/node/www/app.log';
var tnlog = require('./lib/tnlog').tnlog,
module.exports = new tnlog(app.get('env'), logfile, os.hostname(), appname, process.pid);
into a separate file (mylogger.js), and require that anywhere you want to log something with logger = require "./mylogger.js . You always get back that single instance of tnlog, because node caches the exported value.
I also see you might be using Express, so you could also do
app.set("logger",new tnlog(app.get('env'), logfile, os.hostname(), appname, process.pid))
and retrieve it anywhere you have a reference to the app object with app.get("logger").
More complicated:
You must decide whether you want to support logging to different files while the same app is running. If so, you absolutely need to create an object for each log file. You don't have to export a constructor function per se, you could also export a kind of hybrid between a factory and a singleton pattern.
You would create something like:
var loggers = {}
module.exports = function getLogger(env, file, hostname, procname, pid) {
key = env + file + hostname + procname + pid)
if(loggers[key]) return loggers[key]
return loggers[key] = new Logger(env, file, hostname, procname, pid)
}
I.e. you check if you have already created the logger object, based on concatenating the function argument variables.
You then need to create a proper Logger constructor of course, but I assume you know a bit of Javascript.
Note that the loggers object will remain a private variable, just like the Logger constructor. Because node.js caches the object the module exports, the value of the loggers object will persist over multiple calls to require, as part of the getLogger closure.