winston 2 was better

Created on 3 Jun 2019  路  4Comments  路  Source: winstonjs/winston

convention > configuration 99.999999^ % of the time. i really hate winston 3, logging non strings in console is now hell. i can't get the format the way i want it. sucks

feelsbadman.jpg

Most helpful comment

The rewrite made adding such a feature incredibly trivial which illustrates the value in that endeavor.

i think this is a blind spot for you because you are a maintainer of the project, and thus you are more familiar with how to do exactly what you want. i wouldn't call this trivial:

logger.add(new winston.transports.Console({
    format: format.combine(
        format.errors({ stack: true }),
        format.splat(),
        format.colorize(),
        format.timestamp(),
        format.printf(({level,message,timestamp,...restProps})=>{
            var retval = `${timestamp} ${level}: `;
            if(message) {
                retval += message;
            }else{
                retval += util.inspect(JSON.parse(restProps[Symbol.for('message')]));
            }
            return retval;
        })
    )
}));

i think more apt descriptors would be "complicated" and "wasteful", but its what i had to do to match the important aspects of console.log, which i would consider to be:

  • string interpolating messages
  • inspecting values (object, array, etc)

All 4 comments

Speaking in terminology that winston@3 defined you are asking for a better "default format". The rewrite made adding such a feature incredibly trivial which illustrates the value in that endeavor.

Please be constructive with your feedback in the future. For example: in this case go look at logform and make a suggestion as to features (i.e. what exact formats) you feel would be most important to have in a default format that we could add to winston@3.

The rewrite made adding such a feature incredibly trivial which illustrates the value in that endeavor.

i think this is a blind spot for you because you are a maintainer of the project, and thus you are more familiar with how to do exactly what you want. i wouldn't call this trivial:

logger.add(new winston.transports.Console({
    format: format.combine(
        format.errors({ stack: true }),
        format.splat(),
        format.colorize(),
        format.timestamp(),
        format.printf(({level,message,timestamp,...restProps})=>{
            var retval = `${timestamp} ${level}: `;
            if(message) {
                retval += message;
            }else{
                retval += util.inspect(JSON.parse(restProps[Symbol.for('message')]));
            }
            return retval;
        })
    )
}));

i think more apt descriptors would be "complicated" and "wasteful", but its what i had to do to match the important aspects of console.log, which i would consider to be:

  • string interpolating messages
  • inspecting values (object, array, etc)

In my opinion, there's no issue with convention-over-configurtion approach at all, in any case library API and documentation are the most important.

I came from Java world and found formatters configuration indeed confusing.. :(

You'd better to separate all formatters into two groups:

  • functions that modifies fields of log entry object (aka TransformableInfo)
  • functions used to build final string from that object

And to write createLogger api so that one always can add arbitrary number of modifying functions and set only single final formatter (json/printf etc) globally and/or per transport.

How library users should understand why this config will produce "undefined" on each logger.log call?

const logger = createLogger({
    format: format.timestamp(),
    transports: [
        new transports.Console()
    ]
});

PS I'd also add check to transformers to never print "undefined"..

Having a clear delineation between formatters that mutate the incoming object/message, and formatters that simply output a string is very important and a weakness of the current configuration. In winston@2 we had two conventions for this, formatting and rewriting. While these aren't the clearest names, it certainly made it simpler to understand that sometimes I'm adjusting the message I'm going to log and other times I'm actually constructing the output that I will write to the logging facility.

For a given application, I may want to always add a timestamp and redact some fields, but for a given logging facility, I will need different output written.

For example, in .combine(), it doesn't work to put printf() anywhere but the very end because it doesn't output anything useful for a different formatter to consume. That makes is a different class of 'formatter' and probably should be bound to the logger in a different way.

Was this page helpful?
0 / 5 - 0 ratings