sainsburys-tech / next-logger

JSON logging patcher for Next.js
MIT License
144 stars 14 forks source link

Next 13 compatibility #22

Closed arichard-info closed 6 months ago

arichard-info commented 9 months ago

Hello !

It seems that next-logger is not working properly since Next 13.4.20 : https://github.com/vercel/next.js/pull/54713 I may propose a PR when I have the time, but for now let's describe the issue.

The Next log format has changed, for example :

Now : image

Before : image

Since next-logger relies on logs prefixes, we now have log format errors :

Initial log :

âš  See more info here: https://nextjs.org/docs/messages/invalid-next-config
✓ Ready in 1626ms

Formatted log with next-logger :

{"level":40,"time":1701102955852,"pid":35967,"hostname":"myhostname","name":"console","msg":" \u001b[33m\u001b[1mâš \u001b[22m\u001b[39m See more info here: https://nextjs.org/docs/messages/invalid-next-config"}
{"level":30,"time":1701102956877,"pid":35967,"hostname":"myhostname","name":"console","msg":" \u001b[32m\u001b[1m✓\u001b[22m\u001b[39m Ready in 1637ms"}

The new log format is going to be complicated to format. Now there are multi-lines and special characters 😕

rslowinski commented 6 months ago

any updates on this topic? :)

atkinchris commented 6 months ago

I've been digging into this with Next 14, and I'm hitting a blocker. The chalk prefixes shouldn't be an issue, as once patched, we don't call those internal methods at all.

However, patching is my blocker at this stage. An as const declaration was added to Next's log prefixes.

Currently, we patch the prefix methods with basic assignment:

Object.keys(nextLogger.prefixes).forEach(method => {
  nextLogger[method] = getPinoMethod(method)
})

With as const, these methods now only have getters - and silently refuse the assignment, so patching does nothing. Neither Object.assign nor Object.defineProperty can work around this either, by design.

Object.assign(nextLogger, { [method]: getPinoMethod(method) })
// TypeError: Cannot set property XXX of #<Object> which has only a getter

Object.defineProperty(nextLogger, method, { value: getPinoMethod(method) })
// TypeError: Cannot redefine property: XXX

I'm investigating if I can redefine the entire object on the module export, to keep the reference but not the existing properties.


I can redefine the entire exports object within the require cache, which allows the properties themselves to be redefined.

const cachePath = require.resolve('next/dist/build/output/log')
const cacheObject = require.cache[cachePath]
cacheObject.exports = { ...cacheObject.exports }
atkinchris commented 6 months ago

Please can you try the new beta version, to see if this works for you?

npm i next-logger@4.0.0-beta.1
atkinchris commented 6 months ago

Version 4.0.0 has been published, bringing Next 14 support!