Winston: Attempt to write logs with no transports

2020-07-06 03:49发布

问题:

I'm trying to set up an access log and an error log for my express server using Winston, but I seem to be doing something wrong.

Here is my attempt at a config file:

const winston = require('winston'),
    fs = require('fs');

const tsFormat = () => (new Date()).toLocaleTimeString();
winston.loggers.add('errorLog', {
        file: {
                filename: '<path>/errors.log', //<path> is replaced by the 
                timestamp: tsFormat,           //absolute path of the log
                level: 'info'
        }

});
winston.loggers.add('accessLog', {
        file: {
                filename: '<path>/access.log', //same as before
                timestamp: tsFormat,
                level: 'info'
        }
});

And this is how I'm including it in my other files:

var winston = require('winston'),
    accessLog = winston.loggers.get('accessLog'),
    errorLog = winston.loggers.get('errorLog');

This seems to me like it follows the documentation (https://github.com/winstonjs/winston/tree/2.4.0#working-with-multiple-loggers-in-winston) but I'm getting this error when I try to log to it:

[winston] Attempt to write logs with no transports {"message":"pls","level":"info"}
[winston] Attempt to write logs with no transports {"message":"Bad request: undefined","level":"warn"}

Any help would be greatly appreciated, I've been pretty stumped for a couple days now.

回答1:

I'd try something like this, put all the logger related stuff into a module logger.js:

logger.js

    var winston = require('winston');
    var path = require('path');

    // Set this to whatever, by default the path of the script.
    var logPath = __dirname;

    const tsFormat = () => (new Date().toISOString());

  const errorLog = winston.createLogger({
  transports: [
    new winston.transports.File({
      filename: path.join(logPath, 'errors.log'),
      timestamp: tsFormat,
      level: 'info'})
  ]
});

const accessLog = winston.createLogger({
  transports: [
    new winston.transports.File({
      filename: path.join(logPath, 'access.log'),
      timestamp: tsFormat,
      level: 'info'})
  ]
});


    module.exports = {
        errorLog: errorLog,
        accessLog: accessLog
    };

and then test in index.js:

index.js

var logger = require('./logger');

logger.errorLog.info('Test error log');
logger.accessLog.info('Test access log');

You should see log lines like:

errors.log:

{"level":"info","message":"Test access log","timestamp":"2018-03-14T07:51:11.185Z"}

access.log:

{"level":"info","message":"Test error log","timestamp":"2018-03-14T07:51:11.182Z"}

EDIT

On Winston last version, new (winston.Logger) has been replaced by winston.createLogger (https://github.com/bithavoc/express-winston/issues/175)



回答2:

1 Logger + console logging for development purpose:

logger.js

var logPath = '';
var log_level = '';

const log = winston.createLogger({
  level: log_level,
  format: winston.format.json(),
  transports: [
    new winston.transports.File({
      filename: path.join(logPath, 'access.log'),
      timestamp: tsFormat,
      level: log_level
    }),
    new winston.transports.File({
      filename: path.join(logPath, 'error.log'),
      timestamp: tsFormat,
      level: 'error'
    }),
  ]
});

if (process.env.NODE_ENV !== 'production') {
  log.add(new winston.transports.Console({
    format: winston.format.simple()
  }));
}

module.exports = {
  log: log
};

app.js

const logger = require('./logger');

logger.log.info("starting application..");


回答3:

Since you were creating the winston variable in the original code as const winston it wasn't able to add transports and other options in the following lines. The proposed solution moves the similar code into a module but assigns winston variable into var winston.