From cc66c59d8d5c6abcff6a7fa280d24ba827b5501e Mon Sep 17 00:00:00 2001 From: Sebastian Silbermann Date: Mon, 29 Jul 2024 18:16:54 +0200 Subject: [PATCH] Add telemetry for React Compiler usage (#68079) --- packages/next/src/telemetry/events/version.ts | 15 ++++ .../telemetry/next.config.reactCompiler-base | 5 ++ .../next.config.reactCompiler-options | 8 ++ .../integration/telemetry/test/config.test.js | 84 +++++++++++++++++++ 4 files changed, 112 insertions(+) create mode 100644 test/integration/telemetry/next.config.reactCompiler-base create mode 100644 test/integration/telemetry/next.config.reactCompiler-options diff --git a/packages/next/src/telemetry/events/version.ts b/packages/next/src/telemetry/events/version.ts index f70cf3db48cd1..de98c5f944662 100644 --- a/packages/next/src/telemetry/events/version.ts +++ b/packages/next/src/telemetry/events/version.ts @@ -35,6 +35,9 @@ type EventCliSessionStarted = { pagesDir: boolean | null staticStaleTime: number | null dynamicStaleTime: number | null + reactCompiler: boolean + reactCompilerCompilationMode: string | null + reactCompilerPanicThreshold: string | null } function hasBabelConfig(dir: string): boolean { @@ -83,6 +86,9 @@ export function eventCliSession( | 'reactStrictMode' | 'staticStaleTime' | 'dynamicStaleTime' + | 'reactCompiler' + | 'reactCompilerCompilationMode' + | 'reactCompilerPanicThreshold' > ): { eventName: string; payload: EventCliSessionStarted }[] { // This should be an invariant, if it fails our build tooling is broken. @@ -126,6 +132,15 @@ export function eventCliSession( pagesDir: event.pagesDir, staticStaleTime: nextConfig.experimental.staleTimes?.static ?? null, dynamicStaleTime: nextConfig.experimental.staleTimes?.dynamic ?? null, + reactCompiler: Boolean(nextConfig.experimental.reactCompiler), + reactCompilerCompilationMode: + typeof nextConfig.experimental.reactCompiler !== 'boolean' + ? nextConfig.experimental.reactCompiler?.compilationMode ?? null + : null, + reactCompilerPanicThreshold: + typeof nextConfig.experimental.reactCompiler !== 'boolean' + ? nextConfig.experimental.reactCompiler?.panicThreshold ?? null + : null, } return [{ eventName: EVENT_VERSION, payload }] } diff --git a/test/integration/telemetry/next.config.reactCompiler-base b/test/integration/telemetry/next.config.reactCompiler-base new file mode 100644 index 0000000000000..7c1a8401f5eab --- /dev/null +++ b/test/integration/telemetry/next.config.reactCompiler-base @@ -0,0 +1,5 @@ +module.exports = { + experimental: { + reactCompiler: true + } +} \ No newline at end of file diff --git a/test/integration/telemetry/next.config.reactCompiler-options b/test/integration/telemetry/next.config.reactCompiler-options new file mode 100644 index 0000000000000..44a98c4b8cfa7 --- /dev/null +++ b/test/integration/telemetry/next.config.reactCompiler-options @@ -0,0 +1,8 @@ +module.exports = { + experimental: { + reactCompiler: { + compilationMode: 'annotation', + panicThreshold: 'CRITICAL_ERRORS' + } + } +} \ No newline at end of file diff --git a/test/integration/telemetry/test/config.test.js b/test/integration/telemetry/test/config.test.js index 80aec6f56bf08..a3f7f9eccf730 100644 --- a/test/integration/telemetry/test/config.test.js +++ b/test/integration/telemetry/test/config.test.js @@ -571,6 +571,90 @@ describe('config telemetry', () => { invocationCount: 1, }) }) + + it('emits telemetry for default React Compiler options', async () => { + const { stderr } = await nextBuild(appDir, [], { + stderr: true, + env: { NEXT_TELEMETRY_DEBUG: 1 }, + }) + + try { + const event = /NEXT_CLI_SESSION_STARTED[\s\S]+?{([\s\S]+?)}/ + .exec(stderr) + .pop() + + expect(event).toMatch(/"reactCompiler": false/) + expect(event).toMatch(/"reactCompilerCompilationMode": null/) + expect(event).toMatch(/"reactCompilerPanicThreshold": null/) + } catch (err) { + require('console').error('failing stderr', stderr, err) + throw err + } + }) + + it('emits telemetry for enabled React Compiler', async () => { + await fs.rename( + path.join(appDir, 'next.config.reactCompiler-base'), + path.join(appDir, 'next.config.js') + ) + + let stderr + try { + const app = await nextBuild(appDir, [], { + stderr: true, + env: { NEXT_TELEMETRY_DEBUG: 1 }, + }) + stderr = app.stderr + const event = /NEXT_CLI_SESSION_STARTED[\s\S]+?{([\s\S]+?)}/ + .exec(stderr) + .pop() + + expect(event).toMatch(/"reactCompiler": true/) + expect(event).toMatch(/"reactCompilerCompilationMode": null/) + expect(event).toMatch(/"reactCompilerPanicThreshold": null/) + } catch (err) { + require('console').error('failing stderr', stderr, err) + throw err + } finally { + await fs.rename( + path.join(appDir, 'next.config.js'), + path.join(appDir, 'next.config.reactCompiler-base') + ) + } + }) + + it('emits telemetry for configured React Compiler options', async () => { + await fs.rename( + path.join(appDir, 'next.config.reactCompiler-options'), + path.join(appDir, 'next.config.js') + ) + + let stderr + try { + const app = await nextBuild(appDir, [], { + stderr: true, + env: { NEXT_TELEMETRY_DEBUG: 1 }, + }) + stderr = app.stderr + const event = /NEXT_CLI_SESSION_STARTED[\s\S]+?{([\s\S]+?)}/ + .exec(stderr) + .pop() + + expect(event).toMatch(/"reactCompiler": true/) + expect(event).toMatch(/"reactCompilerCompilationMode": "annotation"/) + expect(event).toMatch( + /"reactCompilerPanicThreshold": "CRITICAL_ERRORS"/ + ) + } catch (err) { + require('console').error('failing stderr', stderr, err) + throw err + } finally { + await fs.rename( + path.join(appDir, 'next.config.js'), + path.join(appDir, 'next.config.reactCompiler-options') + ) + } + }) } ) })