Repository: vercel/next.js
Pull request: feat(turbopack) Added sending events to log how long writing entrypoints to disk takes.

## Add logging for entrypoint writing in Turbopack build

### What?
This PR adds diagnostic event logging for the entrypoint writing process during Turbopack builds, showing when the process starts and finishes along with timing information.

### Why?
This allows us to better track if we are bound by file IO in terms of performance as the number of cores increases.

### How?
- Added diagnostic events at the start and end of the `project_write_all_entrypoints_to_disk` function
- Added an `Event` severity level to the `Severity` enum to match the `Log` types in Next.js
- Implemented event subscription in the build process to capture and display these events

Changed files:
filename: crates/napi/src/next_api/project.rs
patch: @@ -831,11 +831,14 @@ pub async fn project_write_all_entrypoints_to_disk(
     app_dir_only: bool,
 ) -> napi::Result<TurbopackResult<NapiEntrypoints>> {
     let turbo_tasks = project.turbo_tasks.clone();
+    let compilation_event_sender = turbo_tasks.clone();
+
     let (entrypoints, issues, diags) = turbo_tasks
         .run_once(async move {
             let entrypoints_with_issues_op =
                 get_all_written_entrypoints_with_issues_operation(project.container, app_dir_only);
 
+            // Read and compile the files
             let EntrypointsWithIssues {
                 entrypoints,
                 issues,
@@ -844,8 +847,26 @@ pub async fn project_write_all_entrypoints_to_disk(
             } = &*entrypoints_with_issues_op
                 .read_strongly_consistent()
                 .await?;
+
+            // Start timing writing the files to disk
+            let now = Instant::now();
+            compilation_event_sender.send_compilation_event(Arc::new(DiagnosticEvent::new(
+                "Starting to write all entrypoints to disk...".to_owned(),
+                Severity::Event,
+            )));
+
+            // Write the files to disk
             effects.apply().await?;
 
+            // Send a compilation event to indicate that the files have been written to disk
+            compilation_event_sender.send_compilation_event(Arc::new(DiagnosticEvent::new(
+                format!(
+                    "Finished writing all entrypoints to disk in {:?}",
+                    now.elapsed()
+                ),
+                Severity::Event,
+            )));
+
             Ok((entrypoints.clone(), issues.clone(), diagnostics.clone()))
         })
         .await

filename: packages/next/src/build/turbopack-build/impl.ts
patch: @@ -19,6 +19,7 @@ import loadConfig from '../../server/config'
 import { hasCustomExportOutput } from '../../export/utils'
 import { Telemetry } from '../../telemetry/storage'
 import { setGlobal } from '../../trace'
+import * as Log from '../output/log'
 
 export async function turbopackBuild(): Promise<{
   duration: number
@@ -87,6 +88,14 @@ export async function turbopackBuild(): Promise<{
     }
   )
   try {
+    ;(async function logCompilationEvents() {
+      for await (const event of project.compilationEventsSubscribe()) {
+        if (event.severity === 'EVENT') {
+          Log.event(event.message)
+        }
+      }
+    })()
+
     // Write an empty file in a known location to signal this was built with Turbopack
     await fs.writeFile(path.join(distDir, 'turbopack'), '')
 

filename: turbopack/crates/turbo-tasks/src/message_queue.rs
patch: @@ -17,7 +17,7 @@ type CompilationEventChannel = mpsc::Sender<Arc<dyn CompilationEvent>>;
 
 pub struct CompilationEventQueue {
     event_history: ArcMx<VecDeque<Arc<dyn CompilationEvent>>>,
-    subscribers: DashMap<String, Vec<CompilationEventChannel>>,
+    subscribers: Arc<DashMap<String, Vec<CompilationEventChannel>>>,
 }
 
 impl Default for CompilationEventQueue {
@@ -27,7 +27,7 @@ impl Default for CompilationEventQueue {
 
         Self {
             event_history: Arc::new(Mutex::new(VecDeque::with_capacity(MAX_QUEUE_SIZE))),
-            subscribers,
+            subscribers: Arc::new(subscribers),
         }
     }
 }
@@ -125,6 +125,7 @@ pub enum Severity {
     Warning,
     Error,
     Fatal,
+    Event,
 }
 
 impl Display for Severity {
@@ -135,6 +136,7 @@ impl Display for Severity {
             Severity::Warning => write!(f, "WARNING"),
             Severity::Error => write!(f, "ERROR"),
             Severity::Fatal => write!(f, "FATAL"),
+            Severity::Event => write!(f, "EVENT"),
         }
     }
 }