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: