pino-http icon indicating copy to clipboard operation
pino-http copied to clipboard

this.log should be replaced with req.log

Open GuskiS opened this issue 4 years ago • 10 comments

I tried this:

req.log = req.log.child({ something: true });

but it didn't work. After digging into sourcecode I found this: https://github.com/pinojs/pino-http/blob/a7c82bc2d82847ba6692b20de1e7d2b65c4a1624/logger.js#L44

this refers to res object, so that would mean res.log. After changing that code, something appeared in my output.

This is very misleading since all examples suggest to use req.log. Also there isn't res.log doesn't have typescript type definition.

GuskiS avatar Nov 26 '19 12:11 GuskiS

Can you add an example to reproduce the problem you are facing?

mcollina avatar Nov 27 '19 09:11 mcollina

I have something like this:

router.use(pinoHttp(), (req, res, next) => {
  req.log = req.log.child({  something: true })
  next();
});

router.get("/example", (req, res) => {
  req.log.info("some message")
  res.json({ ok: true });
});

req.log.info("some message") will have something: true in its output, however, the request completed will not have it, because that one relays on res.

I hope this make it more clear.

GuskiS avatar Nov 27 '19 12:11 GuskiS

if you're always binding the same value, this isn't a good pattern, instead do

const logger = require('pino')().child({ something: true })
const pinoHttp = require('pino-http')({ logger })
router.use(pinoHttp)

davidmarkclements avatar Nov 27 '19 16:11 davidmarkclements

for injecting values on a per request basis use the serializers

davidmarkclements avatar Nov 27 '19 16:11 davidmarkclements

Value changes per request. I tried setting that value on req object, however that didn't show up in serializers from req.raw.

GuskiS avatar Nov 27 '19 20:11 GuskiS

I think it would be helpful to have a full example of what you are trying to do.

mcollina avatar Nov 29 '19 08:11 mcollina

https://github.com/pinojs/pino-http/issues/74#issuecomment-559063426 This is almost the same thing as I'm doing, but here goes: 1.

app.use(pinoHttp());

const originalRouteMiddleware = (originalRoute) => (req, res, next) => {
  req.log = req.log.child({ originalRoute });
  next();
});
app.use(pinoHttp({
  serializers: {
    req(req) {
      req.originalRoute = req.raw.originalRoute;
      return req;
    },
  },
}));

const originalRouteMiddleware = (originalRoute) => (req, res, next) => {
  req.originalRoute = originalRoute;
  next();
});

Route:

router.get("/user/:userId", originalRouteMiddleware("/user/:userId"), (req, res) => {
  req.log.info("some message");
  res.json({ ok: true });
});

So the issues I'm facing:

  1. I would need to do req.log = res.log = res.log.child({ originalRoute }); to make it work, which is misleading and not obvious if you don't take a look at sourcecode. Also, as suggested, not a good pattern.
  2. In this case req.raw doesn't contain my originalRoute, not sure why tho. Maybe .child creates copy of original object? :thinking:

GuskiS avatar Nov 29 '19 08:11 GuskiS

May I get a full example that I can run? Ideally without express (or maybe this is express-only).

mcollina avatar Nov 29 '19 09:11 mcollina

Here it is: https://github.com/GuskiS/pino-express-failure

GuskiS avatar Nov 29 '19 09:11 GuskiS

In this case req.raw doesn't contain my originalRoute, not sure why tho. Maybe .child creates copy of original object?

Child serializes the request object once at the time the log line is created. In order for that property to show up, you'd have to add it in a middleware before the pino-http one.

I do not think there is any other way than req.log = res.log = res.log.child({ originalRoute }); tbh. You could potentially disable autoLogging and log after you have set that value.

mcollina avatar Nov 29 '19 16:11 mcollina