Skip to content

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

@khteh

Description

@khteh

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?

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions