bithavoc / express-winston

express.js middleware for winstonjs
https://www.npmjs.com/package/express-winston
MIT License
797 stars 186 forks source link

SPDY > Express.JS > Next.JS don't show path details #283

Open khteh opened 1 year ago

khteh commented 1 year ago

I am using SPDY server for HTTP/2 for my React.JS / Next.JS application. Unfortunately this solution needs to use Express.JS and therefore this is what I do to have request logging:

    // Init the Next app:
    const app = next({ dev, dir: __dirname })
    const handle = app.getRequestHandler()
const options = {
  key: fs.readFileSync('server.key'),
  cert: fs.readFileSync('server.crt'),
}
app.prepare().then(() => {
    const expressApp = express()
      expressApp.use(expressWinston.logger({
        level: 'info',
        meta: true, // optional: control whether you want to log the meta data about the request (default to true)
        msg: "HTTP {{req.method}} {{req.url}}", // optional: customize the default logging message. E.g. "{{res.statusCode}} {{req.method}} {{res.responseTime}}ms {{req.url}}"
        expressFormat: true, // Use the default Express/morgan request formatting. Enabling this will override any msg if true. Will only output colors with colorize set to true
        colorize: false, // Color the text and status code, using the Express/morgan color palette (text: gray, status: default green, 3XX cyan, 4XX yellow, 5XX red).
        ignoreRoute: function (req, res) { 
          return req?.url?.includes('health') || req?.url?.includes('robots.txt')
        }, // optional: allows to skip some log messages based on request and/or response
        format: winston.format.combine(
          winston.format.splat(),
          winston.format.timestamp(),
          winston.format.json()
        ),
        defaultMeta: { service: 'user-service' },
        requestWhitelist: ['headers', 'query'],  //these are not included in the standard StackDriver httpRequest
        responseWhitelist: ['body'], // this populates the `res.body` so we can get the response size (not required)        
        dynamicMeta:  (req, res) => {
          const httpRequest = {}
          if (req) {
            httpRequest.requestMethod = req.method
            httpRequest.requestUrl = `${req.protocol}://${req.get('host')}${req.originalUrl}`
            httpRequest.protocol = `HTTP/${req.httpVersion}`
            httpRequest.IP = req.ip // this includes both ipv6 and ipv4 addresses separated by ':'
            //httpRequest.remoteIp = req.ip.indexOf(':') >= 0 ? req.ip.substring(req.ip.lastIndexOf(':') + 1) : req.ip   // just ipv4
            httpRequest.requestSize = req.socket.bytesRead
            httpRequest.userAgent = req.get('User-Agent')
            httpRequest.referrer = req.get('Referrer')
            httpRequest.user = req.user ? req.user.username : null
            httpRequest.role = req.user ? req.user.role : null
          }
          if (res) {
            httpRequest.status = res.statusCode
            httpRequest.latency = {
              seconds: Math.floor(res.responseTime / 1000),
              nanos: ( res.responseTime % 1000 ) * 1000000
            }
            if (res.body) {
              if (typeof res.body === 'object') {
                httpRequest.responseSize = JSON.stringify(res.body).length
              } else if (typeof res.body === 'string') {
                httpRequest.responseSize = res.body.length
              }
            }
          }
          return httpRequest
        },        
        transports: [
            new DailyRotateFile({
                level: 'info',
                filename: '/var/log/myapp/log-%DATE%',
                handleExceptions: true,
                format: winston.format.combine(
                    winston.format.splat(),
                    winston.format.timestamp(),
                    winston.format.json()
                  ),            
                maxSize: '100m',
                maxFiles: '14d'
            }),
            new winston.transports.Console({
                level: 'debug',
                handleExceptions: true,
                format: winston.format.combine(
                    winston.format.colorize(),
                    winston.format.simple()
                  )
            })
        ],
        exitOnError: false,
      }))
  expressApp.all('*', (req, res) => {
    return handle(req, res)
  })
   const server = spdy.createServer(options, expressApp)
  server.listen(port, (err) => {
    if (err) {
      apm.captureError(err)
      console.error('Failed to start server', err)
      process.exit(1)
    } else {
      console.log(`HTTP/2 server listening on port: ${port}`)
    }
  })
})

However, I get most of the request paths showing up as "Others" in my EFK logging dashboard: image

How can I get the detailed request paths going into the Next.JS application?