22

I am developing a Node.js application, using babel-cli as an ES6 transpiler and I am using Winston 3.0 as my logging service.

Question:

I want the whole output of the messages from the winston logger to appear in color, not just the label and the message, but the timestamp as well. I know that, in Winston 2.x that was in some ways possible (don't know how though).

I have already tried different NPM Packages like winston color and winston-console-formatter, but they don't seem to work.

I have defined my logger as follows:

    import winston from 'winston'
    
    let alignColorsAndTime = winston.format.combine(
        winston.format.colorize({
            all:true
        }),
        winston.format.label({
            label:'[LOGGER]'
        }),
        winston.format.timestamp({
            format:"YY-MM-DD HH:MM:SS"
        }),
        winston.format.printf(
            info => ` ${info.label}  ${info.timestamp}  ${info.level} : ${info.message}`
        )
    );
    
    export const logger = winston.createLogger({
        level: "debug",
        transports: [
            new (winston.transports.Console)({
                format: alignColorsAndTime
            })
        ],
    });

Still the output looks something like this: Click for Image

While I'd rather have it look styled like this: Click for Image

trashtatur
  • 381
  • 1
  • 3
  • 12

7 Answers7

24

Try with the code below. It will combine both formatting. It works for me.


let alignColorsAndTime = winston.format.combine(
    winston.format.colorize({
        all:true
    }),
    winston.format.label({
        label:'[LOGGER]'
    }),
    winston.format.timestamp({
        format:"YY-MM-DD HH:mm:ss"
    }),
    winston.format.printf(
        info => ` ${info.label}  ${info.timestamp}  ${info.level} : ${info.message}`
    )
);
    
export const logger = winston.createLogger({
    level: "debug",
    transports: [
        new (winston.transports.Console)({
            format: winston.format.combine(winston.format.colorize(), alignColorsAndTime)
        })
    ],
});

Note the padding has to handle the colour. Ex:


const padding= info.level.length <= 7?7:17;  //padding differently if it has colour.
${info.level.padEnd(padding,' ')}

Tested with:

"winston": "^3.1.0"
Martin P.
  • 654
  • 8
  • 18
5

simply use addColors() method

const { createLogger, format, transports, addColors } = require('winston');
const { combine, colorize, label, timestamp, json, prettyPrint, printf } = format;
require('winston-mongodb');

let myCustomFormat = format.combine(
  colorize({ all: true }),
  label({ label: '[LOGGER]' }),
  timestamp({ format: 'YY-MM-DD HH:MM:SS' }),
  printf(
    (info) =>
      ` ${info.label} ${info.timestamp}  ${info.level} : ${info.message}`
  )
);

addColors({
  info: 'bold blue', // fontStyle color
  warn: 'italic yellow',
  error: 'bold red',
  debug: 'green',
});

const logger = createLogger({
  level: 'info',
  transports: [new transports.Console({ format: combine(myCustomFormat) })],
});

This worked for me for customizing colors and font style.

Possible options from the doc are below.

Font styles: bold, dim, italic, underline, inverse, hidden, strikethrough.

Font foreground colors: black, red, green, yellow, blue, magenta, cyan, white, gray, grey.

Background colors: blackBG, redBG, greenBG, yellowBG, blueBG magentaBG, cyanBG, whiteBG
scytale
  • 12,346
  • 3
  • 32
  • 46
Firoj Siddiki
  • 1,649
  • 1
  • 20
  • 22
  • Generally, answers are much more helpful if they include an explanation of what the code is intended to do, and why that solves the problem without introducing others. – DCCoder Oct 02 '20 at 16:36
  • 3
    Basically the question is expected a solution in which output should look like this https://i.stack.imgur.com/BqXev.png this image (BOLD and COLORFUL). And according to documentation, winston provides a method called addColors( ) which has not been mentioned in other given solutions. This is the only new changes i have made to the existing solution here. Hope this helps. – Firoj Siddiki Oct 02 '20 at 18:45
  • This works for me, but I had to add a `format.colorize({all: true})` to the transport as @mehedihasan code. – Carlos Tomas Jan 04 '22 at 17:26
3

another idea:

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

const colorizer = winston.format.colorize();

const logger = winston.createLogger({
    levels: {
        error: 0,
        warn: 1,
        info: 2,
        debug: 4
    },
    format: combine(
        winston.format.timestamp(),
        winston.format.simple(),
        winston.format.printf(msg =>
            colorizer.colorize(msg.level, `${msg.timestamp} - ${msg.level}: ${msg.message}`)
        )
),
    transports: [
        new (winston.transports.Console)({
            // format: winston.format.combine(winston.format.colorize(), alignColorsAndTime),
            prettyPrint: true,
            colorize: true,
            timestamp: true,

        }),
    ],
});
Naomi Messing
  • 638
  • 6
  • 18
3

from this post https://github.com/winstonjs/winston/issues/1388

const colorizer = winston.format.colorize();

const logger = winston.createLogger({
  level: 'debug',
  format: combine(
    winston.format.timestamp(),
    winston.format.simple(),
    winston.format.printf(msg => 
      colorizer.colorize(msg.level, `${msg.timestamp} - ${msg.level}: ${msg.message}`)
    )
  ),
  transports: [
    new transports.Console(),
  ]

});
kheengz
  • 840
  • 12
  • 10
3

This will colorize and display the times in readable format. And store all the errors into a file as well!

import { createLogger, format, transports } from 'winston'

const loggerFormat = format.combine(
  format.timestamp(),
  format.printf((info) => {
    return `${info.timestamp} - [${info.level.toUpperCase().padEnd(7)}]: ${
      info.message
    }`
  }),
  format.colorize({
    all: true,
  })
)

const logger = createLogger({
  format: loggerFormat,
  transports: [
    new transports.Console({ level: 'silly' }),
    new transports.File({ filename: 'error.log', level: 'error' }),
  ],
})

export default logger
Mehedi Hasan
  • 61
  • 1
  • 6
2

The order of format.colorize({ all: true }) matters. Put it after the printf in your combine method like this and it works for me:

const alignColorsAndTime = format.combine(
  format.label({
      label:'[LOGGER]'
  }),
  format.timestamp({
      format:"YYYY-MM-DD HH:mm:ss"
  }),
  format.printf(
      info => ` ${info.label}  ${info.timestamp}  ${info.level} : ${info.message}`
  ),
  format.colorize({
    all:true
  })
);

Using winston 3.7.2.

0

winston 3.10.0

logger definition in a separate module (.mjs)

If you put your colorize format in the transport, it works as the original question requested and colorizes the whole line.

Setting colorize at the transport level also makes a lot of sense because you probably don't want colour escape sequences written to any log files you may subsequently create (even if you start with console only)

import { format, createLogger, transports } from  'winston';
import  'winston-daily-rotate-file';
const { combine, timestamp, printf, } = format;

var logger;

const transConsole = new transports.Console({
    json: true, 
    timestamp: true,
    format: format.colorize({
                all:true
              }),
});

const transDRFile = new transports.DailyRotateFile({
  filename: 'log/my-app-%DATE%.log',
  datePattern: 'YYYY-MM-DD',
  zippedArchive: false,
  maxSize: '20m',
  maxFiles: '14d',
  colorize: false,
});

transDRFile.on('rotate', function(oldFilename, newFilename) {
    logger.info(`Log rotated from ${oldFilename} to ${newFilename}`, {category: "Logger"});
  });

const customFormat = printf(({ level, message, category, subCategory, timestamp }) => {
  return `${level
          } [${(category===undefined)?'':category
          }] [${(subCategory===undefined)?'':subCategory
          }] ${timestamp}: ${message}`;
});

const getLogger = () => {
    if (logger === undefined) {
        logger = createLogger({
            level: "debug",
            format: combine(
              timestamp({
                format: "YYYYMMDD_HH:mm:ss",
              }),
              customFormat,
              ),
              transports: [
              transConsole, transDRFile,
            ],
          });
          logger.warn(`logger created`, {category: "Logger"});         
          logger.info(`logger created`, {category: "Logger"});         
          logger.verbose(`logger created`, {category: "Logger"});         
          logger.debug(`logger created`, {category: "Logger"});         
    }
    return logger;
}

export { getLogger };

enter image description here