Winston: Ability to pass in multiple arguments to logging calls?

Created on 23 May 2011  路  10Comments  路  Source: winstonjs/winston

@pigmej ran into an issue today in the IRC

 var winston = require('winston');
 winston.log('info', 'Hello distributed log files!', {"foo":"bar"}, ['123', '456']);


  node.js:134
          throw e; // process.nextTick error, or 'error' event on first tick
          ^
  TypeError: object is not a function
      at Array.CALL_NON_FUNCTION (native)
      at /usr/local/lib/node/.npm/winston/0.2.7/package/lib/winston/logger.js:107:42
      at [object Object].log (/usr/local/lib/node/.npm/winston/0.2.7/package/lib/winston/transports/console.js:46:3)
      at [object Object].log (/usr/local/lib/node/.npm/winston/0.2.7/package/lib/winston/logger.js:102:17)
      at Object.log (/usr/local/lib/node/.npm/winston/0.2.7/package/lib/winston.js:53:34)
      at Object.<anonymous> (/Users/maraksquires/dev/winston/test.js:3:9)
      at Module._compile (module.js:404:26)
      at Object..js (module.js:410:10)
      at Module.load (module.js:336:31)
      at Function._load (module.js:297:12)

I'm assuming this is a simple fix. What do you think indexzero?

Most helpful comment

@indexzero - The issue is that there is a disconnect between winston's logging method and the standard console.log which many developers are use to using.

It's pretty standard in JS land to do something like:

 console.log("this is foo", foo, " and this is bar", bar); 

I think it's pretty reasonable to emulate this API. There is already code out there for doing the arguments parsing. I would think all we have to do is determine if the last method is a FN or not, if it is, then thats the callback.

All 10 comments

@pigmej What's your use case for this? Just trying it out to see how it works? The correct way to do this is:

  var winston = require('winston');
  winston.log('info', 'Hello distributed log files!', { 'foo': 'bar', 'list': ['123', '456'] });

I'm trying not to go crazy with the flexibility of the arguments parsing in the core log function to prevent any unnecessary overhead given the frequency and concurrency that one would expect that method to be called.

Going to close this. Feel free to reopen it if you can provide a valid usecase. Thanks.

@indexzero - The issue is that there is a disconnect between winston's logging method and the standard console.log which many developers are use to using.

It's pretty standard in JS land to do something like:

 console.log("this is foo", foo, " and this is bar", bar); 

I think it's pretty reasonable to emulate this API. There is already code out there for doing the arguments parsing. I would think all we have to do is determine if the last method is a FN or not, if it is, then thats the callback.

@marak emulating console.log was not the main motivation behind winston. For example, it is already inconsistent: there is already a level parameter which must be passed to the function. That being said, I would accept a pull request for this, but I don't really consider it an issue.

@indexzero

The thing is for example

winston.log("info", "Something %s ... %s", foo, bar);

or
as @Marak wrote.

Then you don't need to do:

winston.log("info", "Something " + foo + " " + bar);

Even if by default winston formats {foo: 'bar'} as foo=bar.
Easier to migrate current projects that are using other logging things for logs (should work then with 'replace').

Errr printf style? No.

console.log style? Maybe.

I am writing server and client side javascript at the same time, and I personally find it really annoying if you have to concatenate everything into one thing. Especially because I forget and stuff disappears from the logs because of it.

I already had a factory method to create the logger, and I wrote a wrapper function which first concatenates the arguments before passing it to winston. It seems to work fine. Maybe it's useful to someone...

Note that in this example there is only a wrapper for the info function. But the others would work the same way I guess.

function createLogger(name){
    var filename = name;
    var winston = require('winston');

    var filepath = path.join(__dirname, logs, filename);
    var logger = new (winston.Logger)({
            transports: [
            new (winston.transports.Console)({ json : false, timestamp : true, level : 0 }),
            new (winston.transports.File)({ filename: filepath, json : false, timestamp : true, level : 0 })
            ]});

    wrap = {};
    wrap.info = function () {
        // convert arguments to real array
        var args = Array.prototype.slice.call(arguments);
        var str = args.join(" ");
        logger.log.apply(logger, ["info", str]);
    };

    wrap.error = logger.error;
    wrap.warn = logger.warn;
    wrap.data = logger.data;

    wrap.info("____new logger____", "test", 1,2,3); 
    return wrap;
}

Just came across this problem as well. Any chance that this will be implemented any time? Or has it maybe already been implemented, hidden behind some secret flag?
It would be so much more equal to console.log() which I frequently use during development and as frequently I forget to change it afterwards which leads to missing parameters in the logs...

Also just ran into this and it's extremely annoying. Is there any reason why console.log functionality emulation in this area is NOT good?

Try this

```
const logger = new winston.Logger({
transports: [
transport
]
})

logger.info.apply(logger, arguments)```

I would suggest using ES2015 template literals. For example:

logger.info(`The value is ${value}`);

Notice I used back ticks ` instead of quotes ' to wrap my string.

Was this page helpful?
0 / 5 - 0 ratings