1
\$\begingroup\$

I'm new to JavaScript, and in Java I probably would do this as a singleton. I need something that I can call from anywhere and instantiate only once.

This is what I have done, but I need some advice to write it in the right way in this new prototype based and functional JavaScript.

var winston = require('winston');
var genericLogger = null,
 dbLogger = null,
 viewLogger = null,
 networkLogger = null;
function initLogger() {
 console.log('logger.js > initLogger');
 genericLogger = new (winston.Logger)({
 transports: [
 new (winston.transports.Console)(),
 new (winston.transports.File)({ filename: './log/error.log' })
 ]
 });
 dbLogger = new (winston.Logger)({
 transports: [
 new (winston.transports.Console)(),
 new (winston.transports.File)({ filename: './log/db.log' })
 ]
 });
 viewLogger = new (winston.Logger)({
 transports: [
 new (winston.transports.Console)(),
 new (winston.transports.File)({ filename: './log/view.log' })
 ]
 });
 networkLogger = new (winston.Logger)({
 transports: [
 new (winston.transports.Console)(),
 new (winston.transports.File)({ filename: './log/network.log' })
 ]
 });
}
initLogger();
var Logger = {}; 
Logger.error = function(n) {
 genericLogger.log('error', n);
};
Logger.info = function(n) {
 genericLogger.log('info', n);
};
Logger.db = function(t, n) {
 if(n) {
 dbLogger.log(t, n);
 } else {
 dbLogger.info(t);
 }
};
Logger.view = function(t, n) {
 if(n) {
 viewLogger.log(t, n);
 } else {
 viewLogger.info(t);
 }
};
Logger.network = function(t, n) {
 if(n) {
 networkLogger.log(t, n);
 } else {
 networkLogger.info(t);
 }
};
module.exports = Logger;

I can call it from anywhere with require, and I expose only few public methods with module.exports and due to the require mechanism there is only one instance.

Is there a cleaner way to do it? More OOP? More functional?

Alex L
5,7832 gold badges26 silver badges69 bronze badges
asked Jul 17, 2014 at 10:50
\$\endgroup\$

1 Answer 1

2
\$\begingroup\$

Interesting question,

You have a ton of repeating code, so don't hesitate to write more helper functions so that this:

genericLogger = new (winston.Logger)({
 transports: [
 new (winston.transports.Console)(),
 new (winston.transports.File)({ filename: './log/error.log' })
 ]
});
dbLogger = new (winston.Logger)({
 transports: [
 new (winston.transports.Console)(),
 new (winston.transports.File)({ filename: './log/db.log' })
 ]
});
viewLogger = new (winston.Logger)({
 transports: [
 new (winston.transports.Console)(),
 new (winston.transports.File)({ filename: './log/view.log' })
 ]
});
networkLogger = new (winston.Logger)({
 transports: [
 new (winston.transports.Console)(),
 new (winston.transports.File)({ filename: './log/network.log' })
 ]
});

could be:

function createLogger( filename ){
 return new (winston.Logger)({
 transports: [
 new (winston.transports.Console)(),
 new (winston.transports.File)({ filename: filename })
 ]
 });
}
genericLogger = createLogger( './log/error.log' );
dbLogger = createLogger( './log/db.log' );
viewLogger = createLogger( './log/view.log' );
networkLogger = createLogger( './log/network.log' );

I did not test this code, but you get the gist.

Furthermore, in this code, I have no idea what t and n are:

Logger.db = function(t, n) {
 if(n) {
 dbLogger.log(t, n);
 } else {
 dbLogger.info(t);
 }
};
Logger.view = function(t, n) {
 if(n) {
 viewLogger.log(t, n);
 } else {
 viewLogger.info(t);
 }
};

Here as well, you could use a helper function:

Logger.loggerHelper = function( o , t , n ){
 if(n){
 o.log(t,n) 
 } else {
 o.log(t)
 }
}
Logger.db = function(t, n) {
 loggerHelper( dbLogger , t , n );
};
Logger.view = function(t, n) {
 loggerHelper( viewLogger , t , n );
};

After a while I would get irritated by the above as well, and write something like this:

var winston = require('winston');
var Logger = {};
var loggers = {
 generic : './log/error.log',
 db : './log/db.log',
 view : './log/view.log',
 network : './log/network.log'
};
for( logger in loggers){
 Logger['_' + logger] = new (winston.Logger)({
 transports: [
 new (winston.transports.Console)(),
 new (winston.transports.File)({ filename: loggers[logger] })
 ]
 });
 Logger[logger] = function(t,n ){
 if(n) {
 Logger['_' + logger].log(t, n);
 } else {
 Logger['_' + logger].info(t);
 } 
 }
}
Logger.error = function(n) {
 Logger['_generic'].log('error', n);
};
Logger.info = function(n) {
 Logger['_generic'].log('info', n);
};
module.exports = Logger;

loggers contains the link between the method and the file name, so it becomes now very easy to add/remove/change loggers. This approach does expose a lot more (all) the functionality in Logger, but I think that would work out.

Alex L
5,7832 gold badges26 silver badges69 bronze badges
answered Jul 17, 2014 at 17:04
\$\endgroup\$

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.