Skip to content

Commit c7105d8

Browse files
authored
Add support for JSON log format (cowprotocol#3336)
# Description Structured logs offer several advantages for our services: - Improved troubleshooting and root cause analysis, as the flow of a request can be more easily traced. - Simpler log correlation. - Easier integration and automation. This PR introduces a new parameter, `use_json_format`, for log output (currently set to `false` by default). When enabled, the `tracing` crate will emit logs in JSON format instead of the standard plain text. Below is an example of a log entry from the `autopilot` service using the new structured format: ```json {"timestamp":"2025-03-25T12:12:42.492Z","level":"DEBUG","fields":{"message":"stored order events","label":"Executing","count":1,"elapsed":"7.604417ms"},"target":"autopilot::database::order_events","span":{"auction_id":1057,"name":"auction"},"spans":[{"auction_id":1057,"name":"auction"}]} ``` Related to cowprotocol#3282 # Changes - Added the `json` feature to the `tracing-subscriber` crate, and updated the version to the latest. - Introduced a new `log_use_json_format` parameter to specify whether to use structured logging. It is disabled by default. - Used across all crates that perform logging: `orderbook`, `autopilot`, `driver`, `solver`, `alerter`, and `refunder`. - Since logging is encapsulated within the `observer` crate, the creation of the new JSON logging layer only needed to be implemented there. - The new parameter is currently set to `false` in all unit and E2E tests. ## How to test Testing was done by running e2e tests in both scenarios (new parameter enabled and disabled) and inspecting the resulting logs for the services.
1 parent 3c2c00b commit c7105d8

21 files changed

Lines changed: 99 additions & 49 deletions

File tree

Cargo.lock

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

Cargo.toml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -48,8 +48,8 @@ thiserror = "1.0.61"
4848
toml = "0.8.14"
4949
tokio = { version = "1.38.0", features = ["tracing"] }
5050
tokio-stream = { version = "0.1.15", features = ["sync"] }
51-
tracing = "0.1.40"
52-
tracing-subscriber = "0.3.18"
51+
tracing = "0.1.41"
52+
tracing-subscriber = { version = "0.3.19", features = ["json"] }
5353
url = "2.5.0"
5454
warp = { git = 'https://github.com/cowprotocol/warp.git', rev = "586244e", default-features = false }
5555
web3 = { version = "0.19.0", default-features = false }

crates/alerter/src/lib.rs

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -378,11 +378,19 @@ struct Arguments {
378378

379379
#[clap(long, env)]
380380
zero_ex_api_key: String,
381+
382+
/// Whether to use JSON format for the logs.
383+
#[clap(long, env, default_value = "false")]
384+
pub use_json_logs: bool,
381385
}
382386

383387
pub async fn start(args: impl Iterator<Item = String>) {
384388
let args = Arguments::parse_from(args);
385-
observe::tracing::initialize("alerter=debug", tracing::Level::ERROR.into());
389+
observe::tracing::initialize(
390+
"alerter=debug",
391+
tracing::Level::ERROR.into(),
392+
args.use_json_logs,
393+
);
386394
observe::panic_hook::install();
387395
observe::metrics::setup_registry(Some("gp_v2_alerter".to_string()), None);
388396
tracing::info!("running alerter with {:#?}", args);

crates/autopilot/src/run.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -122,6 +122,7 @@ pub async fn start(args: impl Iterator<Item = String>) {
122122
observe::tracing::initialize(
123123
args.shared.logging.log_filter.as_str(),
124124
args.shared.logging.log_stderr_threshold,
125+
args.shared.logging.use_json_logs,
125126
);
126127
observe::panic_hook::install();
127128
tracing::info!("running autopilot with validated arguments:\n{}", args);

crates/driver/src/infra/cli.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,10 @@ pub struct Args {
1717
)]
1818
pub log: String,
1919

20+
/// Whether to use JSON format for the logs.
21+
#[clap(long, env, default_value = "false")]
22+
pub use_json_logs: bool,
23+
2024
/// The node RPC API endpoint.
2125
#[clap(long, env)]
2226
pub ethrpc: Url,

crates/driver/src/infra/observe/mod.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -32,8 +32,8 @@ pub mod metrics;
3232

3333
/// Setup the observability. The log argument configures the tokio tracing
3434
/// framework.
35-
pub fn init(log: &str) {
36-
observe::tracing::initialize_reentrant(log);
35+
pub fn init(log: &str, use_json_format: bool) {
36+
observe::tracing::initialize_reentrant(log, use_json_format);
3737
metrics::init();
3838
}
3939

crates/driver/src/run.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ pub async fn run(
4545
/// Run the driver. This function exists to avoid multiple monomorphizations of
4646
/// the `run` code, which bloats the binaries and increases compile times.
4747
async fn run_with(args: cli::Args, addr_sender: Option<oneshot::Sender<SocketAddr>>) {
48-
crate::infra::observe::init(&args.log);
48+
crate::infra::observe::init(&args.log, args.use_json_logs);
4949

5050
let ethrpc = ethrpc(&args).await;
5151
let web3 = ethrpc.web3().clone();

crates/driver/src/tests/setup/mod.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -888,6 +888,7 @@ impl Setup {
888888
pub async fn done(self) -> Test {
889889
observe::tracing::initialize_reentrant(
890890
"driver=trace,driver::tests::setup::blockchain=debug,warn",
891+
false,
891892
);
892893

893894
if let Some(name) = self.name.as_ref() {

crates/e2e/src/setup/mod.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -183,7 +183,7 @@ async fn run<F, Fut, T>(
183183
Fut: Future<Output = ()>,
184184
T: AsRef<str>,
185185
{
186-
observe::tracing::initialize_reentrant(&with_default_filters(filters).join(","));
186+
observe::tracing::initialize_reentrant(&with_default_filters(filters).join(","), false);
187187
observe::panic_hook::install();
188188

189189
// The mutex guarantees that no more than a test at a time is running on

crates/ethrpc/src/block_stream/mod.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -387,7 +387,7 @@ mod tests {
387387
#[tokio::test]
388388
#[ignore]
389389
async fn mainnet() {
390-
observe::tracing::initialize_reentrant("shared=debug");
390+
observe::tracing::initialize_reentrant("shared=debug", false);
391391
let node = std::env::var("NODE_URL").unwrap().parse().unwrap();
392392
let receiver = current_block_stream(node, Duration::from_secs(1))
393393
.await

0 commit comments

Comments
 (0)