expressjs / compression

Node.js compression middleware
MIT License
2.77k stars 241 forks source link

Compression instrumentation (before/after compression hooks) #180

Closed nicholaswmin closed 2 years ago

nicholaswmin commented 2 years ago

We'd like to calculate the compression time and send it as a Server-Timing header back to the client. As I understand it, this middleware overloads res.send/res.json which is where the compression takes place. Obviously we can't set headers after res.send.

Is there a suggested way to do what we want, if any?

Here's some rough ideal code to better communicate what we would like to do:

app.get('/foo', (req, res) => {
  let t0 = 0, t1 = 0

  res.onBeforeCompress(() => {
    t0 = performance.now()
  })

  res.onAfterCompress(() => {
    t1 = performance.now() - t0
  })

  res.setHeader('Server-Timing', `compression;dur=${t1}`)

  res.json({ foo: 'bar' })
})
dougwilson commented 2 years ago

Hi @nicholaswmin unfortunately it is not possible to send that timing as a header, as this module will stream the compression as the response, so it will have written the headers and part of the body before completing the compression. This is because otherwise you can much more easily encounter OOM issues if the server had to buffer the entire response body in memory before writing the response.

nicholaswmin commented 2 years ago

Understood, thanks

How would you measure the compression time if you had to?

We can certainly do this implicitly by measuring Time-to-First-Byte without compression and TTFB with compression by I was wondering if there was a better way.