#Logging Payload API Requests

1 messages · Page 1 of 1 (latest)

sand slate
#

Very cool to see Payload using Pino logger, but was curious to know if it's possible to log all Payload's api requests? Or would this have to be configured in separately in Express? I currently have loggerOptions set to info in server.ts - and see startup messages via Pino, but I'm not seeing any api requests.

jade obsidian
#

@sand slate Good question - I wonder if Pino's config can be extended to catch the missing requests?

#

I know the default level is "info", how about debug or trace?

#

If that exposes the payload requests, you could check the level of those and add a custom logging level

#

That's my best guess, I'll keep my eye open for other possibilities, though another community member or a team member may have more insight

sand slate
#

Hi! @jade obsidian I've tried debug and trace but those don't add request logging.

#

For context - we use CloudWatch Logs Insights extensively with all of our deployed APIs (typically with custom 'topic' properties in log messages), and if we were to deploy Payload CMS to AWS we'd ideally like to do the same.

jade obsidian
#

Hmm

#

@sand slate Did you say you tried to add a middleware to express, prior to Payload?

jade obsidian
#
const requestLoggerMiddleware = ({ logger }) => (req, res, next) => {
  console.log('Should run on every request')
  next();
};
#

app.use(requestLoggerMiddleware)

sand slate
jade obsidian
#

Hopefully that exposes all the requests!

#

Let us know

sand slate
#

@jade obsidian close....

#
const requestLoggerMiddleware =
  ({ logger }) =>
  (req, res, next) => {
    logger.info(`request: ${req.method} ${req.url}`)
    next()
  }

const start = async () => {
  // Initialize Payload
  await payload.init({
    secret: process.env.PAYLOAD_SECRET,
    mongoURL: process.env.MONGODB_URI,
    express: app,
    loggerOptions: {
      level: 'debug',
    },
    onInit: async () => {
      payload.logger.info(`Payload Admin URL: ${payload.getAdminURL()}`)
    },
  })

  app.use(requestLoggerMiddleware({ logger: payload.logger }))

  // Add your own express routes here

  app.listen(process.env.PORT, async () => {
    payload.logger.info(`Server listening on port ${process.env.PORT}`)
  })
}

start()
jade obsidian
#

Ooooo

sand slate
#

I can pass in a configured instance of payload - but for any route that matches the payload runtime, the middleware will not log the request

#

for example if I pass an API request to /api/foo (not a payload collection) then I will get a middleware logged request - since express is handling this route now

#

So I suspect Payload needs to decide if it's going to log its own handled requests.

jade obsidian
#

Hmmm

#

@orchid raft Any ideas on how they could get some extended logging?

orchid raft
#

@sand slate @muted glade Using custom middleware is the right approach here but I think you need to define it at the router level, like this:

import express from "express";
import payload from "payload";

const app = express();

const start = async () => {
  // Initialize Payload
  await payload.init({
    secret: process.env.PAYLOAD_SECRET,
    mongoURL: process.env.MONGODB_URI,
    express: app,
    loggerOptions: {
      level: 'debug',
    },
    onInit: async () => {
      payload.logger.info(`Payload Admin URL: ${payload.getAdminURL()}`)
    },
  })

  const router = express.Router();

  router.use(requestLoggerMiddleware({ logger: payload.logger });

  app.listen(process.env.PORT, async () => {
    payload.logger.info(`Server listening on port ${process.env.PORT}`)
  })
}

start()
sand slate
#

@orchid raft @jade obsidian <plays sad trombone> - sorry Jacob but this didn't work either. Highly likely I'm doing something wrong here, as we're not very familiar with Express (we're a Fastify shop).

mystic crescent
#

It appears this is an undocumented feature but might work for you - You could try sending in some logging middleware into preMiddleware in your Payload config via the express options

#

postMiddleware is available as well

sand slate
#

@mystic crescent thanks a bunch - will give it a try. Was also going to guess that Payload's middleware / handlers are not calling next() - and so we might try registering our own logger middleware before payload.

mystic crescent
sand slate
#

Understood. Thanks @mystic crescent @orchid raft @jade obsidian - as per Elliot's suggestions, this works...
Middleware:

const requestLoggerMiddleware = (req, res, next) => {
  req.payload.logger.info(`request: ${req.method} ${req.url}`)
  next()
}

And then in payload.config.ts

 express: {
    preMiddleware: [requestLoggerMiddleware],
  },
mystic crescent
#

Also heads up on json logging w/ Pino (especially if querying in cloudwatch). If you want to have more json properties, you'll want to log an object w/ msg property for the message. Multiple parameters didn't appear to pass to json properly despite the TS type saying so.

req.payload.logger.info({ msg: 'my message', method: req.method, url: req.url})

sand slate
#

@mystic crescent - thanks - and yup - that's how we're doing it in production with a topic top level property, followed by the payload / params.

#

and so we would probably do something like this ( although it's late here, so ¯_(ツ)_/¯)
req.payload.logger.info({ payload_request: { method: req.method, url: req.url } })

mystic crescent
polar tapir