Carol.Kar
Carol.Kar

Reputation: 5355

Adding winston to express app

I would like to use winston in my express app.

I have configured winston like the following:

const path = require('path')
const winston = require('winston')

module.exports = () => {
  process.on('uncaughtException', err => winston.error('uncaught exception: ', err))
  process.on('unhandledRejection', (reason, p) => winston.error('unhandled rejection: ', reason, p))

  winston.emitErrs = true
  winston.exitOnError = false
  winston.level = process.env.NODE_ENV === 'production' ? 'info' : 'debug'
  winston.remove(winston.transports.Console)

  winston.add(winston.transports.Console, {
    level: process.env.NODE_ENV === 'production' ? 'info' : 'debug',
    handleExceptions: true,
    prettyPrint: true,
    humanReadableUnhandledException: false,
    json: false,
    colorize: true,
    timestamp: new Date(),
  })

  winston.add(winston.transports.File, {
    level: 'info',
    filename: path.join(__dirname, '../logs/app.log'),
    handleExceptions: true,
    humanReadableUnhandledException: true,
    json: false,
    maxsize: 10242880, // ~10MB
    maxFiles: 3,
    colorize: false,
    timestamp: new Date(),
  })
}

In my express app I want to add winston as a middleware to log the console:

const express = require('express')
const winston = require("./config/winston")
const app = express()

//initialize winston
app.use(winston)

app.get('/', function (req, res) {
  res.send('Hello World!')
})

//Start Server
const port = process.env.APP_PORT || 3000
const host = process.env.APP_HOST || "localhost"

app.listen(port, function() {
  console.log("Listening on " + host + ":" + port)
})

My problem is that my app does not load and gives me back the following error message:

Error: Transport already attached: file, assign a different name
    at exports.Logger.Logger.add (C:\Users\user\Desktop\Coding Projects\learning_npm_winston\node_modules\winston\lib\winst
on\logger.js:487:11)
    at Object.winston.(anonymous function) [as add] (C:\Users\user\Desktop\Coding Projects\learning_npm_winston\node_module
s\winston\lib\winston.js:86:34)
    at module.exports (C:\Users\user\Desktop\Coding Projects\learning_npm_winston\src\t02-loggingToFolder.js:23:11)
    at Layer.handle [as handle_request] (C:\Users\user\Desktop\Coding Projects\learning_npm_winston\node_modules\express\li
b\router\layer.js:95:5)
    at trim_prefix (C:\Users\user\Desktop\Coding Projects\learning_npm_winston\node_modules\express\lib\router\index.js:317
:13)
    at C:\Users\user\Desktop\Coding Projects\learning_npm_winston\node_modules\express\lib\router\index.js:284:7
    at Function.process_params (C:\Users\user\Desktop\Coding Projects\learning_npm_winston\node_modules\express\lib\router\
index.js:335:12)
    at next (C:\Users\user\Desktop\Coding Projects\learning_npm_winston\node_modules\express\lib\router\index.js:275:10)
    at expressInit (C:\Users\user\Desktop\Coding Projects\learning_npm_winston\node_modules\express\lib\middleware\init.js:
40:5)
    at Layer.handle [as handle_request] (C:\Users\user\Desktop\Coding Projects\learning_npm_winston\node_modules\express\li
b\router\layer.js:95:5)

Any suggestion what I am doing wrong?

I appreciate your replies!

Upvotes: 6

Views: 15318

Answers (2)

Alok
Alok

Reputation: 10554

Another simple setup of winston with express is like

const winston = require('winston');
const express = require('express')

const app = express()
const port = 3000

var options = {
  file: {
    level: 'debug',
    filename: `mylogs-${Date.now()}.log`,
    handleExceptions: true,
    format: winston.format.combine(
      winston.format.splat(),
      winston.format.timestamp(),
    ),
    maxsize: 100 * 1024 * 1024,
    maxFiles: 10,
  },
  console: {
    level: 'debug',
    handleExceptions: true,
    format: winston.format.combine(
      winston.format.splat(),
      winston.format.timestamp(),
    ),
  }
}

var logger = winston.createLogger({
  levels: winston.config.syslog.levels,
  transports: [
    new winston.transports.File(options.file),
    new winston.transports.Console(options.console)
  ],
  exitOnError: false,
})

app.get('/', (req, res) => {
  logger.info('Got get request')
  res.send('response from express')
})

app.listen(port, () => {
  // console.log(`Example app listening on port ${port}`)
  logger.info(`Example app listening on port ${port}`)
})

Upvotes: 0

robertklep
robertklep

Reputation: 203304

Your module exports a function that sets up winston. That function gets passed to Express:

app.use(winston)

So for every request, that function gets called, which means that each time the winston setup is executed, adding both the Console and the File transports.

For some reason, you're removing the Console transport first, so that doesn't trigger an error, but when the File transport is added (again, and again, etc), you'll get the error: "Transport already attached: file, assign a different name" (in other words: you already have a File transport attached to the logger, and you can only add another one if you change its name explicitly).

The main problem here is that the exported function isn't an Express middleware function, so you can't pass it to app.use() and expect it to work properly.

If your intention is to log HTTP requests with winston, you should use a proper middleware module like express-winston.

Upvotes: 7

Related Questions