diff --git a/.changeset/tough-masks-knock.md b/.changeset/tough-masks-knock.md new file mode 100644 index 00000000000..82f4adbd159 --- /dev/null +++ b/.changeset/tough-masks-knock.md @@ -0,0 +1,5 @@ +--- +'@clerk/nextjs': patch +--- + +Improves the debug log output, and changes the internal behavior to use multiple `console.log()` calls. This will help to avoid any platform logging limitations per call. diff --git a/packages/nextjs/jest.config.js b/packages/nextjs/jest.config.js index 6ec859b3bf8..6a91935b956 100644 --- a/packages/nextjs/jest.config.js +++ b/packages/nextjs/jest.config.js @@ -1,5 +1,8 @@ /** @type {import('ts-jest').JestConfigWithTsJest} */ module.exports = { + globals: { + PACKAGE_VERSION: '0.0.0-test', + }, displayName: 'nextjs', injectGlobals: true, roots: ['/src'], diff --git a/packages/nextjs/src/utils/debugLogger.test.ts b/packages/nextjs/src/utils/debugLogger.test.ts index 7d8cfc8347c..7cb3e72763d 100644 --- a/packages/nextjs/src/utils/debugLogger.test.ts +++ b/packages/nextjs/src/utils/debugLogger.test.ts @@ -123,9 +123,13 @@ describe('withLogger', () => { const handler = withLogger('test-logger', logger => () => { logger.enable(); logger.debug(veryLongString); + logger.debug(veryLongString); }); handler(); - expect(log.mock.calls[0][0]).toHaveLength(4096); + + for (const mockCall of log.mock.calls) { + expect(mockCall[0].length).toBeLessThanOrEqual(4096); + } // restore original console log and reset environment value process.env.VERCEL = undefined; diff --git a/packages/nextjs/src/utils/debugLogger.ts b/packages/nextjs/src/utils/debugLogger.ts index 6c8dd7d927b..d2ddab16040 100644 --- a/packages/nextjs/src/utils/debugLogger.ts +++ b/packages/nextjs/src/utils/debugLogger.ts @@ -1,5 +1,7 @@ // TODO: Replace with a more sophisticated logging solution +import nextPkg from 'next/package.json'; + import { logFormatter } from './logFormatter'; export type Log = string | Record; @@ -25,15 +27,29 @@ export const createDebugLogger = (name: string, formatter: (val: LogEntry) => st }, commit: () => { if (isEnabled) { - const log = `Clerk debug start :: ${name}\n${entries - .map(log => formatter(log)) - .map(e => `-- ${e}\n`) - .join('')}`; - if (process.env.VERCEL) { - console.log(truncate(log, 4096)); - } else { - console.log(log); + console.log(debugLogHeader(name)); + + /** + * We buffer each collected log entry so we can format them and log them all at once. + * Individual console.log calls are used to ensure we don't hit platform-specific log limits (Vercel and Netlify are 4kb). + */ + for (const log of entries) { + let output = formatter(log); + + output = output + .split('\n') + .map(l => ` ${l}`) + .join('\n'); + + // Vercel errors if the output is > 4kb, so we truncate it + if (process.env.VERCEL) { + output = truncate(output, 4096); + } + + console.log(output); } + + console.log(debugLogFooter(name)); } }, }; @@ -77,6 +93,14 @@ export const withLogger: WithLogger = (loggerFactoryOrName, handlerCtor) => { }) as ReturnType; }; +function debugLogHeader(name: string) { + return `[clerk debug start: ${name}]`; +} + +function debugLogFooter(name: string) { + return `[clerk debug end: ${name}] (@clerk/nextjs=${PACKAGE_VERSION},next=${nextPkg.version})`; +} + // ref: https://stackoverflow.com/questions/57769465/javascript-truncate-text-by-bytes-length function truncate(str: string, maxLength: number) { const encoder = new TextEncoder();