diff --git a/crates/turborepo-lib/src/cli/mod.rs b/crates/turborepo-lib/src/cli/mod.rs index 621f413907a81..4ac5c01dd92a7 100644 --- a/crates/turborepo-lib/src/cli/mod.rs +++ b/crates/turborepo-lib/src/cli/mod.rs @@ -1298,17 +1298,24 @@ pub async fn run( #[allow(unused_variables)] logger: &TurboSubscriber, color_config: ColorConfig, ) -> Result { - // TODO: remove mutability from this function - let mut cli_args = Args::new(env::args_os().collect()); + let _cli_run_span = tracing::info_span!("cli_run").entered(); + + let mut cli_args = { + let _span = tracing::info_span!("cli_arg_parsing").entered(); + Args::new(env::args_os().collect()) + }; let version = get_version(); - // Build a single HTTP client to share across telemetry, API, and cache - // operations. This avoids redundant TLS initialization (~150ms savings). - let http_client = APIClient::build_http_client(None) - .expect("Failed to create HTTP client: TLS initialization failed"); + let http_client = { + let _span = tracing::info_span!("http_client_init").entered(); + APIClient::build_http_client(None) + .expect("Failed to create HTTP client: TLS initialization failed") + }; - // track telemetry handle to close at the end of the run - let telemetry_handle = initialize_telemetry_client(&http_client, color_config, version); + let telemetry_handle = { + let _span = tracing::info_span!("telemetry_init").entered(); + initialize_telemetry_client(&http_client, color_config, version) + }; if should_print_version() { eprintln!("{}", GREY.apply_to(format!("• turbo {}", get_version()))); @@ -1592,7 +1599,10 @@ pub async fn run( let event = CommandEventBuilder::new("run").with_parent(&root_telemetry); event.track_call(); - let base = CommandBase::new(cli_args.clone(), repo_root, version, color_config)?; + let base = { + let _span = tracing::info_span!("command_base_new").entered(); + CommandBase::new(cli_args.clone(), repo_root, version, color_config)? + }; event.track_ui_mode(base.opts.run_opts.ui_mode); if execution_args.tasks.is_empty() { diff --git a/crates/turborepo-lib/src/commands/run.rs b/crates/turborepo-lib/src/commands/run.rs index 6a73162debcb0..cd823e11a36e1 100644 --- a/crates/turborepo-lib/src/commands/run.rs +++ b/crates/turborepo-lib/src/commands/run.rs @@ -16,7 +16,10 @@ pub async fn run( let signal = get_signal()?; let handler = SignalHandler::new(signal); - let run_builder = RunBuilder::new(base, Some(http_client))?; + let run_builder = { + let _span = tracing::info_span!("run_builder_new").entered(); + RunBuilder::new(base, Some(http_client))? + }; let run_fut = async { let (analytics_sender, analytics_handle) = run_builder.start_analytics(); @@ -27,7 +30,10 @@ pub async fn run( .await?, ); - let (sender, handle) = run.start_ui()?.unzip(); + let (sender, handle) = { + let _span = tracing::info_span!("start_ui").entered(); + run.start_ui()?.unzip() + }; let result = run.run(sender.clone(), false).await; diff --git a/crates/turborepo-lib/src/run/builder.rs b/crates/turborepo-lib/src/run/builder.rs index f39e217a96657..6a58569b0889b 100644 --- a/crates/turborepo-lib/src/run/builder.rs +++ b/crates/turborepo-lib/src/run/builder.rs @@ -6,7 +6,7 @@ use std::{ }; use chrono::Local; -use tracing::debug; +use tracing::{debug, Instrument}; use turbopath::{AbsoluteSystemPath, AbsoluteSystemPathBuf}; use turborepo_analytics::{start_analytics, AnalyticsHandle, AnalyticsSender}; use turborepo_api_client::{APIAuth, APIClient}; @@ -253,7 +253,10 @@ impl RunBuilder { .with_single_package_mode(self.opts.run_opts.single_package) .with_allow_no_package_manager(self.opts.repo_opts.allow_no_package_manager); - let graph = builder.build().await; + let graph = builder + .build() + .instrument(tracing::info_span!("pkg_dep_graph_build")) + .await; match graph { Ok(graph) => graph, @@ -285,19 +288,25 @@ impl RunBuilder { } }; - let (scm, repo_index) = scm_task.await.expect("detecting scm panicked"); + let (scm, repo_index) = scm_task + .instrument(tracing::info_span!("scm_task_await")) + .await + .expect("detecting scm panicked"); let repo_index = Arc::new(repo_index); debug!( "RunBuilder creating AsyncCache with cache_dir={}, repo_root={}", self.opts.cache_opts.cache_dir, self.repo_root ); - let async_cache = AsyncCache::new( - &self.opts.cache_opts, - &self.repo_root, - self.api_client.clone(), - self.api_auth.clone(), - self.analytics_sender.take(), - )?; + let async_cache = { + let _span = tracing::info_span!("async_cache_new").entered(); + AsyncCache::new( + &self.opts.cache_opts, + &self.repo_root, + self.api_client.clone(), + self.api_auth.clone(), + self.analytics_sender.take(), + )? + }; // restore config from task access trace if it's enabled let task_access = TaskAccess::new(self.repo_root.clone(), async_cache.clone(), &scm); @@ -348,18 +357,25 @@ impl RunBuilder { pkg_dep_graph.validate()?; - let filtered_pkgs = Self::calculate_filtered_packages( - &self.repo_root, - &self.opts, - &pkg_dep_graph, - &scm, - &root_turbo_json, - )?; + let filtered_pkgs = { + let _span = tracing::info_span!("calculate_filtered_packages").entered(); + Self::calculate_filtered_packages( + &self.repo_root, + &self.opts, + &pkg_dep_graph, + &scm, + &root_turbo_json, + )? + }; - let env_at_execution_start = EnvironmentVariableMap::infer(); - // Pre-warm the turbo.json cache: read and parse all package turbo.json - // files in parallel before the engine builder needs them sequentially. - turbo_json_loader.preload_all(); + let env_at_execution_start = { + let _span = tracing::info_span!("env_infer").entered(); + EnvironmentVariableMap::infer() + }; + { + let _span = tracing::info_span!("turbo_json_preload").entered(); + turbo_json_loader.preload_all(); + } let mut engine = self.build_engine( &pkg_dep_graph, diff --git a/crates/turborepo-lib/src/run/mod.rs b/crates/turborepo-lib/src/run/mod.rs index 517abf2209663..bc52c17466aed 100644 --- a/crates/turborepo-lib/src/run/mod.rs +++ b/crates/turborepo-lib/src/run/mod.rs @@ -612,6 +612,7 @@ impl Run { let mut internal_deps_result = None; let mut global_file_result = None; + let _hash_scope_span = tracing::info_span!("hash_scope").entered(); rayon::scope(|s| { s.spawn(|_| { let _span = tracing::info_span!("calculate_file_hashes_task").entered(); @@ -655,6 +656,8 @@ impl Run { }); }); + drop(_hash_scope_span); + let package_inputs_hashes = file_hash_result.expect("file hash task did not complete")?; let root_internal_dependencies_hash = internal_deps_result.expect("internal deps task did not complete")?; diff --git a/crates/turborepo-lib/src/shim.rs b/crates/turborepo-lib/src/shim.rs index 12dbad2effb82..d70fe487b0a85 100644 --- a/crates/turborepo-lib/src/shim.rs +++ b/crates/turborepo-lib/src/shim.rs @@ -150,6 +150,8 @@ pub fn run() -> Result { let _ = subscriber.enable_chrome_tracing(file_path, include_args); } + let _span = tracing::info_span!("shim_run").entered(); + // Create the runtime with all implementations let runtime = ShimRuntime::new( TurboCliRunner::new(&subscriber), diff --git a/crates/turborepo-shim/src/run.rs b/crates/turborepo-shim/src/run.rs index f5d18056f980f..6fbb635459652 100644 --- a/crates/turborepo-shim/src/run.rs +++ b/crates/turborepo-shim/src/run.rs @@ -233,15 +233,22 @@ where // it to execute local turbo. We simply use it to set the `--single-package` // and `--cwd` flags. if is_turbo_binary_path_set() { - let repo_state = match RepoState::infer(&args.cwd) { - Ok(state) => state, - Err(e) => return ShimResult::ShimError(e.into()), + let repo_state = { + let _span = tracing::info_span!("repo_inference").entered(); + match RepoState::infer(&args.cwd) { + Ok(state) => state, + Err(e) => return ShimResult::ShimError(e.into()), + } }; debug!("Repository Root: {}", repo_state.root); return run_cli(runtime, Some(repo_state), color_config); } - match RepoState::infer(&args.cwd) { + let repo_result = { + let _span = tracing::info_span!("repo_inference").entered(); + RepoState::infer(&args.cwd) + }; + match repo_result { Ok(repo_state) => { debug!("Repository Root: {}", repo_state.root); run_correct_turbo(runtime, repo_state, args, color_config)