From b308ccf4326048874a39d6f4f006e13c8b0eee7c Mon Sep 17 00:00:00 2001 From: Prajwol Gyawali Date: Tue, 19 May 2026 09:09:35 +0545 Subject: [PATCH 1/3] feat(asm-runner): use strata-logging from strata-common Drop the in-tree tracing-subscriber bootstrap and share the strata-common logging stack used by alpen/strata-signer. This unlocks OTLP traces/metrics, optional rolling file logs, JSON output, and the tracing-to-metrics bridge through a TOML [logging] section, with field-level defaults so existing config.toml files keep working unchanged. Init now runs inside a Tokio runtime context (required by the OTLP exporter) and finalize() flushes on both the graceful and crash shutdown paths. --- Cargo.lock | 280 ++++++++++++++++++++++++++++++++--- Cargo.toml | 1 + bin/asm-runner/Cargo.toml | 2 +- bin/asm-runner/src/config.rs | 47 ++++++ bin/asm-runner/src/main.rs | 83 +++++++---- 5 files changed, 358 insertions(+), 55 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index b6af4497..5e61ea6c 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -529,7 +529,7 @@ version = "1.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "40c48f72fd53cd289104fc64099abca73db4166ad86ea0b4341abe65af83dadc" dependencies = [ - "windows-sys 0.61.2", + "windows-sys 0.60.2", ] [[package]] @@ -540,7 +540,7 @@ checksum = "291e6a250ff86cd4a820112fb8898808a366d8f9f58ce16d1f538353ad55747d" dependencies = [ "anstyle", "once_cell_polyfill", - "windows-sys 0.61.2", + "windows-sys 0.60.2", ] [[package]] @@ -2083,6 +2083,12 @@ dependencies = [ "cfg-if 1.0.4", ] +[[package]] +name = "critical-section" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "790eea4361631c5e7d22598ecd5723ff611904e3344ce8720784c93e3d83d40b" + [[package]] name = "crossbeam" version = "0.8.4" @@ -2685,7 +2691,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "39cab71617ae0d63f51a36d69f866391735b51691dbda63cf6f96d042b63efeb" dependencies = [ "libc", - "windows-sys 0.61.2", + "windows-sys 0.52.0", ] [[package]] @@ -3416,7 +3422,7 @@ dependencies = [ "libc", "percent-encoding", "pin-project-lite", - "socket2 0.6.3", + "socket2 0.5.10", "tokio", "tower-service", "tracing", @@ -4236,6 +4242,45 @@ version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3d97bbf43eb4f088f8ca469930cde17fa036207c9a5e02ccc5107c4e8b17c964" +[[package]] +name = "metrics" +version = "0.24.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "89550ee9f79e88fef3119de263694973a8adb26c21d75322164fb8c493039fe2" +dependencies = [ + "portable-atomic", + "rapidhash", +] + +[[package]] +name = "metrics-exporter-otel" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "58b8984fa38406b80c094943c0ba90e53d5fff0aea051ff9fac96cf6940993c8" +dependencies = [ + "metrics", + "metrics-util", + "opentelemetry 0.31.0", + "portable-atomic", + "scc", +] + +[[package]] +name = "metrics-util" +version = "0.20.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "96f8722f8562635f92f8ed992f26df0532266eb03d5202607c20c0d7e9745e13" +dependencies = [ + "crossbeam-epoch", + "crossbeam-utils", + "hashbrown 0.16.1", + "metrics", + "rand 0.9.2", + "rand_xoshiro", + "rapidhash", + "sketches-ddsketch", +] + [[package]] name = "mime" version = "0.3.17" @@ -4438,7 +4483,7 @@ version = "0.50.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7957b9740744892f114936ab4a57b3f487491bbeafaf8083688b16841a4240e5" dependencies = [ - "windows-sys 0.61.2", + "windows-sys 0.59.0", ] [[package]] @@ -4604,7 +4649,7 @@ version = "0.7.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "680998035259dcfcafe653688bf2aa6d3e2dc05e98be6ab46afb089dc84f1df8" dependencies = [ - "proc-macro-crate 3.5.0", + "proc-macro-crate 1.3.1", "proc-macro2", "quote", "syn 2.0.117", @@ -4690,6 +4735,68 @@ dependencies = [ "tracing", ] +[[package]] +name = "opentelemetry-http" +version = "0.31.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d7a6d09a73194e6b66df7c8f1b680f156d916a1a942abf2de06823dd02b7855d" +dependencies = [ + "async-trait", + "bytes", + "http 1.4.0", + "opentelemetry 0.31.0", + "reqwest", +] + +[[package]] +name = "opentelemetry-otlp" +version = "0.31.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1f69cd6acbb9af919df949cd1ec9e5e7fdc2ef15d234b6b795aaa525cc02f71f" +dependencies = [ + "http 1.4.0", + "opentelemetry 0.31.0", + "opentelemetry-http", + "opentelemetry-proto", + "opentelemetry_sdk", + "prost 0.14.3", + "reqwest", + "thiserror 2.0.18", + "tokio", + "tonic 0.14.6", + "tracing", +] + +[[package]] +name = "opentelemetry-proto" +version = "0.31.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a7175df06de5eaee9909d4805a3d07e28bb752c34cab57fa9cff549da596b30f" +dependencies = [ + "opentelemetry 0.31.0", + "opentelemetry_sdk", + "prost 0.14.3", + "tonic 0.14.6", + "tonic-prost", +] + +[[package]] +name = "opentelemetry_sdk" +version = "0.31.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e14ae4f5991976fd48df6d843de219ca6d31b01daaab2dad5af2badeded372bd" +dependencies = [ + "futures-channel", + "futures-executor", + "futures-util", + "opentelemetry 0.31.0", + "percent-encoding", + "rand 0.9.2", + "thiserror 2.0.18", + "tokio", + "tokio-stream", +] + [[package]] name = "option-ext" version = "0.2.0" @@ -5191,6 +5298,9 @@ name = "portable-atomic" version = "1.13.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c33a9471896f1c69cecef8d20cbe2f7accd12527ce60845ff44c153bb2a21b49" +dependencies = [ + "critical-section", +] [[package]] name = "potential_utf" @@ -5334,7 +5444,17 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2796faa41db3ec313a31f7624d9286acf277b52de526150b7e69f3debf891ee5" dependencies = [ "bytes", - "prost-derive", + "prost-derive 0.13.5", +] + +[[package]] +name = "prost" +version = "0.14.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d2ea70524a2f82d518bce41317d0fae74151505651af45faf1ffbd6fd33f0568" +dependencies = [ + "bytes", + "prost-derive 0.14.3", ] [[package]] @@ -5350,7 +5470,7 @@ dependencies = [ "once_cell", "petgraph", "prettyplease", - "prost", + "prost 0.13.5", "prost-types", "regex", "syn 2.0.117", @@ -5370,13 +5490,26 @@ dependencies = [ "syn 2.0.117", ] +[[package]] +name = "prost-derive" +version = "0.14.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "27c6023962132f4b30eb4c172c91ce92d933da334c59c23cddee82358ddafb0b" +dependencies = [ + "anyhow", + "itertools 0.12.1", + "proc-macro2", + "quote", + "syn 2.0.117", +] + [[package]] name = "prost-types" version = "0.13.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "52c2c1bf36ddb1a1c396b3601a3cec27c2462e45f07c386894ec3ccf5332bd16" dependencies = [ - "prost", + "prost 0.13.5", ] [[package]] @@ -5398,7 +5531,7 @@ dependencies = [ "quinn-udp", "rustc-hash", "rustls 0.23.37", - "socket2 0.6.3", + "socket2 0.5.10", "thiserror 2.0.18", "tokio", "tracing", @@ -5435,7 +5568,7 @@ dependencies = [ "cfg_aliases", "libc", "once_cell", - "socket2 0.6.3", + "socket2 0.5.10", "tracing", "windows-sys 0.60.2", ] @@ -5538,6 +5671,15 @@ dependencies = [ "rand_core 0.9.5", ] +[[package]] +name = "rand_xoshiro" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f703f4665700daf5512dcca5f43afa6af89f09db47fb56be587f80636bda2d41" +dependencies = [ + "rand_core 0.9.5", +] + [[package]] name = "range-set-blaze" version = "0.1.16" @@ -5680,6 +5822,7 @@ checksum = "eddd3ca559203180a307f12d114c268abf583f59b03cb906fd0b3ff8646c1147" dependencies = [ "base64 0.22.1", "bytes", + "futures-channel", "futures-core", "futures-util", "http 1.4.0", @@ -5859,7 +6002,7 @@ dependencies = [ "errno", "libc", "linux-raw-sys", - "windows-sys 0.61.2", + "windows-sys 0.52.0", ] [[package]] @@ -6486,6 +6629,12 @@ dependencies = [ "thiserror 2.0.18", ] +[[package]] +name = "sketches-ddsketch" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0c6f73aeb92d671e0cc4dca167e59b2deb6387c375391bc99ee743f326994a2b" + [[package]] name = "slab" version = "0.4.12" @@ -6981,7 +7130,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3a766e1110788c36f4fa1c2b71b387a7815aa65f88ce0229841826633d93723e" dependencies = [ "libc", - "windows-sys 0.61.2", + "windows-sys 0.60.2", ] [[package]] @@ -7321,7 +7470,7 @@ dependencies = [ "tempfile", "thiserror 1.0.69", "tokio", - "tonic", + "tonic 0.12.3", "tracing", "tracing-appender", "tracing-subscriber", @@ -7340,13 +7489,13 @@ dependencies = [ "futures-util", "hashbrown 0.14.5", "mti", - "prost", + "prost 0.13.5", "serde", "sp1-core-machine", "sp1-hypercube", "sp1-primitives", "tokio", - "tonic", + "tonic 0.12.3", "tonic-build", "tracing", ] @@ -7508,7 +7657,7 @@ dependencies = [ "itertools 0.14.0", "k256", "num-bigint 0.4.6", - "prost", + "prost 0.13.5", "reqwest", "reqwest-middleware", "rustls 0.23.37", @@ -7528,7 +7677,7 @@ dependencies = [ "tempfile", "thiserror 1.0.69", "tokio", - "tonic", + "tonic 0.12.3", "tracing", "twirp-rs", "zstd", @@ -8087,6 +8236,7 @@ dependencies = [ "strata-btc-types", "strata-btc-verification", "strata-identifiers", + "strata-logging", "strata-merkle", "strata-predicate", "strata-tasks", @@ -8095,7 +8245,6 @@ dependencies = [ "tokio", "toml 1.1.0+spec-1.1.0", "tracing", - "tracing-subscriber", "tree_hash", "zkaleido 0.1.0 (git+https://github.com/alpenlabs/zkaleido?tag=v0.1-beta.2)", "zkaleido-native-adapter", @@ -8330,6 +8479,22 @@ dependencies = [ "thiserror 2.0.18", ] +[[package]] +name = "strata-logging" +version = "0.1.0" +source = "git+https://github.com/alpenlabs/strata-common?tag=v0.1.0-alpha-rc21#bb060d613880d8d4c8decd0e7544acb54e4d5a25" +dependencies = [ + "metrics", + "metrics-exporter-otel", + "opentelemetry 0.31.0", + "opentelemetry-otlp", + "opentelemetry_sdk", + "tracing", + "tracing-appender", + "tracing-opentelemetry", + "tracing-subscriber", +] + [[package]] name = "strata-merkle" version = "0.2.0" @@ -8672,7 +8837,7 @@ dependencies = [ "getrandom 0.4.2", "once_cell", "rustix", - "windows-sys 0.61.2", + "windows-sys 0.52.0", ] [[package]] @@ -9001,7 +9166,7 @@ dependencies = [ "hyper-util", "percent-encoding", "pin-project", - "prost", + "prost 0.13.5", "rustls-native-certs", "rustls-pemfile", "socket2 0.5.10", @@ -9015,6 +9180,32 @@ dependencies = [ "webpki-roots 0.26.11", ] +[[package]] +name = "tonic" +version = "0.14.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac2a5518c70fa84342385732db33fb3f44bc4cc748936eb5833d2df34d6445ef" +dependencies = [ + "async-trait", + "base64 0.22.1", + "bytes", + "http 1.4.0", + "http-body 1.0.1", + "http-body-util", + "hyper", + "hyper-timeout", + "hyper-util", + "percent-encoding", + "pin-project", + "sync_wrapper", + "tokio", + "tokio-stream", + "tower 0.5.3", + "tower-layer", + "tower-service", + "tracing", +] + [[package]] name = "tonic-build" version = "0.12.3" @@ -9029,6 +9220,17 @@ dependencies = [ "syn 2.0.117", ] +[[package]] +name = "tonic-prost" +version = "0.14.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "50849f68853be452acf590cde0b146665b8d507b3b8af17261df47e02c209ea0" +dependencies = [ + "bytes", + "prost 0.14.3", + "tonic 0.14.6", +] + [[package]] name = "tower" version = "0.4.13" @@ -9057,9 +9259,12 @@ checksum = "ebe5ef63511595f1344e2d5cfa636d973292adc0eec1f0ad45fae9f0851ab1d4" dependencies = [ "futures-core", "futures-util", + "indexmap 2.13.0", "pin-project-lite", + "slab", "sync_wrapper", "tokio", + "tokio-util", "tower-layer", "tower-service", "tracing", @@ -9164,6 +9369,32 @@ dependencies = [ "tracing-core", ] +[[package]] +name = "tracing-opentelemetry" +version = "0.32.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1ac28f2d093c6c477eaa76b23525478f38de514fa9aeb1285738d4b97a9552fc" +dependencies = [ + "js-sys", + "opentelemetry 0.31.0", + "smallvec", + "tracing", + "tracing-core", + "tracing-log", + "tracing-subscriber", + "web-time", +] + +[[package]] +name = "tracing-serde" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "704b1aeb7be0d0a84fc9828cae51dab5970fee5088f83d1dd7ee6f6246fc6ff1" +dependencies = [ + "serde", + "tracing-core", +] + [[package]] name = "tracing-subscriber" version = "0.3.23" @@ -9174,12 +9405,15 @@ dependencies = [ "nu-ansi-term", "once_cell", "regex-automata", + "serde", + "serde_json", "sharded-slab", "smallvec", "thread_local", "tracing", "tracing-core", "tracing-log", + "tracing-serde", ] [[package]] @@ -9233,7 +9467,7 @@ dependencies = [ "http 1.4.0", "http-body-util", "hyper", - "prost", + "prost 0.13.5", "reqwest", "serde", "serde_json", @@ -9660,7 +9894,7 @@ version = "0.1.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c2a7b1c03c876122aa43f3020e6c3c3ee5c05081c9a00739faf7503aeba10d22" dependencies = [ - "windows-sys 0.61.2", + "windows-sys 0.48.0", ] [[package]] diff --git a/Cargo.toml b/Cargo.toml index d309d0cf..8cb0c0bb 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -105,6 +105,7 @@ strata-crypto = { git = "https://github.com/alpenlabs/strata-common", tag = "v0. strata-identifiers = { git = "https://github.com/alpenlabs/strata-common", tag = "v0.1.0-alpha-rc21" } strata-l1-envelope-fmt = { git = "https://github.com/alpenlabs/strata-common", tag = "v0.1.0-alpha-rc21" } strata-l1-txfmt = { git = "https://github.com/alpenlabs/strata-common", tag = "v0.1.0-alpha-rc21" } +strata-logging = { git = "https://github.com/alpenlabs/strata-common", tag = "v0.1.0-alpha-rc21" } strata-merkle = { git = "https://github.com/alpenlabs/strata-common", tag = "v0.1.0-alpha-rc21" } strata-msg-fmt = { git = "https://github.com/alpenlabs/strata-common", tag = "v0.1.0-alpha-rc21" } strata-predicate = { git = "https://github.com/alpenlabs/strata-common", tag = "v0.1.0-alpha-rc21" } diff --git a/bin/asm-runner/Cargo.toml b/bin/asm-runner/Cargo.toml index cb6c8a3b..5439a32e 100644 --- a/bin/asm-runner/Cargo.toml +++ b/bin/asm-runner/Cargo.toml @@ -28,6 +28,7 @@ strata-asm-proto-checkpoint-types.workspace = true strata-asm-spec.workspace = true strata-asm-worker.workspace = true strata-btc-types.workspace = true +strata-logging.workspace = true asm-storage.workspace = true @@ -59,7 +60,6 @@ thiserror.workspace = true tokio.workspace = true toml.workspace = true tracing.workspace = true -tracing-subscriber = { version = "0.3.19", features = ["env-filter"] } zkaleido.workspace = true zkaleido-native-adapter.workspace = true zkaleido-sp1-groth16-verifier = { workspace = true, optional = true } diff --git a/bin/asm-runner/src/config.rs b/bin/asm-runner/src/config.rs index 3603d115..f833f9bb 100644 --- a/bin/asm-runner/src/config.rs +++ b/bin/asm-runner/src/config.rs @@ -17,6 +17,53 @@ pub(crate) struct AsmRpcConfig { pub bitcoin: BitcoinConfig, /// Proof orchestrator configuration (optional — omit to disable proof generation). pub orchestrator: Option, + /// Logging configuration. Omit the `[logging]` section to accept defaults + /// (stdout, compact format, `RUST_LOG`-driven filter). + #[serde(default)] + pub logging: LoggingConfig, +} + +/// Logging configuration mirroring `strata_logging::LoggingInitConfig`. +/// +/// All fields are optional; missing fields fall back to `strata-logging` defaults. +#[derive(Debug, Clone, Serialize, Deserialize)] +pub(crate) struct LoggingConfig { + /// Optional service label appended to the service name (e.g. `"prod"`, `"dev"`). + pub service_label: Option, + /// OpenTelemetry OTLP collector gRPC endpoint. When set, OTLP export is enabled + /// and the tracing-to-metrics bridge is turned on automatically. + pub otlp_url: Option, + /// Directory to write rolling log files into. When unset, file logging is disabled. + pub log_dir: Option, + /// Filename prefix for rolling log files. Falls back to the binary's default prefix. + pub log_file_prefix: Option, + /// Use JSON output format instead of the compact text format. + pub json_format: Option, + /// Extra `EnvFilter` directives applied before `RUST_LOG` (e.g. to silence noisy + /// dependencies). Defaults to a curated list when omitted; specify an empty list + /// in TOML to clear the defaults. + #[serde(default = "default_extra_filter_directives")] + pub extra_filter_directives: Vec, +} + +impl Default for LoggingConfig { + fn default() -> Self { + Self { + service_label: None, + otlp_url: None, + log_dir: None, + log_file_prefix: None, + json_format: None, + extra_filter_directives: default_extra_filter_directives(), + } + } +} + +fn default_extra_filter_directives() -> Vec { + vec![ + "jsonrpsee_server::server=warn".to_owned(), + "sp1_core_executor=warn".to_owned(), + ] } /// RPC server configuration diff --git a/bin/asm-runner/src/main.rs b/bin/asm-runner/src/main.rs index c8d632f3..8642621a 100644 --- a/bin/asm-runner/src/main.rs +++ b/bin/asm-runner/src/main.rs @@ -16,13 +16,16 @@ use std::{fs::read_to_string, path::PathBuf, time::Duration}; use anyhow::Result; use clap::Parser; use strata_asm_params::AsmParams; +use strata_logging::{LoggingInitConfig, finalize, init_logging_from_config}; use strata_tasks::TaskManager; -use tokio::runtime::Builder; -use tracing::info; -use tracing_subscriber::{EnvFilter, fmt, layer::SubscriberExt, util::SubscriberInitExt}; +use tokio::runtime::{Builder, Handle}; +use tracing::{error, info}; use zkaleido_native_adapter as _; -use crate::{bootstrap::bootstrap, config::AsmRpcConfig}; +use crate::{ + bootstrap::bootstrap, + config::{AsmRpcConfig, LoggingConfig}, +}; /// Timeout for graceful shutdown. const SHUTDOWN_TIMEOUT: Duration = Duration::from_secs(30); @@ -42,29 +45,29 @@ struct Cli { } fn main() { - // 1. Initialize logging - init_logging(); - - // 2. Parse CLI args + // 1. Parse CLI args let cli = Cli::parse(); - // 3. Load configuration + // 2. Load configuration let config = load_config(&cli.config).expect("Failed to load config"); - // 4. Load ASM params + // 3. Load ASM params let params = load_params(&cli.params).expect("Failed to load ASM params"); - info!( - "Starting ASM RPC server with config: {:?}, params: {:?}", - config, params - ); - - // 5. Create tokio runtime + // 4. Create tokio runtime let runtime = Builder::new_multi_thread() .enable_all() .build() .expect("Failed to create tokio runtime"); + // 5. Initialize logging. + init_logging(runtime.handle(), &config.logging); + + info!( + "Starting ASM RPC server with config: {:?}, params: {:?}", + config, params + ); + // 6. Create task manager and start signal listeners let task_manager = TaskManager::new(runtime.handle().clone()); task_manager.start_signal_listeners(); @@ -76,12 +79,19 @@ fn main() { bootstrap(config, params, executor_clone).await }); - // 8. Monitor all tasks and handle shutdown - if let Err(e) = task_manager.monitor(Some(SHUTDOWN_TIMEOUT)) { - panic!("ASM RPC server crashed: {e:?}"); + // 8. Monitor all tasks and handle shutdown. Flush OTLP on both paths so a crash signal still + // reaches the collector. + match task_manager.monitor(Some(SHUTDOWN_TIMEOUT)) { + Ok(()) => { + info!("ASM RPC server shutdown complete"); + finalize(); + } + Err(e) => { + error!("ASM RPC server crashed: {e:?}"); + finalize(); + panic!("ASM RPC server crashed: {e:?}"); + } } - - tracing::info!("ASM RPC server shutdown complete"); } /// Load ASM parameters @@ -98,14 +108,25 @@ fn load_config(path: &PathBuf) -> Result { Ok(config) } -/// Initialize tracing-based logging with an env filter. -/// -/// Honors the `RUST_LOG` environment variable. When unset, defaults to `info`. -fn init_logging() { - let filter = EnvFilter::try_from_default_env().unwrap_or_else(|_| EnvFilter::new("info")); - let layer = fmt::layer().compact(); - tracing_subscriber::registry() - .with(filter) - .with(layer) - .init(); +// The OTLP exporter is built via the Tokio reactor, so init must happen inside +// a runtime context — entering the handle for the duration of this call is +// enough; the guard does not need to live past initialization. +fn init_logging(rt: &Handle, config: &LoggingConfig) { + let _guard = rt.enter(); + let extra_filter_directives: Vec<&str> = config + .extra_filter_directives + .iter() + .map(String::as_str) + .collect(); + init_logging_from_config(LoggingInitConfig { + service_base_name: "asm-runner", + service_label: config.service_label.as_deref(), + otlp_url: config.otlp_url.as_deref(), + log_dir: config.log_dir.as_ref(), + log_file_prefix: config.log_file_prefix.as_deref(), + json_format: config.json_format, + default_log_prefix: "asm-runner", + enable_metrics_layer: config.otlp_url.is_some(), + extra_filter_directives: &extra_filter_directives, + }); } From 1462355bdeb6ecd70db581075affc41b9e0df5ab Mon Sep 17 00:00:00 2001 From: Prajwol Gyawali Date: Tue, 19 May 2026 09:16:15 +0545 Subject: [PATCH 2/3] feat(asm-runner): drop curated default for extra_filter_directives The custom serde-default and matching manual Default impl were boilerplate that disagreed with the derived Default. Rely on derive(Default) so the empty-section and missing-field paths agree, and let operators populate extra_filter_directives explicitly in TOML when they want them. --- bin/asm-runner/src/config.rs | 26 ++------------------------ 1 file changed, 2 insertions(+), 24 deletions(-) diff --git a/bin/asm-runner/src/config.rs b/bin/asm-runner/src/config.rs index f833f9bb..16a22c5e 100644 --- a/bin/asm-runner/src/config.rs +++ b/bin/asm-runner/src/config.rs @@ -26,7 +26,7 @@ pub(crate) struct AsmRpcConfig { /// Logging configuration mirroring `strata_logging::LoggingInitConfig`. /// /// All fields are optional; missing fields fall back to `strata-logging` defaults. -#[derive(Debug, Clone, Serialize, Deserialize)] +#[derive(Debug, Clone, Default, Serialize, Deserialize)] pub(crate) struct LoggingConfig { /// Optional service label appended to the service name (e.g. `"prod"`, `"dev"`). pub service_label: Option, @@ -40,32 +40,10 @@ pub(crate) struct LoggingConfig { /// Use JSON output format instead of the compact text format. pub json_format: Option, /// Extra `EnvFilter` directives applied before `RUST_LOG` (e.g. to silence noisy - /// dependencies). Defaults to a curated list when omitted; specify an empty list - /// in TOML to clear the defaults. - #[serde(default = "default_extra_filter_directives")] + /// dependencies). Empty when omitted. pub extra_filter_directives: Vec, } -impl Default for LoggingConfig { - fn default() -> Self { - Self { - service_label: None, - otlp_url: None, - log_dir: None, - log_file_prefix: None, - json_format: None, - extra_filter_directives: default_extra_filter_directives(), - } - } -} - -fn default_extra_filter_directives() -> Vec { - vec![ - "jsonrpsee_server::server=warn".to_owned(), - "sp1_core_executor=warn".to_owned(), - ] -} - /// RPC server configuration #[derive(Debug, Clone, Serialize, Deserialize)] pub(crate) struct RpcConfig { From 1d95891aac9332875bb540134a329abef03a0439 Mon Sep 17 00:00:00 2001 From: Prajwol Gyawali Date: Tue, 19 May 2026 21:02:40 +0545 Subject: [PATCH 3/3] fix(asm-runner): default-skip every field of LoggingConfig Without struct-level `#[serde(default)]`, a `[logging]` section that omits `extra_filter_directives` (a `Vec`, not an `Option`) fails to deserialize with `missing field`, despite the docs promising all fields are optional. Moving the attribute to the struct piggybacks on the derived `Default` and makes every field uniformly skippable, including future non-`Option` additions. Adds deserialization tests covering both a partial `[logging]` section and a config with no `[logging]` table at all. --- bin/asm-runner/src/config.rs | 66 ++++++++++++++++++++++++++++++++++++ 1 file changed, 66 insertions(+) diff --git a/bin/asm-runner/src/config.rs b/bin/asm-runner/src/config.rs index 16a22c5e..0e423f4b 100644 --- a/bin/asm-runner/src/config.rs +++ b/bin/asm-runner/src/config.rs @@ -27,6 +27,7 @@ pub(crate) struct AsmRpcConfig { /// /// All fields are optional; missing fields fall back to `strata-logging` defaults. #[derive(Debug, Clone, Default, Serialize, Deserialize)] +#[serde(default)] pub(crate) struct LoggingConfig { /// Optional service label appended to the service name (e.g. `"prod"`, `"dev"`). pub service_label: Option, @@ -85,3 +86,68 @@ pub(crate) struct BitcoinConfig { // emitted only on the rawblock connection. Fix that. pub rawblock_connection_string: String, } + +#[cfg(test)] +mod tests { + use super::*; + + // A `[logging]` section that only sets `otlp_url` must deserialize cleanly + // and leave every other field at its default — historically the missing + // `extra_filter_directives` triggered `missing field` errors. + #[test] + fn logging_config_partial_section_uses_defaults() { + let toml_src = r#" + [rpc] + host = "127.0.0.1" + port = 8000 + + [database] + path = "/tmp/asm-db" + + [bitcoin] + rpc_url = "http://localhost:18443" + rpc_user = "user" + rpc_password = "pass" + rawblock_connection_string = "tcp://127.0.0.1:28332" + + [logging] + otlp_url = "http://localhost:4317" + "#; + + let config: AsmRpcConfig = toml::from_str(toml_src).expect("should parse"); + + assert_eq!( + config.logging.otlp_url.as_deref(), + Some("http://localhost:4317") + ); + assert!(config.logging.service_label.is_none()); + assert!(config.logging.log_dir.is_none()); + assert!(config.logging.log_file_prefix.is_none()); + assert!(config.logging.json_format.is_none()); + assert!(config.logging.extra_filter_directives.is_empty()); + } + + // Omitting the entire `[logging]` table must also be a clean parse. + #[test] + fn logging_section_optional() { + let toml_src = r#" + [rpc] + host = "127.0.0.1" + port = 8000 + + [database] + path = "/tmp/asm-db" + + [bitcoin] + rpc_url = "http://localhost:18443" + rpc_user = "user" + rpc_password = "pass" + rawblock_connection_string = "tcp://127.0.0.1:28332" + "#; + + let config: AsmRpcConfig = toml::from_str(toml_src).expect("should parse"); + + assert!(config.logging.otlp_url.is_none()); + assert!(config.logging.extra_filter_directives.is_empty()); + } +}