Winston: Colorize doesn't work on transports.Console

Created on 10 Oct 2017  路  12Comments  路  Source: winstonjs/winston

I created a shared logger successfully, but it prints all white, even though I've set colorize to true. And as a test, My Label successfully prints out in red.

// Logging with Winston
const { red } = require('colors')
const os = require('os')
const fs = require('fs')
const path = require('path')
const config = require('../data/config/config')
const winston = require('winston')
const { createLogger, format, transports } = winston
const { combine, timestamp, label, printf } = format
const tsFormat = () => (new Date()).toLocaleTimeString()
const myFormat = printf(info => {
  return `${info.timestamp} [${info.label}] ${info.level}: ${info.message}`
})

const logDir = path.resolve(os.homedir(), '.curator-server')

if (!fs.existsSync(logDir)) {
  fs.mkdirSync(logDir)
}

const logger = createLogger({
  format: combine(
    label({ label: red('My Label') }),
    timestamp(),
    myFormat
  ),
  transports: [
    new transports.Console({ level: config.logLevel, humanReadableUnhandledException: true, colorize: true }),
    new transports.File({ filename: path.resolve(logDir, 'info.log'), level: 'info' }),
    new transports.File({ filename: path.resolve(logDir, 'error.log'), level: 'error' })
  ]
})

module.exports = logger

docs good first issue help wanted

Most helpful comment

Right, so I've looked more into this. You can't "format.colorize()" after you use "myFormat" since the modifications colorize does would not be seen in the final message.

You would need to add colorize and myFormat to the format specifiers of each transport instead of for the whole logger.

const winston = require('winston')
const { createLogger, format, transports } = winston
const { combine, timestamp, label, printf, colorize } = format

const logger = createLogger({
  format: combine(
    label({ label: red('My Label') }),
    timestamp()
  ),
  transports: [
    new transports.Console({
      format: combine(
        colorize(),
        myFormat
      ),
      level: 'silly' }),
    new transports.File({ format: myFormat, filename: path.resolve(logDir, 'info.log'), level: 'info' }),
    new transports.File({ format: myFormat, filename: path.resolve(logDir, 'error.log'), level: 'error' })
  ]
})

All 12 comments

Try moving the colorize to a format property inside your Console constructor:
new transports.Console({ level: config.logLevel, format: colorize() })

I have the same problem and your suggestion doesn't work for me, unfortunately. For
new transports.Console({ level: config.logLevel, format: colorize() })
I get

colorize is not defined

I also tried
winston.format.colorize()
which doesn't throw any error, but doesn't work either.
BTW: Calling colorize() is not the way this is described in the docs.

Right, so I've looked more into this. You can't "format.colorize()" after you use "myFormat" since the modifications colorize does would not be seen in the final message.

You would need to add colorize and myFormat to the format specifiers of each transport instead of for the whole logger.

const winston = require('winston')
const { createLogger, format, transports } = winston
const { combine, timestamp, label, printf, colorize } = format

const logger = createLogger({
  format: combine(
    label({ label: red('My Label') }),
    timestamp()
  ),
  transports: [
    new transports.Console({
      format: combine(
        colorize(),
        myFormat
      ),
      level: 'silly' }),
    new transports.File({ format: myFormat, filename: path.resolve(logDir, 'info.log'), level: 'info' }),
    new transports.File({ format: myFormat, filename: path.resolve(logDir, 'error.log'), level: 'error' })
  ]
})

Thanks! Works! Just for info I prefer to do the 'require' that way:

const winston = require('winston');
const myConsoleFormat = winston.format.printf(function (info) {
  return `${info.level}: ${info.message} (${moment().format('YYYY-MM-DDTHH:mm:ss.SSSZZ')})`;
});
var myLogger = winston.createLogger({
    transports: [
      new winston.transports.Console({ format: winston.format.combine( winston.format.colorize(), myConsoleFormat)  })
    ],
    level: 'silly',
  });

In my opinion, it's more clear what comes from Winston and what not.

I was just using the style used in the original example code here.

This worked for me.

Additionally, before reading this answer, I came across the Transport docs here, but it specifies formatter instead of format. I had unsuccessfully tried close to what was suggested, using formatter instead and was unsuccessful. Wouldn't have known to do format if not for the answer from @mempf.

Note - This is my first time ever using any logging library, so maybe it's an issue of assumed knowledge?

Winston is in the middle of transitioning to version 3.0.0 which has breaking API changes when it comes to formatting.

Ah! Completely understandable. Thanks for your help, @mempf.

If you're like me you might have ended up here because it is not obvious that order is important. It must be:

format: combine(colorize(), myFormat)

and NOT:

format: combine(myFormat, colorize())

which simply silently fails to color anything.

This is still broken in the 2.4.1 release version. Are there any plans to fix this or do we have to wait until version 3 finally gets released before Winston supports colors?

Updating docs/transports.md is one of the last things to do before the release of [email protected] on May 29th. If you're looking for a way to get involved or help with the project a PR for those docs would be outstanding!

Right, so I've looked more into this. You can't "format.colorize()" after you use "myFormat" since the modifications colorize does would not be seen in the final message.

You would need to add colorize and myFormat to the format specifiers of each transport instead of for the whole logger.

const winston = require('winston')
const { createLogger, format, transports } = winston
const { combine, timestamp, label, printf, colorize } = format

const logger = createLogger({
  format: combine(
    label({ label: red('My Label') }),
    timestamp()
  ),
  transports: [
    new transports.Console({
      format: combine(
        colorize(),
        myFormat
      ),
      level: 'silly' }),
    new transports.File({ format: myFormat, filename: path.resolve(logDir, 'info.log'), level: 'info' }),
    new transports.File({ format: myFormat, filename: path.resolve(logDir, 'error.log'), level: 'error' })
  ]
})

The problem is that on each transport it will run format function. So, if I log like this logger.silly('hello') - myFormat will run 3 times.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

JaehyunLee-B2LiNK picture JaehyunLee-B2LiNK  路  3Comments

sinai-doron picture sinai-doron  路  3Comments

Infinitay picture Infinitay  路  3Comments

jlank picture jlank  路  4Comments

anks333 picture anks333  路  3Comments