Skip to content

Commit 8184d41

Browse files
authored
Add tracing setup (#108)
1 parent a9499e1 commit 8184d41

File tree

5 files changed

+233
-19
lines changed

5 files changed

+233
-19
lines changed

Cargo.lock

Lines changed: 87 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,10 @@ serde_json = "1.0.145"
1919
clap = "4.5.48"
2020
anyhow = "1.0.100"
2121
console = "0.16.1"
22+
tracing = "0.1"
23+
chrono = { version = "0.4", optional = true }
24+
tracing-chrome = {version = "0.7", optional = true}
25+
tracing-subscriber = { version = "0.3", optional = true, features = ["env-filter"] }
2226

2327
[dev-dependencies]
2428
snapbox = "0.6.21"
@@ -28,3 +32,6 @@ fs_extra = "1.3.0"
2832
test-case = "3.3.1"
2933
num-bigint = "0.4.6"
3034
cairo-lang-casm = { version = "2.12.3", features = ["serde"] }
35+
36+
[features]
37+
tracing = ["dep:chrono", "dep:tracing-chrome", "dep:tracing-subscriber"]

src/commands/compile_contract.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ pub struct CompileContract {
2323
}
2424

2525
/// Compiles Sierra of the Starknet contract.
26+
#[tracing::instrument(skip_all, level = "info")]
2627
pub fn compile(mut sierra_json: Value) -> Result<Value> {
2728
sierra_json["abi"] = Value::Null;
2829
sierra_json["sierra_program_debug_info"] = Value::Null;

src/commands/compile_raw.rs

Lines changed: 42 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ use cairo_lang_sierra_to_casm::metadata::{calc_metadata, MetadataComputationConf
55
use clap::Args;
66
use serde_json::{json, Value};
77
use std::path::PathBuf;
8+
use tracing::trace_span;
89

910
#[derive(Args)]
1011
pub struct CompileRaw {
@@ -20,29 +21,51 @@ pub struct CompileRaw {
2021
}
2122

2223
/// Compiles Sierra of the plain Cairo code.
24+
#[tracing::instrument(skip_all, level = "info")]
2325
pub fn compile(sierra_program: Value) -> Result<Value> {
24-
let sierra_program: Program = serde_json::from_value(sierra_program)
25-
.context("Unable to deserialize Sierra program. Make sure it is in a correct format")?;
26+
let span = trace_span!("deserialize_sierra");
27+
let sierra_program: Program = {
28+
let _g = span.enter();
29+
serde_json::from_value(sierra_program)
30+
.context("Unable to deserialize Sierra program. Make sure it is in a correct format")?
31+
};
32+
2633
let metadata_config = MetadataComputationConfig::default();
27-
let metadata = calc_metadata(&sierra_program, metadata_config)?;
34+
let span = trace_span!("calc_metadata");
35+
let metadata = {
36+
let _g = span.enter();
37+
calc_metadata(&sierra_program, metadata_config)?
38+
};
2839

29-
let cairo_program = cairo_lang_sierra_to_casm::compiler::compile(
30-
&sierra_program,
31-
&metadata,
32-
SierraToCasmConfig {
33-
gas_usage_check: true,
34-
max_bytecode_size: usize::MAX,
35-
},
36-
)?;
37-
let assembled_cairo_program = cairo_program.assemble();
40+
let span = trace_span!("compile_sierra_to_casm");
41+
let cairo_program = {
42+
let _g = span.enter();
43+
cairo_lang_sierra_to_casm::compiler::compile(
44+
&sierra_program,
45+
&metadata,
46+
SierraToCasmConfig {
47+
gas_usage_check: true,
48+
max_bytecode_size: usize::MAX,
49+
},
50+
)?
51+
};
52+
let span = trace_span!("assemble_cairo_program");
53+
let assembled_cairo_program = {
54+
let _g = span.enter();
55+
cairo_program.assemble()
56+
};
3857

39-
Ok(json!({
40-
"assembled_cairo_program": {
41-
"bytecode": serde_json::to_value(assembled_cairo_program.bytecode)?,
42-
"hints": serde_json::to_value(assembled_cairo_program.hints)?
43-
},
44-
"debug_info": serde_json::to_value(serialize_cairo_program_debug_info(&cairo_program.debug_info))?
45-
}))
58+
let span = trace_span!("serialize_result");
59+
Ok({
60+
let _g = span.enter();
61+
json!({
62+
"assembled_cairo_program": {
63+
"bytecode": serde_json::to_value(assembled_cairo_program.bytecode)?,
64+
"hints": serde_json::to_value(assembled_cairo_program.hints)?
65+
},
66+
"debug_info": serde_json::to_value(serialize_cairo_program_debug_info(&cairo_program.debug_info))?
67+
})
68+
})
4669
}
4770

4871
fn serialize_cairo_program_debug_info(debug_info: &CairoProgramDebugInfo) -> Vec<(usize, usize)> {

src/main.rs

Lines changed: 96 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,13 +32,15 @@ fn print_error_message(error: &Error) {
3232
eprintln!("[{error_tag}] {error}");
3333
}
3434

35+
#[tracing::instrument(skip_all, level = "info")]
3536
fn read_json(file_path: PathBuf) -> Result<Value> {
3637
let sierra_file = File::open(file_path).context("Unable to open json file")?;
3738
let sierra_file_reader = BufReader::new(sierra_file);
3839

3940
serde_json::from_reader(sierra_file_reader).context("Unable to read json file")
4041
}
4142

43+
#[tracing::instrument(skip_all, level = "info")]
4244
fn output_casm(output_json: &Value, output_file_path: Option<PathBuf>) -> Result<()> {
4345
match output_file_path {
4446
Some(output_path) => {
@@ -58,6 +60,7 @@ fn output_casm(output_json: &Value, output_file_path: Option<PathBuf>) -> Result
5860

5961
fn main_execution() -> Result<bool> {
6062
let cli = Cli::parse();
63+
let _g = init_logging();
6164

6265
match cli.command {
6366
Commands::CompileContract(compile_contract) => {
@@ -89,3 +92,96 @@ fn main() {
8992
}
9093
};
9194
}
95+
96+
#[cfg(not(feature = "tracing"))]
97+
fn init_logging() -> Option<impl Drop> {
98+
struct Zst;
99+
impl Drop for Zst {
100+
fn drop(&mut self) {}
101+
}
102+
Option::<Zst>::None
103+
}
104+
105+
#[cfg(feature = "tracing")]
106+
fn init_logging() -> Option<impl Drop> {
107+
use chrono::Local;
108+
use std::fs;
109+
110+
use std::path::PathBuf;
111+
use tracing_chrome::ChromeLayerBuilder;
112+
use tracing_subscriber::filter::{EnvFilter, LevelFilter, Targets};
113+
use tracing_subscriber::fmt::time::Uptime;
114+
use tracing_subscriber::fmt::Layer;
115+
use tracing_subscriber::prelude::*;
116+
117+
let mut guard = None;
118+
119+
let fmt_layer = Layer::new()
120+
.with_writer(std::io::stderr)
121+
.with_timer(Uptime::default())
122+
.with_filter(
123+
EnvFilter::builder()
124+
.with_default_directive(LevelFilter::TRACE.into())
125+
.with_env_var("USC_LOG")
126+
.from_env_lossy(),
127+
);
128+
129+
// Disabled unless explicitly enabled with env var.
130+
let tracing_profile = is_truthy_env("USC_TRACING_PROFILE", false);
131+
132+
let profile_layer = if tracing_profile {
133+
let mut path = PathBuf::from(format!("./usc-profile-{}.json", Local::now().to_rfc3339()));
134+
135+
// Create the file now, so that we early panic, and `fs::canonicalize` will work.
136+
let profile_file = fs::File::create(&path).expect("failed to create profile file");
137+
138+
// Try to canonicalise the path so that it is easier to find the file from logs.
139+
if let Ok(canonical) = fs::canonicalize(&path) {
140+
path = canonical;
141+
}
142+
143+
eprintln!(
144+
"this USC run will output tracing profile to: {}",
145+
path.display()
146+
);
147+
eprintln!(
148+
"open that file with https://ui.perfetto.dev (or chrome://tracing) to analyze it"
149+
);
150+
151+
let (profile_layer, profile_layer_guard) = ChromeLayerBuilder::new()
152+
.writer(profile_file)
153+
.include_args(true)
154+
.build();
155+
156+
// Filter out less important logs because they're too verbose,
157+
// and with them the profile file quickly grows to several GBs of data.
158+
let profile_layer = profile_layer.with_filter(
159+
Targets::new()
160+
.with_default(LevelFilter::TRACE)
161+
.with_target("salsa", LevelFilter::WARN),
162+
);
163+
164+
guard = Some(profile_layer_guard);
165+
Some(profile_layer)
166+
} else {
167+
None
168+
};
169+
170+
tracing::subscriber::set_global_default(
171+
tracing_subscriber::registry()
172+
.with(fmt_layer)
173+
.with(profile_layer),
174+
)
175+
.expect("could not set up global logger");
176+
177+
guard
178+
}
179+
180+
#[cfg(feature = "tracing")]
181+
#[must_use]
182+
pub fn is_truthy_env(name: &str, default: bool) -> bool {
183+
std::env::var(name).ok().map_or(default, |var| {
184+
let s = var.as_str();
185+
s == "true" || s == "1"
186+
})
187+
}

0 commit comments

Comments
 (0)