aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authornsfisis <nsfisis@gmail.com>2026-02-22 10:29:19 +0900
committernsfisis <nsfisis@gmail.com>2026-02-22 10:29:19 +0900
commit2c243a3cb814939bbe40fda1608781825ab0d77d (patch)
treecb79b397e19e23b1670ab2ef3766c0c4717637aa
parent0a8e5935e6305819bb02d8c69e2f046ff397913a (diff)
downloadphp-mozart-2c243a3cb814939bbe40fda1608781825ab0d77d.tar.gz
php-mozart-2c243a3cb814939bbe40fda1608781825ab0d77d.tar.zst
php-mozart-2c243a3cb814939bbe40fda1608781825ab0d77d.zip
feat(tracing): add performance profiling via tracing crate
Wire up the existing --profile flag with tracing-subscriber to emit span timings on stderr. Supports MOZART_LOG env var override and verbose-level-aware filtering. No subscriber is installed when --profile is off, keeping tracing macros zero-cost. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
-rw-r--r--Cargo.lock95
-rw-r--r--Cargo.toml2
-rw-r--r--crates/mozart-autoload/Cargo.toml1
-rw-r--r--crates/mozart-core/Cargo.toml1
-rw-r--r--crates/mozart-registry/Cargo.toml1
-rw-r--r--crates/mozart/Cargo.toml2
-rw-r--r--crates/mozart/src/commands.rs41
-rw-r--r--crates/mozart/src/main.rs36
8 files changed, 179 insertions, 0 deletions
diff --git a/Cargo.lock b/Cargo.lock
index 5e7b497..9051a53 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -933,6 +933,12 @@ dependencies = [
]
[[package]]
+name = "lazy_static"
+version = "1.5.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe"
+
+[[package]]
name = "libc"
version = "0.2.181"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -984,6 +990,15 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "112b39cec0b298b6c1999fee3e31427f74f676e4cb9879ed1a121b43661a4154"
[[package]]
+name = "matchers"
+version = "0.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d1525a2a28c7f4fa0fc98bb91ae755d1e2d1505079e05539e35bc876b5d65ae9"
+dependencies = [
+ "regex-automata",
+]
+
+[[package]]
name = "md5"
version = "0.7.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -1044,6 +1059,8 @@ dependencies = [
"serde_json",
"sha1",
"tempfile",
+ "tracing",
+ "tracing-subscriber",
]
[[package]]
@@ -1072,6 +1089,7 @@ dependencies = [
"serde",
"serde_json",
"tempfile",
+ "tracing",
]
[[package]]
@@ -1089,6 +1107,7 @@ dependencies = [
"serde",
"serde_json",
"tempfile",
+ "tracing",
]
[[package]]
@@ -1110,6 +1129,7 @@ dependencies = [
"tar",
"tempfile",
"tokio",
+ "tracing",
"zip",
]
@@ -1120,6 +1140,15 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "61807f77802ff30975e01f4f071c8ba10c022052f98b3294119f3e615d13e5be"
[[package]]
+name = "nu-ansi-term"
+version = "0.50.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7957b9740744892f114936ab4a57b3f487491bbeafaf8083688b16841a4240e5"
+dependencies = [
+ "windows-sys 0.61.2",
+]
+
+[[package]]
name = "num-traits"
version = "0.2.19"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -1691,6 +1720,15 @@ dependencies = [
]
[[package]]
+name = "sharded-slab"
+version = "0.1.7"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f40ca3c46823713e0d4209592e8d6e826aa57e928f09752619fc696c499637f6"
+dependencies = [
+ "lazy_static",
+]
+
+[[package]]
name = "shell-words"
version = "1.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -1880,6 +1918,15 @@ dependencies = [
]
[[package]]
+name = "thread_local"
+version = "1.1.9"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f60246a4944f24f6e018aa17cdeffb7818b76356965d03b07d6a9886e8962185"
+dependencies = [
+ "cfg-if",
+]
+
+[[package]]
name = "tinystr"
version = "0.8.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -2007,16 +2054,58 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "63e71662fa4b2a2c3a26f570f037eb95bb1f85397f3cd8076caed2f026a6d100"
dependencies = [
"pin-project-lite",
+ "tracing-attributes",
"tracing-core",
]
[[package]]
+name = "tracing-attributes"
+version = "0.1.31"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7490cfa5ec963746568740651ac6781f701c9c5ea257c58e057f3ba8cf69e8da"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn",
+]
+
+[[package]]
name = "tracing-core"
version = "0.1.36"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "db97caf9d906fbde555dd62fa95ddba9eecfd14cb388e4f491a66d74cd5fb79a"
dependencies = [
"once_cell",
+ "valuable",
+]
+
+[[package]]
+name = "tracing-log"
+version = "0.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ee855f1f400bd0e5c02d150ae5de3840039a3f54b025156404e34c23c03f47c3"
+dependencies = [
+ "log",
+ "once_cell",
+ "tracing-core",
+]
+
+[[package]]
+name = "tracing-subscriber"
+version = "0.3.22"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "2f30143827ddab0d256fd843b7a66d164e9f271cfa0dde49142c5ca0ca291f1e"
+dependencies = [
+ "matchers",
+ "nu-ansi-term",
+ "once_cell",
+ "regex-automata",
+ "sharded-slab",
+ "smallvec",
+ "thread_local",
+ "tracing",
+ "tracing-core",
+ "tracing-log",
]
[[package]]
@@ -2074,6 +2163,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821"
[[package]]
+name = "valuable"
+version = "0.1.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ba73ea9cf16a25df0c8caa16c51acb937d5712a8429db78a3ee29d5dcacd3a65"
+
+[[package]]
name = "version-ranges"
version = "0.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
diff --git a/Cargo.toml b/Cargo.toml
index 8d93856..9d0691a 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -31,6 +31,8 @@ sha1 = "0.10"
tar = "0.4"
tempfile = "3.25.0"
tokio = { version = "1.49.0", features = ["full"] }
+tracing = "0.1"
+tracing-subscriber = { version = "0.3", features = ["env-filter", "fmt"] }
zip = { version = "2", default-features = false, features = ["deflate"] }
assert_cmd = "2"
predicates = "3"
diff --git a/crates/mozart-autoload/Cargo.toml b/crates/mozart-autoload/Cargo.toml
index 6aba8ab..84ec08a 100644
--- a/crates/mozart-autoload/Cargo.toml
+++ b/crates/mozart-autoload/Cargo.toml
@@ -11,6 +11,7 @@ md5.workspace = true
regex.workspace = true
serde.workspace = true
serde_json.workspace = true
+tracing.workspace = true
[dev-dependencies]
tempfile.workspace = true
diff --git a/crates/mozart-core/Cargo.toml b/crates/mozart-core/Cargo.toml
index 25210be..85a5c9f 100644
--- a/crates/mozart-core/Cargo.toml
+++ b/crates/mozart-core/Cargo.toml
@@ -10,6 +10,7 @@ dialoguer.workspace = true
regex.workspace = true
serde.workspace = true
serde_json.workspace = true
+tracing.workspace = true
[dev-dependencies]
tempfile.workspace = true
diff --git a/crates/mozart-registry/Cargo.toml b/crates/mozart-registry/Cargo.toml
index 964e0a1..a048f91 100644
--- a/crates/mozart-registry/Cargo.toml
+++ b/crates/mozart-registry/Cargo.toml
@@ -19,4 +19,5 @@ sha1.workspace = true
tar.workspace = true
tempfile.workspace = true
tokio.workspace = true
+tracing.workspace = true
zip.workspace = true
diff --git a/crates/mozart/Cargo.toml b/crates/mozart/Cargo.toml
index 8a803fa..ec35e24 100644
--- a/crates/mozart/Cargo.toml
+++ b/crates/mozart/Cargo.toml
@@ -20,6 +20,8 @@ serde.workspace = true
serde_json.workspace = true
sha1.workspace = true
tempfile.workspace = true
+tracing.workspace = true
+tracing-subscriber.workspace = true
[dev-dependencies]
assert_cmd.workspace = true
diff --git a/crates/mozart/src/commands.rs b/crates/mozart/src/commands.rs
index a745b3a..7b94f4d 100644
--- a/crates/mozart/src/commands.rs
+++ b/crates/mozart/src/commands.rs
@@ -197,6 +197,47 @@ pub enum Commands {
Validate(validate::ValidateArgs),
}
+impl Commands {
+ pub fn name(&self) -> &'static str {
+ match self {
+ Commands::About(_) => "about",
+ Commands::Archive(_) => "archive",
+ Commands::Audit(_) => "audit",
+ Commands::Browse(_) => "browse",
+ Commands::Bump(_) => "bump",
+ Commands::CheckPlatformReqs(_) => "check-platform-reqs",
+ Commands::ClearCache(_) => "clear-cache",
+ Commands::Completion(_) => "completion",
+ Commands::Config(_) => "config",
+ Commands::CreateProject(_) => "create-project",
+ Commands::Depends(_) => "depends",
+ Commands::Diagnose(_) => "diagnose",
+ Commands::DumpAutoload(_) => "dump-autoload",
+ Commands::Exec(_) => "exec",
+ Commands::Fund(_) => "fund",
+ Commands::Global(_) => "global",
+ Commands::Init(_) => "init",
+ Commands::Install(_) => "install",
+ Commands::Licenses(_) => "licenses",
+ Commands::Outdated(_) => "outdated",
+ Commands::Prohibits(_) => "prohibits",
+ Commands::Reinstall(_) => "reinstall",
+ Commands::Remove(_) => "remove",
+ Commands::Repository(_) => "repository",
+ Commands::Require(_) => "require",
+ Commands::RunScript(_) => "run-script",
+ Commands::Search(_) => "search",
+ Commands::SelfUpdate(_) => "self-update",
+ Commands::Show(_) => "show",
+ Commands::Status(_) => "status",
+ Commands::Suggests(_) => "suggests",
+ Commands::Update(_) => "update",
+ Commands::Validate(_) => "validate",
+ }
+ }
+}
+
+#[tracing::instrument(skip(cli), fields(command = cli.command.name()))]
pub fn execute(cli: &Cli) -> anyhow::Result<()> {
let console = mozart_core::console::Console::new(
cli.verbose,
diff --git a/crates/mozart/src/main.rs b/crates/mozart/src/main.rs
index 59ad392..ebe84e5 100644
--- a/crates/mozart/src/main.rs
+++ b/crates/mozart/src/main.rs
@@ -1,9 +1,45 @@
use clap::Parser;
use mozart::commands;
use mozart_core::exit_code;
+use tracing_subscriber::{fmt, prelude::*, EnvFilter};
+
+fn init_tracing(profile: bool, verbose: u8, quiet: bool) {
+ // MOZART_LOG environment variable takes highest priority.
+ if let Ok(env_filter) = EnvFilter::try_from_env("MOZART_LOG") {
+ tracing_subscriber::registry()
+ .with(fmt::layer().with_writer(std::io::stderr))
+ .with(env_filter)
+ .init();
+ return;
+ }
+
+ if profile {
+ let filter = match verbose {
+ 0 => "mozart=info",
+ 1 | 2 => "mozart=debug",
+ _ => "mozart=trace",
+ };
+ tracing_subscriber::registry()
+ .with(
+ fmt::layer()
+ .with_writer(std::io::stderr)
+ .with_timer(fmt::time::uptime())
+ .with_span_events(fmt::format::FmtSpan::CLOSE),
+ )
+ .with(EnvFilter::new(filter))
+ .init();
+ } else if verbose >= 3 && !quiet {
+ tracing_subscriber::registry()
+ .with(fmt::layer().with_writer(std::io::stderr).with_target(false))
+ .with(EnvFilter::new("mozart=debug"))
+ .init();
+ }
+ // Otherwise: no subscriber installed → tracing macros are effectively zero-cost no-ops.
+}
fn main() {
let cli = commands::Cli::parse();
+ init_tracing(cli.profile, cli.verbose, cli.quiet);
match commands::execute(&cli) {
Ok(()) => {}
Err(e) => {