What would be the recommended way to use with Hapi and specifically hapi-pino
josh803316 opened this issue · 1 comments
I read this article about adding tracing to logs and it inspired me to want to enable this inside my hapi/hapi-pino project.
I registered hapi-pino as a hapi plugin just like the docs recommend (below). I'm wondering if it would make more sense to register a separate cls-pino-logger plugin or if it would be recommended to do it somehow inside of hapi-pino? Thanks in advance for any guidance.
await server.register({
plugin: require('hapi-pino'),
options: {
prettyPrint: process.env.NODE_ENV !== 'production',
// Redact Authorization headers, see https://getpino.io/#/docs/redaction
redact: ['req.headers.authorization']
}
})
I created a plugin per the hapi plugin docs:
import { clsProxify, clsProxifyNamespace, setClsProxyValue } from 'cls-proxify'
import * as Pino from "pino";
const logger = Pino();
const loggerCls = clsProxify('clsKeyLogger', logger)
const handler = function (request, h) {
clsProxifyNamespace.bindEmitter(request);
clsProxifyNamespace.bindEmitter(request.response);
clsProxifyNamespace.run(() => {
const headerRequestID = request.headers.Traceparent
// this value will be accesible in CLS by key 'clsKeyLogger'
// it will be used as a proxy for `loggerCls`
const loggerProxy = {
info: (msg: string) => `${headerRequestID}: ${msg}`,
}
setClsProxyValue('clsKeyLogger', loggerProxy)
})
};
exports.plugin = {
name: 'cls-trace-logger',
register: function (server, options) {
server.route({ method: 'GET', path: '/test/cls', handler });
loggerCls.info('My message!');
}
};
But I get this error:
1597365833550] ERROR (55306 on ip-192-168-2-50.ec2.internal): request error
err: {
"type": "AssertionError",
"message": "can only bind real EEs",
"stack":
AssertionError [ERR_ASSERTION]: can only bind real EEs
@josh803316 AFAICS, hapi-pino has an "instance" option field. I would suggest to use it.
I have never used hapi myself, but roughly it could look like this:
import { clsProxify, clsProxifyNamespace, setClsProxyValue } from 'cls-proxify'
const logger = pino()
const loggerCls = clsProxify('clsKeyLogger', logger)
const server = Hapi.server({
port: 3000,
host: 'localhost'
})
await server.register({
name: 'cls-trace-logger',
plugin: async (server, options) => {
server.ext('onRequest', (request, h) => {
clsProxifyNamespace.bindEmitter(request.raw.req)
clsProxifyNamespace.bindEmitter(request.raw.res)
const clsCtx = clsProxifyNamespace.createContext()
clsProxifyNamespace.enter(clsCtx)
request.plugins['cls-trace-logger'] = {
context: clsCtx
}
const requestId = req.headers.Traceparent || uuidv1()
const childLoggerWithRequestID = logger.child({ requestId })
setClsProxyValue('clsKeyLogger', childLoggerWithRequestID)
return h.continue
})
server.events.on('response', () => {
const clsCtx = request.plugins['cls-trace-logger'].context
clsProxifyNamespace.exit(clsCtx)
})
}
})
await server.register({
plugin: require('hapi-pino'),
options: {
prettyPrint: process.env.NODE_ENV !== 'production',
// Redact Authorization headers, see https://getpino.io/#/docs/redaction
redact: ['req.headers.authorization'],
instance: loggerCls
}
})
So the idea is to create a child pino
logger with an embedded request ID for each request and put it into our CLS context. clsProxify
wraps the original pino
logger with a Proxy. Later on, we we use our loggerCls
, it looks up that child pino
logger with the embedded request ID in the CLS context and uses it instead. At last, we feed our wrapped logger instance to hapi-pino
.
Let me know if it helps.