Next.js: Add support to monitoring performances

Created on 4 Jun 2019  路  9Comments  路  Source: vercel/next.js

Feature request

Is your feature request related to a problem?

I'm migrating an application to Next.js and one requirement that we have is to be able to monitor the application (using Prometheus for example).
Here are 2 examples of metrics that could make sense:

  • rendering time: how long does the app takes to render (once data is ready). Useful to track the evolution of the complexity of the tree.
  • data-fetching time: how long do we wait for the data. Useful to track how our dependencies behave. This would basically measure the time spent in the _app.js getInitialProps().

Describe the solution you'd like

I think this would require the developer to use the custom server approach: we could provide a few new options on the const app = next({ dev }) call.

Options proposal:

  • onRenderStart or beforeRender
  • onRenderEnd or afterRender
  • onGetInitialPropsStart or beforeGetInitialProps
  • onGetInitialPropsEnd or afterGetInitialProps

All the options above would be callbacks called at the right time. They could also be grouped inside a single timings option maybe.

One thing to consider as well is that a timer started in a start/before callback needs to be stopped in the end/after one. This means we need to have a context shared between those...

One other way that could enable this context could be to return the end function:

next({
  onRender: () => {
    const endTimer = timer.start()
    return () => endTimer()
  }
})

Describe alternatives you've considered

I don't have other ideas in my mind so far as I'm still beginning with using Next.js, I'm probably lacking a wider vision.

Most helpful comment

The specific PR is client-only but there's more coming.

All 9 comments

Gonna add my comment here as well then:

One idea could be to add a Server-Timing header/trailer. Not sure if that would be enough for your use case.

This won't need as much configuration. It could be parsed by middleware and exposed to prometheus that way.

@Janpot I'm not sure to understand how this would work, could you detail a bit more?

The headers would be sent to the browser?

With Prometheus, you need to able to increment a counter/metric that is stored on the server because you need to expose them on a specific port to be scraped by Prometheus.

I didn't test it yet, but AFAIK, this should be possible:

const { createServer } = require('http')
const next = require('next')

const dev = process.env.NODE_ENV !== 'production'
const app = next({ dev })
const handle = app.getRequestHandler()

app.prepare().then(() => {
  createServer((req, res) => {
    res.on('finish', () => {
      const timing = res.getHeader('Server-Timing')
      // parse header and log with prometheus or anything else
    })

    handle(req, res)
  }).listen(3000, err => {
    if (err) throw err
    console.log('> Ready on http://localhost:3000')
  })
})

Yes this makes sense. I understand now :)

However, it means that it will be Next's responsibility to measure the time and not the wrapping app. It can also be an issue with Prometheus because the developer needs to start and stop a counter/histogram by herself.

Yes, one could definitely imagine more powerful hooks. I'm just putting it on the table as a low config alternative, that uses already available standards.

Closing this in favor of #8069 and other work Houssein has been doing.

@timneutkens does this PR only enable monitoring on client side or these metrics are available on the server as well?

The specific PR is client-only but there's more coming.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

timneutkens picture timneutkens  路  3Comments

ghost picture ghost  路  3Comments

jesselee34 picture jesselee34  路  3Comments

irrigator picture irrigator  路  3Comments

formula349 picture formula349  路  3Comments