diff --git a/.gitignore b/.gitignore index 1e3a6e093..3a6a0e465 100644 --- a/.gitignore +++ b/.gitignore @@ -8,3 +8,6 @@ result # Editor specific ignores .idea + +# Generated by setting `JJ_TRACE` environment variable. +jj-trace-*.json diff --git a/Cargo.lock b/Cargo.lock index 540fa31df..2c9abae8c 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1035,6 +1035,7 @@ dependencies = [ "timeago", "toml_edit", "tracing", + "tracing-chrome", "tracing-subscriber", ] @@ -2261,6 +2262,17 @@ dependencies = [ "syn 2.0.23", ] +[[package]] +name = "tracing-chrome" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "496b3cd5447f7ff527bbbf19b071ad542a000adf297d4127078b4dfdb931f41a" +dependencies = [ + "serde_json", + "tracing-core", + "tracing-subscriber", +] + [[package]] name = "tracing-core" version = "0.1.30" @@ -2268,6 +2280,18 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "24eb03ba0eab1fd845050058ce5e616558e8f8d8fca633e6b163fe25c797213a" dependencies = [ "once_cell", + "valuable", +] + +[[package]] +name = "tracing-log" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "78ddad33d2d10b1ed7eb9d1f518a5674713876e97e5bb9b7345a7984fbb4f922" +dependencies = [ + "lazy_static", + "log", + "tracing-core", ] [[package]] @@ -2281,9 +2305,11 @@ dependencies = [ "once_cell", "regex", "sharded-slab", + "smallvec", "thread_local", "tracing", "tracing-core", + "tracing-log", ] [[package]] @@ -2353,6 +2379,12 @@ version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "711b9620af191e0cdc7468a8d14e709c3dcdb115b36f838e601583af800a370a" +[[package]] +name = "valuable" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "830b7e5d4d90034032940e4ace0d9a9a057e7a45cd94e6c007832e39edb82f6d" + [[package]] name = "vcpkg" version = "0.2.15" diff --git a/Cargo.toml b/Cargo.toml index 6e797a2ba..ef25f3842 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -62,6 +62,7 @@ thiserror = "1.0.43" timeago = { version = "0.4.1", default-features = false } toml_edit = { version = "0.19.12", features = ["serde"] } tracing = "0.1.37" +tracing-chrome = "0.7.1" tracing-subscriber = { version = "0.3.17", default-features = false, features = ["std", "ansi", "env-filter", "fmt"] } [target.'cfg(unix)'.dependencies] diff --git a/src/cli_util.rs b/src/cli_util.rs index 95c784a02..d1a13e987 100644 --- a/src/cli_util.rs +++ b/src/cli_util.rs @@ -23,6 +23,7 @@ use std::process::ExitCode; use std::rc::Rc; use std::str::FromStr; use std::sync::Arc; +use std::time::SystemTime; use clap::builder::{NonEmptyStringValueParser, TypedValueParser, ValueParserFactory}; use clap::{Arg, ArgAction, ArgMatches, Command, FromArgMatches}; @@ -62,6 +63,7 @@ use jj_lib::{dag_walk, file_util, git, revset}; use once_cell::unsync::OnceCell; use thiserror::Error; use toml_edit; +use tracing_chrome::ChromeLayerBuilder; use tracing_subscriber::prelude::*; use crate::config::{ @@ -332,6 +334,20 @@ impl From for CommandError { } } +#[derive(Clone)] +struct ChromeTracingFlushGuard { + _inner: Option>, +} + +impl Debug for ChromeTracingFlushGuard { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + let Self { _inner } = self; + f.debug_struct("ChromeTracingFlushGuard") + .field("inner", &"not shown") + .finish() + } +} + /// Handle to initialize or change tracing subscription. #[derive(Clone, Debug)] pub struct TracingSubscription { @@ -339,6 +355,7 @@ pub struct TracingSubscription { tracing_subscriber::EnvFilter, tracing_subscriber::Registry, >, + _chrome_tracing_flush_guard: ChromeTracingFlushGuard, } impl TracingSubscription { @@ -349,11 +366,43 @@ impl TracingSubscription { .with_default_directive(tracing::metadata::LevelFilter::ERROR.into()) .from_env_lossy(); let (filter, reload_log_filter) = tracing_subscriber::reload::Layer::new(filter); + + let (chrome_tracing_layer, chrome_tracing_flush_guard) = match std::env::var("JJ_TRACE") { + Ok(_) => { + let filename = format!( + "jj-trace-{}.json", + SystemTime::now() + .duration_since(SystemTime::UNIX_EPOCH) + .unwrap() + .as_secs(), + ); + let include_args = std::env::var("JJ_TRACE_INCLUDE_ARGS").is_ok(); + let (layer, guard) = ChromeLayerBuilder::new() + .file(filename) + .include_args(include_args) + .build(); + ( + Some(layer), + ChromeTracingFlushGuard { + _inner: Some(Rc::new(guard)), + }, + ) + } + Err(_) => (None, ChromeTracingFlushGuard { _inner: None }), + }; + tracing_subscriber::registry() - .with(filter) - .with(tracing_subscriber::fmt::Layer::default().with_writer(std::io::stderr)) + .with( + tracing_subscriber::fmt::Layer::default() + .with_writer(std::io::stderr) + .with_filter(filter), + ) + .with(chrome_tracing_layer) .init(); - TracingSubscription { reload_log_filter } + TracingSubscription { + reload_log_filter, + _chrome_tracing_flush_guard: chrome_tracing_flush_guard, + } } pub fn enable_verbose_logging(&self) -> Result<(), CommandError> {