diff --git a/Cargo.lock b/Cargo.lock
index 32dfc0725..24aa8dc7e 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -2056,6 +2056,7 @@ dependencies = [
"ibc-relayer",
"ibc-relayer-types",
"oneline-eyre",
+ "serde_json",
"tracing",
]
@@ -2068,6 +2069,8 @@ dependencies = [
"hermes-cosmos-relayer",
"hermes-relayer-runtime",
"oneline-eyre",
+ "serde",
+ "serde_json",
"tokio",
"tracing",
"tracing-subscriber",
@@ -6320,6 +6323,16 @@ dependencies = [
"tracing-core",
]
+[[package]]
+name = "tracing-serde"
+version = "0.1.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "bc6b213177105856957181934e4920de57730fc69bf42c37ee5bb664d406d9e1"
+dependencies = [
+ "serde",
+ "tracing-core",
+]
+
[[package]]
name = "tracing-subscriber"
version = "0.3.18"
@@ -6330,12 +6343,15 @@ dependencies = [
"nu-ansi-term",
"once_cell",
"regex",
+ "serde",
+ "serde_json",
"sharded-slab",
"smallvec",
"thread_local",
"tracing",
"tracing-core",
"tracing-log",
+ "tracing-serde",
]
[[package]]
diff --git a/crates/cli/cli-framework/Cargo.toml b/crates/cli/cli-framework/Cargo.toml
index 023189582..0c463a553 100644
--- a/crates/cli/cli-framework/Cargo.toml
+++ b/crates/cli/cli-framework/Cargo.toml
@@ -20,5 +20,7 @@ cgp-core = { workspace = true }
clap = { workspace = true }
tokio = { workspace = true, features = ["full"] }
tracing = { workspace = true }
-tracing-subscriber = { workspace = true, features = ["env-filter"] }
+tracing-subscriber = { workspace = true, features = ["env-filter", "json"] }
oneline-eyre = { workspace = true }
+serde = { workspace = true }
+serde_json = { workspace = true }
diff --git a/crates/cli/cli-framework/src/application/boot.rs b/crates/cli/cli-framework/src/application/boot.rs
index 79e42a502..56160c860 100644
--- a/crates/cli/cli-framework/src/application/boot.rs
+++ b/crates/cli/cli-framework/src/application/boot.rs
@@ -7,20 +7,24 @@ use hermes_relayer_runtime::types::runtime::HermesRuntime;
use crate::application::log::{enable_ansi, install_logger};
use crate::application::Application;
use crate::config::Config;
+use crate::output;
use crate::Result;
pub fn boot() -> Result<()>
where
A: Application,
{
- let with_color = enable_ansi();
- install_logger(with_color);
-
oneline_eyre::install()?;
let app = A::parse_from_env();
let config_path = app.config_path();
+ let with_color = enable_ansi();
+ let with_json = app.json_output();
+ install_logger(with_color, with_json);
+
+ output::set_json(with_json);
+
let config =
A::Config::load_from_path(config_path).map_err(|e| eyre!("failed to load config: {e}"))?;
@@ -32,8 +36,17 @@ where
let rt = HermesRuntime::new(Arc::new(rt));
rt.runtime
- .block_on(app.run(rt.clone(), config))
+ .block_on(run(rt.clone(), app, config))
.map_err(|e| eyre!("Hermes command exited with an error: {e}"))?;
Ok(())
}
+
+pub async fn run(rt: HermesRuntime, app: A, config: A::Config) -> Result<()>
+where
+ A: Application,
+{
+ let output = app.run(rt, config).await?;
+ output.print();
+ Ok(())
+}
diff --git a/crates/cli/cli-framework/src/application/log.rs b/crates/cli/cli-framework/src/application/log.rs
index 0e7023e47..e0832d64c 100644
--- a/crates/cli/cli-framework/src/application/log.rs
+++ b/crates/cli/cli-framework/src/application/log.rs
@@ -2,25 +2,29 @@
Install the [`tracing_subscriber`] logger handlers so that logs will
be displayed during test.
*/
-pub fn install_logger(with_color: bool) {
+pub fn install_logger(with_color: bool, with_json: bool) {
use tracing::level_filters::LevelFilter;
use tracing_subscriber::layer::SubscriberExt;
use tracing_subscriber::util::SubscriberInitExt;
use tracing_subscriber::EnvFilter;
+ use tracing_subscriber::{fmt, registry};
// Use log level INFO by default if RUST_LOG is not set.
let env_filter = EnvFilter::builder()
.with_default_directive(LevelFilter::INFO.into())
.from_env_lossy();
- let layer = tracing_subscriber::fmt::layer()
- .with_ansi(with_color)
- .with_target(false);
+ if with_json {
+ let fmt_layer = fmt::layer().with_target(false).json();
+ registry().with(env_filter).with(fmt_layer).init();
+ } else {
+ let fmt_layer = fmt::layer()
+ .with_ansi(with_color)
+ .with_target(false)
+ .compact();
- tracing_subscriber::registry()
- .with(env_filter)
- .with(layer)
- .init();
+ registry().with(env_filter).with(fmt_layer).init();
+ };
}
/// Check if both stdout and stderr are proper terminal (tty),
diff --git a/crates/cli/cli-framework/src/application/mod.rs b/crates/cli/cli-framework/src/application/mod.rs
index 03ddf4dab..4ce9b47fd 100644
--- a/crates/cli/cli-framework/src/application/mod.rs
+++ b/crates/cli/cli-framework/src/application/mod.rs
@@ -10,6 +10,7 @@ use hermes_relayer_runtime::types::runtime::HermesRuntime;
use crate::command::Runnable;
use crate::config::Config;
+use crate::output::Output;
use crate::Result;
#[async_trait]
@@ -21,5 +22,7 @@ pub trait Application: Sized {
fn config_path(&self) -> &Path;
- async fn run(&self, runtime: HermesRuntime, config: Self::Config) -> Result<()>;
+ fn json_output(&self) -> bool;
+
+ async fn run(&self, runtime: HermesRuntime, config: Self::Config) -> Result