4

I just implemented Winston Logging and it works as expected but i came accross a few issues which i cant find answer for.

The way winston works as far as i can tell, the set log level and anything below as far as priority gets used, like on error it will also include info logs etc. Is there a way to create a specific log level lets call it HTTP or db where i only log http or db events to and they don't end up in the combined file or console ?

MisterniceGuy
  • 1,646
  • 2
  • 18
  • 41

2 Answers2

7

A better solution is to use a single logger with a format function as a "level filter" to specify which transport logs which specific level. Here is the solution (note, levelFilter could easily be extended to take an array of acceptable levels).

The key insight is that if no info object is returned from the formatter chain, nothing gets logged.

const { createLogger, format, transports } = require('winston');

const levelFilter = (level) =>
  format((info, opts) => {
     if (info.level != level) { return false; }
      return info;
  })();

const logger = createLogger({
  transports: [
    new transports.Console({
        format: format.combine(
          levelFilter("info"),
          format.json()
        )
    }),
    new transports.File({
        filename: "test.log",
        format: format.combine(
          levelFilter("error"),
          format.json()
        )
    }),
  ]
});

// ONLY is logged to test.log
logger.log({
  level: 'error',
  message: 'abcd'
});

// ONLY is logged to console
logger.log({
  level: 'info',
  message: '1234'
});
davewy
  • 1,781
  • 1
  • 16
  • 27
  • Yeah but @ MisterniceGuy also want to use separate log files for specific purposes, thats why multiple loggers, but maybe there is a way how to dynamically change a filename property – l2ysho Jul 07 '19 at 16:04
  • 1
    In my example I had a console transport and a file transport, but you could just as easily use two file transports, one that logs the error-level messages and one that logs the info-level messages. Still works with a single logger, though. – davewy Jul 07 '19 at 18:46
0

I can init a winston with a parameter, in your case filename. I use similar setup for logging separated cron tasks (I use type parameter instead filename, which is used as a prefix in log, so I can identify problems in multiple cron tasks in one log file). I hope you are familiar with ES6 syntax.

utils/winston.js

const { createLogger, transports } = require('winston');

const infoLogger = filename => createLogger({
    transports: [
        new transports.File({
            filename: 'info-' + filename,
            level: 'info'
        }),
        new transports.Console(),
    ],
        exitOnError: false
    });

const errorLogger = filename => createLogger({
    transports: [
        new transports.File({
            filename: 'error-' + filename,
            level: 'error'
        }),
        new transports.Console(),
    ],
        exitOnError: false
    });

export default filename => ({
    errorLogger: errorLogger(filename).error,
    infoLogger: infoLogger(filename).info
});

So in a your code you can import custom winston setup from utils and initialize it with a filename. Be careful, I basically export only error function from winston errorLogger(filename).error, You can modify it in way acceptable for you

main.js

import logger from './utils/winston';
const { errorLogger, infoLogger } = logger('http.log');
errorLogger('some http fail'); // destination file => error-http.log
infoLogger('some http info'); // destination file => info-http.log
l2ysho
  • 2,542
  • 1
  • 20
  • 41
  • That's what i have currently but if i say error it will also log anything below error to that file which includes info etc. I am trying to create a file which does not log anything besides for example my db query's – MisterniceGuy Jul 05 '19 at 20:03
  • @MisterniceGuy I think we dont understand each other, I made some changes to make it more clear – l2ysho Jul 05 '19 at 20:19
  • yes the new code makes your approach more clear, ultimately you create 2 different instances of the logger. This might work but not sure it is the best approach – MisterniceGuy Jul 06 '19 at 17:26
  • @MisterniceGuy yes its a bit weird approach, maybe you can try another logger package, because as I see it, winston's way of error logging is kind of tech standard so it is probably optimal way. If you find something interesting let me know – l2ysho Jul 06 '19 at 18:47