From c0815cdaf878afcd9c41dddd9fe56bcf8d910633 Mon Sep 17 00:00:00 2001 From: Igor Aleksanov Date: Fri, 26 Jul 2024 12:07:39 +0400 Subject: [PATCH] feat(vlog): New vlog interface + opentelemtry improvements (#2472) OK, that's a big PR for its purpose, sorry for that. Essence of changes: ## Nice observability installation from the config We can now write the following: ``` let observability_config = configs .observability .clone() .context("observability config")?; let _observability_guard = observability_config.install()?; ``` instead of having to manually map data from `observability_config` to `ObservabilityBuilder` methods. This is done in a non-intrusive way: the functionality is under a feature flag in `zksync_config` which is only enabled for binaries. ## Nicer `ObservabilityBuilder` interface Previously we've had "everything in one place", now we have separate structures for logs, opentelemetry, and sentry. It would be nice to integrate prometheus there too, but it's a separate task. ## More service information is exposed via opentelemetry Previously only service name was exposed. Now we also expose pod name and namespace. It's done in a non-intrusive way as well, where you can provide _some_ of information if you have it, but otherwise it'll be populated from env variables (which is fine, because it's not a permanent configuration, but rather a machine descriptor). --- Cargo.lock | 360 ++++++++------- Cargo.toml | 10 +- core/bin/block_reverter/Cargo.toml | 2 +- core/bin/block_reverter/src/main.rs | 26 +- core/bin/contract-verifier/Cargo.toml | 2 +- core/bin/contract-verifier/src/main.rs | 19 +- .../external_node/src/config/observability.rs | 36 +- core/bin/external_node/src/config/tests.rs | 6 +- core/bin/external_node/src/main.rs | 4 +- core/bin/external_node/src/node_builder.rs | 10 +- core/bin/external_node/src/tests/mod.rs | 8 +- .../Cargo.toml | 2 +- .../src/main.rs | 13 +- core/bin/snapshots_creator/Cargo.toml | 2 +- core/bin/snapshots_creator/src/main.rs | 14 +- core/bin/zksync_server/Cargo.toml | 2 +- core/bin/zksync_server/src/main.rs | 42 +- core/bin/zksync_server/src/node_builder.rs | 16 +- core/bin/zksync_tee_prover/Cargo.toml | 2 +- core/bin/zksync_tee_prover/src/main.rs | 21 +- core/lib/config/Cargo.toml | 5 + core/lib/config/src/configs/observability.rs | 2 +- core/lib/config/src/lib.rs | 3 + core/lib/config/src/observability_ext.rs | 52 +++ core/lib/utils/src/wait_for_tasks.rs | 10 +- core/lib/vlog/Cargo.toml | 6 +- core/lib/vlog/src/lib.rs | 376 ++-------------- core/lib/vlog/src/logs/layer.rs | 140 ++++++ core/lib/vlog/src/logs/mod.rs | 163 +++++++ core/lib/vlog/src/opentelemetry/mod.rs | 191 ++++++++ core/lib/vlog/src/sentry.rs | 38 ++ .../node/node_framework/examples/main_node.rs | 419 ------------------ core/node/node_framework/examples/showcase.rs | 10 +- core/node/node_framework/src/service/mod.rs | 50 ++- core/node/node_framework/src/service/tests.rs | 20 +- core/tests/loadnext/src/main.rs | 25 +- etc/env/file_based/general.yaml | 17 +- prover/Cargo.lock | 216 ++++----- .../bin/proof_fri_compressor/Cargo.toml | 1 + .../bin/proof_fri_compressor/src/main.rs | 23 +- prover/crates/bin/prover_fri/Cargo.toml | 2 +- prover/crates/bin/prover_fri/src/main.rs | 31 +- .../crates/bin/prover_fri_gateway/Cargo.toml | 2 +- .../crates/bin/prover_fri_gateway/src/main.rs | 15 +- .../crates/bin/witness_generator/Cargo.toml | 2 +- .../crates/bin/witness_generator/src/main.rs | 30 +- .../bin/witness_vector_generator/Cargo.toml | 2 +- .../bin/witness_vector_generator/src/main.rs | 23 +- zk_toolbox/Cargo.lock | 243 +++++----- 49 files changed, 1204 insertions(+), 1510 deletions(-) create mode 100644 core/lib/config/src/observability_ext.rs create mode 100644 core/lib/vlog/src/logs/layer.rs create mode 100644 core/lib/vlog/src/logs/mod.rs create mode 100644 core/lib/vlog/src/opentelemetry/mod.rs create mode 100644 core/lib/vlog/src/sentry.rs delete mode 100644 core/node/node_framework/examples/main_node.rs diff --git a/Cargo.lock b/Cargo.lock index a2cf9e4fde0c..3cdfe491c993 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -342,34 +342,6 @@ dependencies = [ "paste", ] -[[package]] -name = "axum" -version = "0.6.20" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3b829e4e32b91e643de6eafe82b1d90675f5874230191a4ffbc1b336dec4d6bf" -dependencies = [ - "async-trait", - "axum-core 0.3.4", - "bitflags 1.3.2", - "bytes", - "futures-util", - "http 0.2.9", - "http-body 0.4.6", - "hyper 0.14.29", - "itoa", - "matchit", - "memchr", - "mime", - "percent-encoding", - "pin-project-lite", - "rustversion", - "serde", - "sync_wrapper 0.1.2", - "tower", - "tower-layer", - "tower-service", -] - [[package]] name = "axum" version = "0.7.5" @@ -377,7 +349,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3a6c9af12842a67734c9a2e355436e5d03b22383ed60cf13cd0c18fbfe3dcbcf" dependencies = [ "async-trait", - "axum-core 0.4.3", + "axum-core", "bytes", "futures-util", "http 1.1.0", @@ -404,23 +376,6 @@ dependencies = [ "tracing", ] -[[package]] -name = "axum-core" -version = "0.3.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "759fa577a247914fd3f7f76d62972792636412fbfd634cd452f6a385a74d2d2c" -dependencies = [ - "async-trait", - "bytes", - "futures-util", - "http 0.2.9", - "http-body 0.4.6", - "mime", - "rustversion", - "tower-layer", - "tower-service", -] - [[package]] name = "axum-core" version = "0.4.3" @@ -2763,9 +2718,9 @@ dependencies = [ [[package]] name = "hermit-abi" -version = "0.3.3" +version = "0.3.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d77f7ec81a6d05a3abb01ab6eb7590f6083d08449fe5a1c8b1e620283546ccb7" +checksum = "d231dfb89cfffdbc30e7fc41579ed6066ad03abda9e567ccafae602b97ec5024" [[package]] name = "hex" @@ -2944,14 +2899,15 @@ dependencies = [ [[package]] name = "hyper-timeout" -version = "0.4.1" +version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bbb958482e8c7be4bc3cf272a766a2b0bf1a6755e7a6ae777f017a31d11b13b1" +checksum = "3203a961e5c83b6f5498933e78b6b263e208c197b63e9c6c53cc82ffd3f63793" dependencies = [ - "hyper 0.14.29", + "hyper 1.3.1", + "hyper-util", "pin-project-lite", "tokio", - "tokio-io-timeout", + "tower-service", ] [[package]] @@ -3810,13 +3766,14 @@ dependencies = [ [[package]] name = "mio" -version = "0.8.11" +version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a4a650543ca06a924e8b371db273b2756685faae30f8487da1b56505a8f78b0c" +checksum = "4569e456d394deccd22ce1c1913e6ea0e54519f577285001215d33557431afe4" dependencies = [ + "hermit-abi 0.3.9", "libc", "wasi 0.11.0+wasi-snapshot-preview1", - "windows-sys 0.48.0", + "windows-sys 0.52.0", ] [[package]] @@ -3961,6 +3918,12 @@ dependencies = [ "serde", ] +[[package]] +name = "num-conv" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "51d515d32fb182ee37cda2ccdcb92950d6a3c2893aa280e540671c2cd0f3b1d9" + [[package]] name = "num-derive" version = "0.2.5" @@ -4030,7 +3993,7 @@ version = "1.16.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4161fcb6d602d4d2081af7c3a45852d875a03dd337a6bfdd6e06407b61342a43" dependencies = [ - "hermit-abi 0.3.3", + "hermit-abi 0.3.9", "libc", ] @@ -4149,43 +4112,46 @@ dependencies = [ [[package]] name = "opentelemetry" -version = "0.20.0" +version = "0.24.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9591d937bc0e6d2feb6f71a559540ab300ea49955229c347a517a28d27784c54" +checksum = "4c365a63eec4f55b7efeceb724f1336f26a9cf3427b70e59e2cd2a5b947fba96" dependencies = [ - "opentelemetry_api", - "opentelemetry_sdk", + "futures-core", + "futures-sink", + "js-sys", + "once_cell", + "pin-project-lite", + "thiserror", ] [[package]] name = "opentelemetry-http" -version = "0.9.0" +version = "0.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c7594ec0e11d8e33faf03530a4c49af7064ebba81c1480e01be67d90b356508b" +checksum = "ad31e9de44ee3538fb9d64fe3376c1362f406162434609e79aea2a41a0af78ab" dependencies = [ "async-trait", "bytes", - "http 0.2.9", - "opentelemetry_api", - "reqwest 0.11.22", + "http 1.1.0", + "opentelemetry", + "reqwest 0.12.5", ] [[package]] name = "opentelemetry-otlp" -version = "0.13.0" +version = "0.17.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7e5e5a5c4135864099f3faafbe939eb4d7f9b80ebf68a8448da961b32a7c1275" +checksum = "6b925a602ffb916fb7421276b86756027b37ee708f9dce2dbdcc51739f07e727" dependencies = [ "async-trait", "futures-core", - "http 0.2.9", + "http 1.1.0", + "opentelemetry", "opentelemetry-http", "opentelemetry-proto", - "opentelemetry-semantic-conventions", - "opentelemetry_api", "opentelemetry_sdk", - "prost 0.11.9", - "reqwest 0.11.22", + "prost 0.13.1", + "reqwest 0.12.5", "thiserror", "tokio", "tonic", @@ -4193,58 +4159,37 @@ dependencies = [ [[package]] name = "opentelemetry-proto" -version = "0.3.0" +version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b1e3f814aa9f8c905d0ee4bde026afd3b2577a97c10e1699912e3e44f0c4cbeb" +checksum = "30ee9f20bff9c984511a02f082dc8ede839e4a9bf15cc2487c8d6fea5ad850d9" dependencies = [ - "opentelemetry_api", + "opentelemetry", "opentelemetry_sdk", - "prost 0.11.9", + "prost 0.13.1", "tonic", ] [[package]] name = "opentelemetry-semantic-conventions" -version = "0.12.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "73c9f9340ad135068800e7f1b24e9e09ed9e7143f5bf8518ded3d3ec69789269" -dependencies = [ - "opentelemetry", -] - -[[package]] -name = "opentelemetry_api" -version = "0.20.0" +version = "0.16.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8a81f725323db1b1206ca3da8bb19874bbd3f57c3bcd59471bfb04525b265b9b" -dependencies = [ - "futures-channel", - "futures-util", - "indexmap 1.9.3", - "js-sys", - "once_cell", - "pin-project-lite", - "thiserror", - "urlencoding", -] +checksum = "1cefe0543875379e47eb5f1e68ff83f45cc41366a92dfd0d073d513bf68e9a05" [[package]] name = "opentelemetry_sdk" -version = "0.20.0" +version = "0.24.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fa8e705a0612d48139799fcbaba0d4a90f06277153e43dd2bdc16c6f0edd8026" +checksum = "692eac490ec80f24a17828d49b40b60f5aeaccdfe6a503f939713afd22bc28df" dependencies = [ "async-trait", - "crossbeam-channel 0.5.13", "futures-channel", "futures-executor", "futures-util", + "glob", "once_cell", - "opentelemetry_api", - "ordered-float 3.9.2", + "opentelemetry", "percent-encoding", "rand 0.8.5", - "regex", "serde_json", "thiserror", "tokio", @@ -4260,15 +4205,6 @@ dependencies = [ "num-traits", ] -[[package]] -name = "ordered-float" -version = "3.9.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f1e1c390732d15f1d48471625cd92d154e66db2c56645e29a9cd26f4699f72dc" -dependencies = [ - "num-traits", -] - [[package]] name = "os_info" version = "3.7.0" @@ -4733,22 +4669,22 @@ dependencies = [ [[package]] name = "prost" -version = "0.11.9" +version = "0.12.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0b82eaa1d779e9a4bc1c3217db8ffbeabaae1dca241bf70183242128d48681cd" +checksum = "f4fdd22f3b9c31b53c060df4a0613a1c7f062d4115a2b984dd15b1858f7e340d" dependencies = [ "bytes", - "prost-derive 0.11.9", + "prost-derive 0.12.1", ] [[package]] name = "prost" -version = "0.12.1" +version = "0.13.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f4fdd22f3b9c31b53c060df4a0613a1c7f062d4115a2b984dd15b1858f7e340d" +checksum = "e13db3d3fde688c61e2446b4d843bc27a7e8af269a69440c0308021dc92333cc" dependencies = [ "bytes", - "prost-derive 0.12.1", + "prost-derive 0.13.1", ] [[package]] @@ -4775,25 +4711,25 @@ dependencies = [ [[package]] name = "prost-derive" -version = "0.11.9" +version = "0.12.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e5d2d8d10f3c6ded6da8b05b5fb3b8a5082514344d56c9f871412d29b4e075b4" +checksum = "265baba7fabd416cf5078179f7d2cbeca4ce7a9041111900675ea7c4cb8a4c32" dependencies = [ "anyhow", - "itertools 0.10.5", + "itertools 0.11.0", "proc-macro2 1.0.69", "quote 1.0.33", - "syn 1.0.109", + "syn 2.0.38", ] [[package]] name = "prost-derive" -version = "0.12.1" +version = "0.13.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "265baba7fabd416cf5078179f7d2cbeca4ce7a9041111900675ea7c4cb8a4c32" +checksum = "18bec9b0adc4eba778b33684b7ba3e7137789434769ee3ce3930463ef904cfca" dependencies = [ "anyhow", - "itertools 0.11.0", + "itertools 0.12.0", "proc-macro2 1.0.69", "quote 1.0.33", "syn 2.0.38", @@ -5749,7 +5685,7 @@ version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f3a1a3341211875ef120e117ea7fd5228530ae7e7036a779fdc9117be6b3282c" dependencies = [ - "ordered-float 2.10.1", + "ordered-float", "serde", ] @@ -6673,12 +6609,13 @@ dependencies = [ [[package]] name = "time" -version = "0.3.30" +version = "0.3.36" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c4a34ab300f2dee6e562c10a046fc05e358b29f9bf92277f30c3c8d82275f6f5" +checksum = "5dfd88e563464686c916c7e46e623e520ddc6d79fa6641390f2e3fa86e83e885" dependencies = [ "deranged", "itoa", + "num-conv", "powerfmt", "serde", "time-core", @@ -6693,10 +6630,11 @@ checksum = "ef927ca75afb808a4d64dd374f00a2adf8d0fcff8e7b184af886c3c87ec4a3f3" [[package]] name = "time-macros" -version = "0.2.15" +version = "0.2.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4ad70d68dba9e1f8aceda7aa6711965dfec1cac869f311a51bd08b3a2ccbce20" +checksum = "3f252a68540fde3a3877aeea552b832b40ab9a69e318efd078774a01ddee1ccf" dependencies = [ + "num-conv", "time-core", ] @@ -6758,38 +6696,27 @@ dependencies = [ [[package]] name = "tokio" -version = "1.34.0" +version = "1.39.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d0c014766411e834f7af5b8f4cf46257aab4036ca95e9d2c144a10f59ad6f5b9" +checksum = "d040ac2b29ab03b09d4129c2f5bbd012a3ac2f79d38ff506a4bf8dd34b0eac8a" dependencies = [ "backtrace", "bytes", "libc", "mio", - "num_cpus", "parking_lot", "pin-project-lite", "signal-hook-registry", "socket2", "tokio-macros", - "windows-sys 0.48.0", -] - -[[package]] -name = "tokio-io-timeout" -version = "1.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "30b74022ada614a1b4834de765f9bb43877f910cc8ce4be40e89042c9223a8bf" -dependencies = [ - "pin-project-lite", - "tokio", + "windows-sys 0.52.0", ] [[package]] name = "tokio-macros" -version = "2.2.0" +version = "2.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b8a1e28f2deaa14e508979454cb3a223b10b938b45af148bc0986de36f1923b" +checksum = "693d596312e88961bc67d7f1f97af8a70227d9f90c31bba5806eec004978d752" dependencies = [ "proc-macro2 1.0.69", "quote 1.0.33", @@ -6885,24 +6812,26 @@ dependencies = [ [[package]] name = "tonic" -version = "0.9.2" +version = "0.12.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3082666a3a6433f7f511c7192923fa1fe07c69332d3c6a2e6bb040b569199d5a" +checksum = "38659f4a91aba8598d27821589f5db7dddd94601e7a01b1e485a50e5484c7401" dependencies = [ + "async-stream", "async-trait", - "axum 0.6.20", - "base64 0.21.5", + "axum", + "base64 0.22.1", "bytes", - "futures-core", - "futures-util", - "h2 0.3.26", - "http 0.2.9", - "http-body 0.4.6", - "hyper 0.14.29", + "h2 0.4.5", + "http 1.1.0", + "http-body 1.0.0", + "http-body-util", + "hyper 1.3.1", "hyper-timeout", + "hyper-util", "percent-encoding", "pin-project", - "prost 0.11.9", + "prost 0.13.1", + "socket2", "tokio", "tokio-stream", "tower", @@ -7004,20 +6933,33 @@ dependencies = [ "tracing-core", ] +[[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-opentelemetry" -version = "0.21.0" +version = "0.25.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "75327c6b667828ddc28f5e3f169036cb793c3f588d83bf0f262a7f062ffed3c8" +checksum = "a9784ed4da7d921bc8df6963f8c80a0e4ce34ba6ba76668acadd3edbd985ff3b" dependencies = [ + "js-sys", "once_cell", "opentelemetry", "opentelemetry_sdk", "smallvec", "tracing", "tracing-core", - "tracing-log", + "tracing-log 0.2.0", "tracing-subscriber", + "web-time", ] [[package]] @@ -7048,7 +6990,7 @@ dependencies = [ "time", "tracing", "tracing-core", - "tracing-log", + "tracing-log 0.1.4", "tracing-serde", ] @@ -7463,6 +7405,16 @@ dependencies = [ "wasm-bindgen", ] +[[package]] +name = "web-time" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5a6580f308b1fad9207618087a65c04e7a10bc77e02c8e84e9b00dd4b12fa0bb" +dependencies = [ + "js-sys", + "wasm-bindgen", +] + [[package]] name = "webpki-roots" version = "0.26.0" @@ -7552,6 +7504,15 @@ dependencies = [ "windows-targets 0.48.5", ] +[[package]] +name = "windows-sys" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" +dependencies = [ + "windows-targets 0.52.6", +] + [[package]] name = "windows-targets" version = "0.42.2" @@ -7582,6 +7543,22 @@ dependencies = [ "windows_x86_64_msvc 0.48.5", ] +[[package]] +name = "windows-targets" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973" +dependencies = [ + "windows_aarch64_gnullvm 0.52.6", + "windows_aarch64_msvc 0.52.6", + "windows_i686_gnu 0.52.6", + "windows_i686_gnullvm", + "windows_i686_msvc 0.52.6", + "windows_x86_64_gnu 0.52.6", + "windows_x86_64_gnullvm 0.52.6", + "windows_x86_64_msvc 0.52.6", +] + [[package]] name = "windows_aarch64_gnullvm" version = "0.42.2" @@ -7594,6 +7571,12 @@ version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8" +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" + [[package]] name = "windows_aarch64_msvc" version = "0.42.2" @@ -7606,6 +7589,12 @@ version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc" +[[package]] +name = "windows_aarch64_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" + [[package]] name = "windows_i686_gnu" version = "0.42.2" @@ -7618,6 +7607,18 @@ version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e" +[[package]] +name = "windows_i686_gnu" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b" + +[[package]] +name = "windows_i686_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" + [[package]] name = "windows_i686_msvc" version = "0.42.2" @@ -7630,6 +7631,12 @@ version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406" +[[package]] +name = "windows_i686_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" + [[package]] name = "windows_x86_64_gnu" version = "0.42.2" @@ -7642,6 +7649,12 @@ version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e" +[[package]] +name = "windows_x86_64_gnu" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" + [[package]] name = "windows_x86_64_gnullvm" version = "0.42.2" @@ -7654,6 +7667,12 @@ version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc" +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" + [[package]] name = "windows_x86_64_msvc" version = "0.42.2" @@ -7666,6 +7685,12 @@ version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538" +[[package]] +name = "windows_x86_64_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" + [[package]] name = "winnow" version = "0.5.17" @@ -8140,6 +8165,7 @@ dependencies = [ "zksync_concurrency", "zksync_consensus_utils", "zksync_crypto_primitives", + "zksync_vlog", ] [[package]] @@ -8328,7 +8354,7 @@ name = "zksync_contract_verification_server" version = "0.1.0" dependencies = [ "anyhow", - "axum 0.7.5", + "axum", "serde", "serde_json", "tokio", @@ -8809,7 +8835,7 @@ dependencies = [ "anyhow", "assert_matches", "async-trait", - "axum 0.7.5", + "axum", "futures 0.3.28", "itertools 0.10.5", "once_cell", @@ -8887,7 +8913,7 @@ dependencies = [ "anyhow", "assert_matches", "async-trait", - "axum 0.7.5", + "axum", "chrono", "futures 0.3.28", "governor", @@ -9204,7 +9230,7 @@ name = "zksync_proof_data_handler" version = "0.1.0" dependencies = [ "anyhow", - "axum 0.7.5", + "axum", "chrono", "hyper 1.3.1", "serde_json", @@ -9656,13 +9682,17 @@ dependencies = [ "opentelemetry", "opentelemetry-otlp", "opentelemetry-semantic-conventions", + "opentelemetry_sdk", "sentry", "serde", "serde_json", + "thiserror", + "time", "tokio", "tracing", "tracing-opentelemetry", "tracing-subscriber", + "url", "vise", "vise-exporter", ] diff --git a/Cargo.toml b/Cargo.toml index 7b6ac30be8f1..49b2cc50c567 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -139,9 +139,10 @@ num = "0.4.0" num_cpus = "1.13" num_enum = "0.7.2" once_cell = "1" -opentelemetry = "0.20.0" -opentelemetry-otlp = "0.13.0" -opentelemetry-semantic-conventions = "0.12.0" +opentelemetry = "0.24.0" +opentelemetry_sdk = "0.24.0" +opentelemetry-otlp = "0.17.0" +opentelemetry-semantic-conventions = "0.16.0" pin-project-lite = "0.2.13" pretty_assertions = "1" prost = "0.12.1" @@ -179,7 +180,8 @@ tower = "0.4.13" tower-http = "0.5.2" tracing = "0.1" tracing-subscriber = "0.3" -tracing-opentelemetry = "0.21.0" +tracing-opentelemetry = "0.25.0" +time = "0.3.36" # Has to be same as used by `tracing-subscriber` url = "2" web3 = "0.19.0" fraction = "0.15.3" diff --git a/core/bin/block_reverter/Cargo.toml b/core/bin/block_reverter/Cargo.toml index 9ac7a49335c4..2144fcffdddd 100644 --- a/core/bin/block_reverter/Cargo.toml +++ b/core/bin/block_reverter/Cargo.toml @@ -12,7 +12,7 @@ categories.workspace = true publish = false [dependencies] -zksync_config.workspace = true +zksync_config = { workspace = true, features = ["observability_ext"] } zksync_core_leftovers.workspace = true zksync_env_config.workspace = true zksync_dal.workspace = true diff --git a/core/bin/block_reverter/src/main.rs b/core/bin/block_reverter/src/main.rs index 513de522aa40..1be006cfb3d1 100644 --- a/core/bin/block_reverter/src/main.rs +++ b/core/bin/block_reverter/src/main.rs @@ -106,21 +106,19 @@ async fn main() -> anyhow::Result<()> { let opts = Cli::parse(); let observability_config = ObservabilityConfig::from_env().context("ObservabilityConfig::from_env()")?; - let log_format: zksync_vlog::LogFormat = observability_config - .log_format - .parse() - .context("Invalid log format")?; - let mut builder = zksync_vlog::ObservabilityBuilder::new() - .with_log_format(log_format) - .disable_default_logs(); // It's a CLI application, so we only need to show logs that were actually requested. - if let Some(sentry_url) = observability_config.sentry_url { - builder = builder - .with_sentry_url(&sentry_url) - .context("Invalid Sentry URL")? - .with_sentry_environment(observability_config.sentry_environment); - } - let _guard = builder.build(); + let logs = zksync_vlog::Logs::try_from(observability_config.clone()) + .context("logs")? + .disable_default_logs(); // It's a CLI application, so we only need to show logs that were actually requested.; + let sentry: Option = + TryFrom::try_from(observability_config.clone()).context("sentry")?; + let opentelemetry: Option = + TryFrom::try_from(observability_config.clone()).context("opentelemetry")?; + let _guard = zksync_vlog::ObservabilityBuilder::new() + .with_logs(Some(logs)) + .with_sentry(sentry) + .with_opentelemetry(opentelemetry) + .build(); let general_config: Option = if let Some(path) = opts.config_path { let yaml = std::fs::read_to_string(&path).with_context(|| path.display().to_string())?; diff --git a/core/bin/contract-verifier/Cargo.toml b/core/bin/contract-verifier/Cargo.toml index d57b44f046cc..f088c2337e71 100644 --- a/core/bin/contract-verifier/Cargo.toml +++ b/core/bin/contract-verifier/Cargo.toml @@ -13,7 +13,7 @@ publish = false [dependencies] zksync_dal.workspace = true zksync_env_config.workspace = true -zksync_config.workspace = true +zksync_config = { workspace = true, features = ["observability_ext"] } zksync_contract_verifier_lib.workspace = true zksync_queued_job_processor.workspace = true zksync_utils.workspace = true diff --git a/core/bin/contract-verifier/src/main.rs b/core/bin/contract-verifier/src/main.rs index fe33a34a7583..36640049e446 100644 --- a/core/bin/contract-verifier/src/main.rs +++ b/core/bin/contract-verifier/src/main.rs @@ -146,25 +146,8 @@ async fn main() -> anyhow::Result<()> { let observability_config = general_config .observability .context("ObservabilityConfig")?; - let log_format: zksync_vlog::LogFormat = observability_config - .log_format - .parse() - .context("Invalid log format")?; - let mut builder = zksync_vlog::ObservabilityBuilder::new().with_log_format(log_format); - if let Some(sentry_url) = &observability_config.sentry_url { - builder = builder - .with_sentry_url(sentry_url) - .expect("Invalid Sentry URL") - .with_sentry_environment(observability_config.sentry_environment); - } - let _guard = builder.build(); - // Report whether sentry is running after the logging subsystem was initialized. - if let Some(sentry_url) = observability_config.sentry_url { - tracing::info!("Sentry configured with URL: {sentry_url}"); - } else { - tracing::info!("No sentry URL was provided"); - } + let _observability_guard = observability_config.install()?; let (stop_sender, stop_receiver) = watch::channel(false); let (stop_signal_sender, mut stop_signal_receiver) = mpsc::channel(256); diff --git a/core/bin/external_node/src/config/observability.rs b/core/bin/external_node/src/config/observability.rs index 4cd4efe0df04..0dd83f3bd35b 100644 --- a/core/bin/external_node/src/config/observability.rs +++ b/core/bin/external_node/src/config/observability.rs @@ -3,7 +3,7 @@ use std::{collections::HashMap, time::Duration}; use anyhow::Context as _; use serde::Deserialize; use zksync_config::configs::GeneralConfig; -use zksync_vlog::{prometheus::PrometheusExporterConfig, LogFormat}; +use zksync_vlog::{logs::LogFormat, prometheus::PrometheusExporterConfig}; use super::{ConfigurationSource, Environment}; @@ -81,26 +81,24 @@ impl ObservabilityENConfig { } pub fn build_observability(&self) -> anyhow::Result { - let mut builder = zksync_vlog::ObservabilityBuilder::new().with_log_format(self.log_format); - if let Some(log_directives) = self.log_directives.clone() { - builder = builder.with_log_directives(log_directives) - }; + let logs = zksync_vlog::Logs::from(self.log_format) + .with_log_directives(self.log_directives.clone()); + // Some legacy deployments use `unset` as an equivalent of `None`. let sentry_url = self.sentry_url.as_deref().filter(|&url| url != "unset"); - if let Some(sentry_url) = sentry_url { - builder = builder - .with_sentry_url(sentry_url) - .context("Invalid Sentry URL")? - .with_sentry_environment(self.sentry_environment.clone()); - } - let guard = builder.build(); - - // Report whether sentry is running after the logging subsystem was initialized. - if let Some(sentry_url) = sentry_url { - tracing::info!("Sentry configured with URL: {sentry_url}"); - } else { - tracing::info!("No sentry URL was provided"); - } + let sentry = sentry_url + .map(|url| { + anyhow::Ok( + zksync_vlog::Sentry::new(url) + .context("Invalid Sentry URL")? + .with_environment(self.sentry_environment.clone()), + ) + }) + .transpose()?; + let guard = zksync_vlog::ObservabilityBuilder::new() + .with_logs(Some(logs)) + .with_sentry(sentry) + .build(); Ok(guard) } diff --git a/core/bin/external_node/src/config/tests.rs b/core/bin/external_node/src/config/tests.rs index 1b42b98a32a4..43210a765723 100644 --- a/core/bin/external_node/src/config/tests.rs +++ b/core/bin/external_node/src/config/tests.rs @@ -42,12 +42,12 @@ fn parsing_observability_config() { assert_eq!(config.prometheus_port, Some(3322)); assert_eq!(config.sentry_url.unwrap(), "https://example.com/"); assert_eq!(config.sentry_environment.unwrap(), "mainnet - mainnet2"); - assert_matches!(config.log_format, zksync_vlog::LogFormat::Plain); + assert_matches!(config.log_format, zksync_vlog::logs::LogFormat::Plain); assert_eq!(config.prometheus_push_interval_ms, 10_000); env_vars.0.insert("MISC_LOG_FORMAT", "json"); let config = ObservabilityENConfig::new(&env_vars).unwrap(); - assert_matches!(config.log_format, zksync_vlog::LogFormat::Json); + assert_matches!(config.log_format, zksync_vlog::logs::LogFormat::Json); // If both the canonical and obsolete vars are specified, the canonical one should prevail. env_vars.0.insert("EN_LOG_FORMAT", "plain"); @@ -55,7 +55,7 @@ fn parsing_observability_config() { .0 .insert("EN_SENTRY_URL", "https://example.com/new"); let config = ObservabilityENConfig::new(&env_vars).unwrap(); - assert_matches!(config.log_format, zksync_vlog::LogFormat::Plain); + assert_matches!(config.log_format, zksync_vlog::logs::LogFormat::Plain); assert_eq!(config.sentry_url.unwrap(), "https://example.com/new"); } diff --git a/core/bin/external_node/src/main.rs b/core/bin/external_node/src/main.rs index f6696d733482..00ce3cc71e87 100644 --- a/core/bin/external_node/src/main.rs +++ b/core/bin/external_node/src/main.rs @@ -824,6 +824,8 @@ async fn main() -> anyhow::Result<()> { if !opt.enable_consensus { config.consensus = None; } + // Note: when old code will be removed, observability must be build within + // tokio context. let _guard = config.observability.build_observability()?; // Build L1 and L2 clients. @@ -856,7 +858,7 @@ async fn main() -> anyhow::Result<()> { // We run the node from a different thread, since the current thread is in tokio context. std::thread::spawn(move || { let node = - ExternalNodeBuilder::new(config).build(opt.components.0.into_iter().collect())?; + ExternalNodeBuilder::new(config)?.build(opt.components.0.into_iter().collect())?; node.run()?; anyhow::Ok(()) }) diff --git a/core/bin/external_node/src/node_builder.rs b/core/bin/external_node/src/node_builder.rs index ff851999f623..d9e216c84dd2 100644 --- a/core/bin/external_node/src/node_builder.rs +++ b/core/bin/external_node/src/node_builder.rs @@ -69,11 +69,11 @@ pub(crate) struct ExternalNodeBuilder { } impl ExternalNodeBuilder { - pub fn new(config: ExternalNodeConfig) -> Self { - Self { - node: ZkStackServiceBuilder::new(), + pub fn new(config: ExternalNodeConfig) -> anyhow::Result { + Ok(Self { + node: ZkStackServiceBuilder::new().context("Cannot create ZkStackServiceBuilder")?, config, - } + }) } fn add_sigint_handler_layer(mut self) -> anyhow::Result { @@ -587,7 +587,7 @@ impl ExternalNodeBuilder { } } - Ok(self.node.build()?) + Ok(self.node.build()) } } diff --git a/core/bin/external_node/src/tests/mod.rs b/core/bin/external_node/src/tests/mod.rs index e2b7edc174c4..2adf336728f0 100644 --- a/core/bin/external_node/src/tests/mod.rs +++ b/core/bin/external_node/src/tests/mod.rs @@ -28,7 +28,7 @@ async fn external_node_basics(components_str: &'static str) { let node_handle = tokio::task::spawn_blocking(move || { std::thread::spawn(move || { - let mut node = ExternalNodeBuilder::new(env.config); + let mut node = ExternalNodeBuilder::new(env.config)?; inject_test_layers( &mut node, env.sigint_receiver, @@ -97,7 +97,7 @@ async fn node_reacts_to_stop_signal_during_initial_reorg_detection() { let mut node_handle = tokio::task::spawn_blocking(move || { std::thread::spawn(move || { - let mut node = ExternalNodeBuilder::new(env.config); + let mut node = ExternalNodeBuilder::new(env.config)?; inject_test_layers( &mut node, env.sigint_receiver, @@ -133,7 +133,7 @@ async fn running_tree_without_core_is_not_allowed() { let node_handle = tokio::task::spawn_blocking(move || { std::thread::spawn(move || { - let mut node = ExternalNodeBuilder::new(env.config); + let mut node = ExternalNodeBuilder::new(env.config)?; inject_test_layers( &mut node, env.sigint_receiver, @@ -170,7 +170,7 @@ async fn running_tree_api_without_tree_is_not_allowed() { let node_handle = tokio::task::spawn_blocking(move || { std::thread::spawn(move || { - let mut node = ExternalNodeBuilder::new(env.config); + let mut node = ExternalNodeBuilder::new(env.config)?; inject_test_layers( &mut node, env.sigint_receiver, diff --git a/core/bin/merkle_tree_consistency_checker/Cargo.toml b/core/bin/merkle_tree_consistency_checker/Cargo.toml index 1399faec1d42..eb7dcd81a0dc 100644 --- a/core/bin/merkle_tree_consistency_checker/Cargo.toml +++ b/core/bin/merkle_tree_consistency_checker/Cargo.toml @@ -12,7 +12,7 @@ categories.workspace = true publish = false [dependencies] -zksync_config.workspace = true +zksync_config = { workspace = true, features = ["observability_ext"] } zksync_env_config.workspace = true zksync_merkle_tree.workspace = true zksync_types.workspace = true diff --git a/core/bin/merkle_tree_consistency_checker/src/main.rs b/core/bin/merkle_tree_consistency_checker/src/main.rs index f8584653681f..4218975e4865 100644 --- a/core/bin/merkle_tree_consistency_checker/src/main.rs +++ b/core/bin/merkle_tree_consistency_checker/src/main.rs @@ -54,18 +54,7 @@ impl Cli { fn main() -> anyhow::Result<()> { let observability_config = ObservabilityConfig::from_env().context("ObservabilityConfig::from_env()")?; - let log_format: zksync_vlog::LogFormat = observability_config - .log_format - .parse() - .context("Invalid log format")?; - let mut builder = zksync_vlog::ObservabilityBuilder::new().with_log_format(log_format); - if let Some(sentry_url) = observability_config.sentry_url { - builder = builder - .with_sentry_url(&sentry_url) - .context("Invalid Sentry URL")? - .with_sentry_environment(observability_config.sentry_environment); - } - let _guard = builder.build(); + let _observability_guard = observability_config.install()?; let db_config = DBConfig::from_env().context("DBConfig::from_env()")?; Cli::parse().run(&db_config) diff --git a/core/bin/snapshots_creator/Cargo.toml b/core/bin/snapshots_creator/Cargo.toml index 33b1fa82a857..530b9635cd4f 100644 --- a/core/bin/snapshots_creator/Cargo.toml +++ b/core/bin/snapshots_creator/Cargo.toml @@ -13,7 +13,7 @@ publish = false [dependencies] vise.workspace = true -zksync_config.workspace = true +zksync_config = { workspace = true, features = ["observability_ext"] } zksync_dal.workspace = true zksync_env_config.workspace = true zksync_types.workspace = true diff --git a/core/bin/snapshots_creator/src/main.rs b/core/bin/snapshots_creator/src/main.rs index e07a879746ad..bfdc17fefcd5 100644 --- a/core/bin/snapshots_creator/src/main.rs +++ b/core/bin/snapshots_creator/src/main.rs @@ -70,21 +70,9 @@ async fn main() -> anyhow::Result<()> { let observability_config = general_config .observability .context("observability config")?; - let log_format: zksync_vlog::LogFormat = observability_config - .log_format - .parse() - .context("Invalid log format")?; - + let _observability_guard = observability_config.install()?; let prometheus_exporter_task = maybe_enable_prometheus_metrics(general_config.prometheus_config, stop_receiver).await?; - let mut builder = zksync_vlog::ObservabilityBuilder::new().with_log_format(log_format); - if let Some(sentry_url) = observability_config.sentry_url { - builder = builder - .with_sentry_url(&sentry_url) - .context("Invalid Sentry URL")? - .with_sentry_environment(observability_config.sentry_environment); - } - let _guard = builder.build(); tracing::info!("Starting snapshots creator"); let creator_config = general_config diff --git a/core/bin/zksync_server/Cargo.toml b/core/bin/zksync_server/Cargo.toml index 5470f24010c1..72eff1384e2d 100644 --- a/core/bin/zksync_server/Cargo.toml +++ b/core/bin/zksync_server/Cargo.toml @@ -12,7 +12,7 @@ categories.workspace = true publish = false [dependencies] -zksync_config.workspace = true +zksync_config = { workspace = true, features = ["observability_ext"] } zksync_env_config.workspace = true zksync_eth_client.workspace = true zksync_protobuf_config.workspace = true diff --git a/core/bin/zksync_server/src/main.rs b/core/bin/zksync_server/src/main.rs index a59705b8e587..93cabfdfe6d6 100644 --- a/core/bin/zksync_server/src/main.rs +++ b/core/bin/zksync_server/src/main.rs @@ -113,36 +113,6 @@ fn main() -> anyhow::Result<()> { } }; - let observability_config = configs - .observability - .clone() - .context("observability config")?; - - let log_format: zksync_vlog::LogFormat = observability_config - .log_format - .parse() - .context("Invalid log format")?; - - let mut builder = zksync_vlog::ObservabilityBuilder::new().with_log_format(log_format); - if let Some(log_directives) = observability_config.log_directives { - builder = builder.with_log_directives(log_directives); - } - - if let Some(sentry_url) = &observability_config.sentry_url { - builder = builder - .with_sentry_url(sentry_url) - .expect("Invalid Sentry URL") - .with_sentry_environment(observability_config.sentry_environment); - } - let _guard = builder.build(); - - // Report whether sentry is running after the logging subsystem was initialized. - if let Some(sentry_url) = observability_config.sentry_url { - tracing::info!("Sentry configured with URL: {sentry_url}"); - } else { - tracing::info!("No sentry URL was provided"); - } - let wallets = match opt.wallets_path { None => tmp_config.wallets(), Some(path) => { @@ -186,8 +156,18 @@ fn main() -> anyhow::Result<()> { .context("failed decoding genesis YAML config")? } }; + let observability_config = configs + .observability + .clone() + .context("observability config")?; - let node = MainNodeBuilder::new(configs, wallets, genesis, contracts_config, secrets); + let node = MainNodeBuilder::new(configs, wallets, genesis, contracts_config, secrets)?; + + let _observability_guard = { + // Observability initialization should be performed within tokio context. + let _context_guard = node.runtime_handle().enter(); + observability_config.install()? + }; if opt.genesis { // If genesis is requested, we don't need to run the node. diff --git a/core/bin/zksync_server/src/node_builder.rs b/core/bin/zksync_server/src/node_builder.rs index 0eaa9b651f64..3da14c920886 100644 --- a/core/bin/zksync_server/src/node_builder.rs +++ b/core/bin/zksync_server/src/node_builder.rs @@ -92,15 +92,19 @@ impl MainNodeBuilder { genesis_config: GenesisConfig, contracts_config: ContractsConfig, secrets: Secrets, - ) -> Self { - Self { - node: ZkStackServiceBuilder::new(), + ) -> anyhow::Result { + Ok(Self { + node: ZkStackServiceBuilder::new().context("Cannot create ZkStackServiceBuilder")?, configs, wallets, genesis_config, contracts_config, secrets, - } + }) + } + + pub fn runtime_handle(&self) -> tokio::runtime::Handle { + self.node.runtime_handle() } fn add_sigint_handler_layer(mut self) -> anyhow::Result { @@ -589,7 +593,7 @@ impl MainNodeBuilder { .add_query_eth_client_layer()? .add_storage_initialization_layer(LayerKind::Task)?; - Ok(self.node.build()?) + Ok(self.node.build()) } /// Builds the node with the specified components. @@ -701,7 +705,7 @@ impl MainNodeBuilder { } } } - Ok(self.node.build()?) + Ok(self.node.build()) } } diff --git a/core/bin/zksync_tee_prover/Cargo.toml b/core/bin/zksync_tee_prover/Cargo.toml index 037833b1890e..0c89971fd305 100644 --- a/core/bin/zksync_tee_prover/Cargo.toml +++ b/core/bin/zksync_tee_prover/Cargo.toml @@ -23,7 +23,7 @@ tracing.workspace = true url.workspace = true vise.workspace = true zksync_basic_types.workspace = true -zksync_config.workspace = true +zksync_config = { workspace = true, features = ["observability_ext"] } zksync_env_config.workspace = true zksync_node_framework.workspace = true zksync_prover_interface.workspace = true diff --git a/core/bin/zksync_tee_prover/src/main.rs b/core/bin/zksync_tee_prover/src/main.rs index b6c311cb55de..174e2108242d 100644 --- a/core/bin/zksync_tee_prover/src/main.rs +++ b/core/bin/zksync_tee_prover/src/main.rs @@ -30,26 +30,15 @@ mod tee_prover; fn main() -> anyhow::Result<()> { let observability_config = ObservabilityConfig::from_env().context("ObservabilityConfig::from_env()")?; - let log_format: zksync_vlog::LogFormat = observability_config - .log_format - .parse() - .context("Invalid log format")?; - let mut builder = zksync_vlog::ObservabilityBuilder::new().with_log_format(log_format); - if let Some(sentry_url) = observability_config.sentry_url { - builder = builder - .with_sentry_url(&sentry_url) - .context("Invalid Sentry URL")? - .with_sentry_environment(observability_config.sentry_environment); - } - let _guard = builder.build(); + let _observability_guard = observability_config.install()?; let tee_prover_config = TeeProverConfig::from_env()?; let attestation_quote_bytes = std::fs::read(tee_prover_config.attestation_quote_file_path)?; let prometheus_config = PrometheusConfig::from_env()?; - let mut builder = ZkStackServiceBuilder::new(); - let mut builder_mut = builder + let mut builder = ZkStackServiceBuilder::new()?; + builder .add_layer(SigintHandlerLayer) .add_layer(TeeProverLayer::new( tee_prover_config.api_url, @@ -61,9 +50,9 @@ fn main() -> anyhow::Result<()> { if let Some(gateway) = prometheus_config.gateway_endpoint() { let exporter_config = PrometheusExporterConfig::push(gateway, prometheus_config.push_interval()); - builder_mut = builder_mut.add_layer(PrometheusExporterLayer(exporter_config)); + builder.add_layer(PrometheusExporterLayer(exporter_config)); } - builder_mut.build()?.run()?; + builder.build().run()?; Ok(()) } diff --git a/core/lib/config/Cargo.toml b/core/lib/config/Cargo.toml index b1a2a0ef1e8f..784bdebfef07 100644 --- a/core/lib/config/Cargo.toml +++ b/core/lib/config/Cargo.toml @@ -15,9 +15,14 @@ zksync_basic_types.workspace = true zksync_crypto_primitives.workspace = true zksync_consensus_utils.workspace = true zksync_concurrency.workspace = true +zksync_vlog = { workspace = true, optional = true } url.workspace = true anyhow.workspace = true rand.workspace = true secrecy.workspace = true serde = { workspace = true, features = ["derive"] } + +[features] +default = [] +observability_ext = ["zksync_vlog"] diff --git a/core/lib/config/src/configs/observability.rs b/core/lib/config/src/configs/observability.rs index 96754e61e897..0bc61df31197 100644 --- a/core/lib/config/src/configs/observability.rs +++ b/core/lib/config/src/configs/observability.rs @@ -11,7 +11,7 @@ pub struct ObservabilityConfig { /// Format of the logs as expected by the `vlog` crate. /// Currently must be either `plain` or `json`. pub log_format: String, - // Log directives in format that is used in `RUST_LOG` + /// Log directives in format that is used in `RUST_LOG` pub log_directives: Option, } diff --git a/core/lib/config/src/lib.rs b/core/lib/config/src/lib.rs index 91b5c6d480e3..c5944e581a97 100644 --- a/core/lib/config/src/lib.rs +++ b/core/lib/config/src/lib.rs @@ -8,3 +8,6 @@ pub use crate::configs::{ pub mod configs; pub mod testonly; + +#[cfg(feature = "observability_ext")] +mod observability_ext; diff --git a/core/lib/config/src/observability_ext.rs b/core/lib/config/src/observability_ext.rs new file mode 100644 index 000000000000..5f8a8927efd5 --- /dev/null +++ b/core/lib/config/src/observability_ext.rs @@ -0,0 +1,52 @@ +//! Extensions for the `ObservabilityConfig` to install the observability stack. + +use crate::configs::ObservabilityConfig; + +impl ObservabilityConfig { + /// Installs the observability stack based on the configuration. + /// + /// If any overrides are needed, consider using the `TryFrom` implementations. + pub fn install(self) -> anyhow::Result { + let logs = zksync_vlog::Logs::try_from(self.clone())?; + let sentry = Option::::try_from(self.clone())?; + let opentelemetry = Option::::try_from(self.clone())?; + + let guard = zksync_vlog::ObservabilityBuilder::new() + .with_logs(Some(logs)) + .with_sentry(sentry) + .with_opentelemetry(opentelemetry) + .build(); + Ok(guard) + } +} + +impl TryFrom for zksync_vlog::Logs { + type Error = anyhow::Error; + + fn try_from(config: ObservabilityConfig) -> Result { + Ok(zksync_vlog::Logs::new(&config.log_format)?.with_log_directives(config.log_directives)) + } +} + +impl TryFrom for Option { + type Error = anyhow::Error; + + fn try_from(config: ObservabilityConfig) -> Result { + Ok(config + .sentry_url + .map(|url| zksync_vlog::Sentry::new(&url)) + .transpose()? + .map(|sentry| sentry.with_environment(config.sentry_environment))) + } +} + +impl TryFrom for Option { + type Error = anyhow::Error; + + fn try_from(config: ObservabilityConfig) -> Result { + Ok(config + .opentelemetry + .map(|config| zksync_vlog::OpenTelemetry::new(&config.level, config.endpoint)) + .transpose()?) + } +} diff --git a/core/lib/utils/src/wait_for_tasks.rs b/core/lib/utils/src/wait_for_tasks.rs index ab548bdd1dde..210d26484162 100644 --- a/core/lib/utils/src/wait_for_tasks.rs +++ b/core/lib/utils/src/wait_for_tasks.rs @@ -47,14 +47,20 @@ impl ManagedTasks { let err = "One of the actors finished its run, while it wasn't expected to do it"; tracing::error!("{err}"); - zksync_vlog::capture_message(err, zksync_vlog::AlertLevel::Warning); + zksync_vlog::sentry::capture_message( + err, + zksync_vlog::sentry::AlertLevel::Warning, + ); } } Ok(Err(err)) => { let err = format!("One of the tokio actors unexpectedly finished with error: {err:#}"); tracing::error!("{err}"); - zksync_vlog::capture_message(&err, zksync_vlog::AlertLevel::Warning); + zksync_vlog::sentry::capture_message( + &err, + zksync_vlog::sentry::AlertLevel::Warning, + ); } Err(error) => { let panic_message = try_extract_panic_message(error); diff --git a/core/lib/vlog/Cargo.toml b/core/lib/vlog/Cargo.toml index eb1ed735519c..3f9ce247442a 100644 --- a/core/lib/vlog/Cargo.toml +++ b/core/lib/vlog/Cargo.toml @@ -22,10 +22,13 @@ tracing-subscriber = { workspace = true, features = [ "json", ] } tracing-opentelemetry.workspace = true +time.workspace = true +thiserror.workspace = true sentry.workspace = true serde.workspace = true serde_json.workspace = true -opentelemetry = { workspace = true, features = ["rt-tokio", "trace"] } +opentelemetry = { workspace = true, features = ["trace"] } +opentelemetry_sdk = { workspace = true, features = [ "rt-tokio" ] } opentelemetry-otlp = { workspace = true, features = [ "http-proto", "reqwest-client", @@ -33,3 +36,4 @@ opentelemetry-otlp = { workspace = true, features = [ opentelemetry-semantic-conventions.workspace = true vise.workspace = true vise-exporter.workspace = true +url.workspace = true diff --git a/core/lib/vlog/src/lib.rs b/core/lib/vlog/src/lib.rs index 9b2886ba81d5..5633f20f5882 100644 --- a/core/lib/vlog/src/lib.rs +++ b/core/lib/vlog/src/lib.rs @@ -1,152 +1,23 @@ //! This crate contains the observability subsystem. //! It is responsible for providing a centralized interface for consistent observability configuration. -use std::{backtrace::Backtrace, borrow::Cow, panic::PanicInfo, str::FromStr}; +use ::sentry::ClientInitGuard; +use tracing_subscriber::{layer::SubscriberExt, util::SubscriberInitExt}; -// Temporary re-export of `sentry::capture_message` aiming to simplify the transition from `vlog` to using -// crates directly. -use opentelemetry::{ - sdk::{ - propagation::TraceContextPropagator, - trace::{self, RandomIdGenerator, Sampler, Tracer}, - Resource, - }, - KeyValue, -}; -use opentelemetry_otlp::WithExportConfig; -use opentelemetry_semantic_conventions::resource::SERVICE_NAME; -pub use sentry::{capture_message, Level as AlertLevel}; -use sentry::{types::Dsn, ClientInitGuard}; -use serde::{de::Error, Deserialize, Deserializer}; -use tracing_opentelemetry::OpenTelemetryLayer; -use tracing_subscriber::{ - filter::Filtered, - fmt, - layer::{Layered, SubscriberExt}, - registry::LookupSpan, - util::SubscriberInitExt, - EnvFilter, Layer, -}; +pub use crate::{logs::Logs, opentelemetry::OpenTelemetry, sentry::Sentry}; +pub mod logs; +pub mod opentelemetry; pub mod prometheus; - -type TracingLayer = - Layered, EnvFilter, Inner>, Inner>; - -/// Specifies the format of the logs in stdout. -#[derive(Debug, Clone, Copy, Default)] -pub enum LogFormat { - #[default] - Plain, - Json, -} - -impl std::fmt::Display for LogFormat { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - match self { - Self::Plain => f.write_str("plain"), - Self::Json => f.write_str("json"), - } - } -} - -#[derive(Debug)] -pub struct LogFormatError(&'static str); - -impl std::fmt::Display for LogFormatError { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - write!(f, "{}", self.0) - } -} - -impl std::error::Error for LogFormatError {} - -impl FromStr for LogFormat { - type Err = LogFormatError; - - fn from_str(s: &str) -> Result { - match s { - "plain" => Ok(LogFormat::Plain), - "json" => Ok(LogFormat::Json), - _ => Err(LogFormatError("invalid log format")), - } - } -} - -impl<'de> Deserialize<'de> for LogFormat { - fn deserialize>(deserializer: D) -> Result { - let s = String::deserialize(deserializer)?; - s.parse::().map_err(D::Error::custom) - } -} - -// Doesn't define WARN and ERROR, because the highest verbosity of spans is INFO. -#[derive(Copy, Clone, Debug, Default)] -pub enum OpenTelemetryLevel { - #[default] - OFF, - INFO, - DEBUG, - TRACE, -} - -#[derive(Debug)] -pub struct OpenTelemetryLevelFormatError; - -impl std::fmt::Display for OpenTelemetryLevelFormatError { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - write!(f, "Invalid OpenTelemetry level format") - } -} - -impl std::error::Error for OpenTelemetryLevelFormatError {} - -impl FromStr for OpenTelemetryLevel { - type Err = OpenTelemetryLevelFormatError; - - fn from_str(s: &str) -> Result { - match s { - "off" => Ok(OpenTelemetryLevel::OFF), - "info" => Ok(OpenTelemetryLevel::INFO), - "debug" => Ok(OpenTelemetryLevel::DEBUG), - "trace" => Ok(OpenTelemetryLevel::TRACE), - _ => Err(OpenTelemetryLevelFormatError), - } - } -} - -impl std::fmt::Display for OpenTelemetryLevel { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - let str = match self { - OpenTelemetryLevel::OFF => "off", - OpenTelemetryLevel::INFO => "info", - OpenTelemetryLevel::DEBUG => "debug", - OpenTelemetryLevel::TRACE => "trace", - }; - write!(f, "{}", str) - } -} - -#[derive(Clone, Debug)] -pub struct OpenTelemetryOptions { - /// Enables export of span data of specified level (and above) using opentelemetry exporters. - pub opentelemetry_level: OpenTelemetryLevel, - /// Opentelemetry HTTP collector endpoint. - pub otlp_endpoint: String, - /// Logical service name to be used for exported events. See [`SERVICE_NAME`]. - pub service_name: String, -} +pub mod sentry; /// Builder for the observability subsystem. /// Currently capable of configuring logging output and sentry integration. #[derive(Debug, Default)] pub struct ObservabilityBuilder { - disable_default_logs: bool, - log_format: LogFormat, - log_directives: Option, - sentry_url: Option, - sentry_environment: Option, - opentelemetry_options: Option, + logs: Option, + opentelemetry_layer: Option, + sentry: Option, } /// Guard for the observability subsystem. @@ -167,235 +38,40 @@ impl ObservabilityBuilder { Self::default() } - /// Sets the log format. - /// Default is `LogFormat::Plain`. - pub fn with_log_format(mut self, log_format: LogFormat) -> Self { - self.log_format = log_format; + pub fn with_logs(mut self, logs: Option) -> Self { + self.logs = logs; self } - pub fn with_log_directives(mut self, log_level: String) -> Self { - self.log_directives = Some(log_level); + pub fn with_opentelemetry(mut self, opentelemetry: Option) -> Self { + self.opentelemetry_layer = opentelemetry; self } - /// Disables logs enabled by default. - /// May be used, for example, in interactive CLI applications, where the user may want to fully control - /// the verbosity. - pub fn disable_default_logs(mut self) -> Self { - self.disable_default_logs = true; - self - } - - /// Enables Sentry integration. - /// Returns an error if the provided Sentry URL is invalid. - pub fn with_sentry_url( - mut self, - sentry_url: &str, - ) -> Result { - let sentry_url = sentry_url.parse()?; - self.sentry_url = Some(sentry_url); - Ok(self) - } - - /// Sets the Sentry environment ID. - /// If not set, no environment will be provided in Sentry events. - pub fn with_sentry_environment(mut self, environment: Option) -> Self { - self.sentry_environment = environment; + pub fn with_sentry(mut self, sentry: Option) -> Self { + self.sentry = sentry; self } - pub fn with_opentelemetry( - mut self, - opentelemetry_level: &str, - otlp_endpoint: String, - service_name: String, - ) -> Result { - self.opentelemetry_options = Some(OpenTelemetryOptions { - opentelemetry_level: opentelemetry_level.parse()?, - otlp_endpoint, - service_name, - }); - Ok(self) - } - - fn add_opentelemetry_layer( - opentelemetry_level: OpenTelemetryLevel, - otlp_endpoint: String, - service_name: String, - subscriber: S, - ) -> TracingLayer - where - S: tracing::Subscriber + for<'span> LookupSpan<'span> + Send + Sync, - { - let filter = match opentelemetry_level { - OpenTelemetryLevel::OFF => EnvFilter::new("off"), - OpenTelemetryLevel::INFO => EnvFilter::new("info"), - OpenTelemetryLevel::DEBUG => EnvFilter::new("debug"), - OpenTelemetryLevel::TRACE => EnvFilter::new("trace"), - }; - // `otel::tracing` should be a level info to emit opentelemetry trace & span - // `otel` set to debug to log detected resources, configuration read and inferred - let filter = filter - .add_directive("otel::tracing=trace".parse().unwrap()) - .add_directive("otel=debug".parse().unwrap()); - - let resource = vec![KeyValue::new(SERVICE_NAME, service_name)]; - - let tracer = opentelemetry_otlp::new_pipeline() - .tracing() - .with_exporter( - opentelemetry_otlp::new_exporter() - .http() - .with_endpoint(otlp_endpoint), - ) - .with_trace_config( - trace::config() - .with_sampler(Sampler::AlwaysOn) - .with_id_generator(RandomIdGenerator::default()) - .with_resource(Resource::new(resource)), - ) - .install_batch(opentelemetry::runtime::Tokio) - .unwrap(); - - opentelemetry::global::set_text_map_propagator(TraceContextPropagator::new()); - let layer = tracing_opentelemetry::layer() - .with_tracer(tracer) - .with_filter(filter); - subscriber.with(layer) - } - - /// Builds a filter for the logs. - /// - /// Unless `disable_default_logs` was set, uses `zksync=info` as a default which is then merged - /// with user-defined directives. Provided directives can extend/override the default value. - /// - /// The provided default convers all the crates with a name starting with `zksync` (per `tracing` - /// [documentation][1]), which is a good enough default for any project. - /// - /// If `log_directives` are provided via `with_log_directives`, they will be used. - /// Otherwise, the value will be parsed from the environment variable `RUST_LOG`. - /// - /// [1]: https://docs.rs/tracing-subscriber/0.3.18/tracing_subscriber/filter/targets/struct.Targets.html#filtering-with-targets - fn build_filter(&self) -> EnvFilter { - let mut directives = if self.disable_default_logs { - "".to_string() - } else { - "zksync=info,".to_string() - }; - if let Some(log_directives) = &self.log_directives { - directives.push_str(log_directives); - } else if let Ok(env_directives) = std::env::var(EnvFilter::DEFAULT_ENV) { - directives.push_str(&env_directives); - }; - EnvFilter::new(directives) - } - /// Initializes the observability subsystem. pub fn build(self) -> ObservabilityGuard { - // Initialize logs. - let env_filter = self.build_filter(); - - match self.log_format { - LogFormat::Plain => { - let subscriber = tracing_subscriber::registry() - .with(env_filter) - .with(fmt::Layer::default()); - if let Some(opts) = self.opentelemetry_options { - let subscriber = Self::add_opentelemetry_layer( - opts.opentelemetry_level, - opts.otlp_endpoint, - opts.service_name, - subscriber, - ); - subscriber.init() - } else { - subscriber.init() - } - } - LogFormat::Json => { - let timer = tracing_subscriber::fmt::time::UtcTime::rfc_3339(); - let subscriber = tracing_subscriber::registry().with(env_filter).with( - fmt::Layer::default() - .with_file(true) - .with_line_number(true) - .with_timer(timer) - .json(), - ); - if let Some(opts) = self.opentelemetry_options { - let subscriber = Self::add_opentelemetry_layer( - opts.opentelemetry_level, - opts.otlp_endpoint, - opts.service_name, - subscriber, - ); - subscriber.init() - } else { - subscriber.init() - } - } - }; + let logs = self.logs.unwrap_or_default(); + logs.install_panic_hook(); - // Check whether we need to change the default panic handler. - // Note that this must happen before we initialize Sentry, since otherwise - // Sentry's panic handler will also invoke the default one, resulting in unformatted - // panic info being output to stderr. - if matches!(self.log_format, LogFormat::Json) { - // Remove any existing hook. We expect that no hook is set by default. - let _ = std::panic::take_hook(); - // Override the default panic handler to print the panic in JSON format. - std::panic::set_hook(Box::new(json_panic_handler)); - }; + // For now we use logs filter as a global filter for subscriber. + // Later we may want to enforce each layer to have its own filter. + let global_filter = logs.build_filter(); - // Initialize the Sentry. - let sentry_guard = if let Some(sentry_url) = self.sentry_url { - let options = sentry::ClientOptions { - release: sentry::release_name!(), - environment: self.sentry_environment.map(Cow::from), - attach_stacktrace: true, - ..Default::default() - }; + tracing_subscriber::registry() + .with(global_filter) + .with(logs.into_layer()) + .with(self.opentelemetry_layer.map(|layer| layer.into_layer())) + .init(); - Some(sentry::init((sentry_url, options))) - } else { - None - }; + let sentry_guard = self.sentry.map(|sentry| sentry.install()); ObservabilityGuard { _sentry_guard: sentry_guard, } } } - -fn json_panic_handler(panic_info: &PanicInfo) { - let backtrace = Backtrace::force_capture(); - let timestamp = chrono::Utc::now(); - let panic_message = if let Some(s) = panic_info.payload().downcast_ref::() { - s.as_str() - } else if let Some(s) = panic_info.payload().downcast_ref::<&str>() { - s - } else { - "Panic occurred without additional info" - }; - - let panic_location = panic_info - .location() - .map(|val| val.to_string()) - .unwrap_or_else(|| "Unknown location".to_owned()); - - let backtrace_str = backtrace.to_string(); - let timestamp_str = timestamp.format("%Y-%m-%dT%H:%M:%S%.fZ").to_string(); - - println!( - "{}", - serde_json::json!({ - "timestamp": timestamp_str, - "level": "CRITICAL", - "fields": { - "message": panic_message, - "location": panic_location, - "backtrace": backtrace_str, - } - }) - ); -} diff --git a/core/lib/vlog/src/logs/layer.rs b/core/lib/vlog/src/logs/layer.rs new file mode 100644 index 000000000000..3577487bea2e --- /dev/null +++ b/core/lib/vlog/src/logs/layer.rs @@ -0,0 +1,140 @@ +use tracing::{span, Subscriber}; +use tracing_subscriber::{fmt, registry::LookupSpan, Layer}; + +/// Implementation of statically typed logs layer, which can be either plain or JSON. +/// This is mostly required to avoid [boxing the layer][layer_box]. +/// +/// [layer_box]: https://docs.rs/tracing-subscriber/latest/tracing_subscriber/layer/trait.Layer.html#method.boxed +#[derive(Debug)] +pub enum LogsLayer { + Plain(fmt::Layer), + Json(JsonLayer), +} + +macro_rules! dispatch_layer { + ($self:ident.$method:ident($($arg:ident),*)) => { + match $self { + LogsLayer::Plain(layer) => layer.$method($($arg),*), + LogsLayer::Json(layer) => layer.$method($($arg),*), + } + }; +} + +// Implementation note: methods like `and_then`, `with_filter`, `with_timer`, etc. are not +// implemented because they wrap `Self`, so default implementation is sufficient. +impl tracing_subscriber::Layer for LogsLayer +where + S: Subscriber + for<'span> LookupSpan<'span> + Send + Sync, +{ + fn on_register_dispatch(&self, collector: &tracing::Dispatch) { + dispatch_layer!(self.on_register_dispatch(collector)); + } + + fn on_layer(&mut self, subscriber: &mut S) { + dispatch_layer!(self.on_layer(subscriber)); + } + + fn register_callsite( + &self, + metadata: &'static tracing::Metadata<'static>, + ) -> tracing::subscriber::Interest { + dispatch_layer!(self.register_callsite(metadata)) + } + + fn enabled( + &self, + metadata: &tracing::Metadata<'_>, + ctx: tracing_subscriber::layer::Context<'_, S>, + ) -> bool { + dispatch_layer!(self.enabled(metadata, ctx)) + } + + fn on_new_span( + &self, + attrs: &span::Attributes<'_>, + id: &span::Id, + ctx: tracing_subscriber::layer::Context<'_, S>, + ) { + dispatch_layer!(self.on_new_span(attrs, id, ctx)) + } + + fn on_record( + &self, + span: &span::Id, + values: &span::Record<'_>, + ctx: tracing_subscriber::layer::Context<'_, S>, + ) { + dispatch_layer!(self.on_record(span, values, ctx)) + } + + fn on_follows_from( + &self, + span: &span::Id, + follows: &span::Id, + ctx: tracing_subscriber::layer::Context<'_, S>, + ) { + dispatch_layer!(self.on_follows_from(span, follows, ctx)) + } + + fn event_enabled( + &self, + event: &tracing::Event<'_>, + ctx: tracing_subscriber::layer::Context<'_, S>, + ) -> bool { + dispatch_layer!(self.event_enabled(event, ctx)) + } + + fn on_event(&self, event: &tracing::Event<'_>, ctx: tracing_subscriber::layer::Context<'_, S>) { + dispatch_layer!(self.on_event(event, ctx)) + } + + fn on_enter(&self, id: &span::Id, ctx: tracing_subscriber::layer::Context<'_, S>) { + dispatch_layer!(self.on_enter(id, ctx)) + } + + fn on_exit(&self, id: &span::Id, ctx: tracing_subscriber::layer::Context<'_, S>) { + dispatch_layer!(self.on_exit(id, ctx)) + } + + fn on_close(&self, id: span::Id, ctx: tracing_subscriber::layer::Context<'_, S>) { + dispatch_layer!(self.on_close(id, ctx)) + } + + fn on_id_change( + &self, + old: &span::Id, + new: &span::Id, + ctx: tracing_subscriber::layer::Context<'_, S>, + ) { + dispatch_layer!(self.on_id_change(old, new, ctx)) + } + + fn boxed(self) -> Box + Send + Sync + 'static> + where + Self: Sized, + Self: Layer + Send + Sync + 'static, + S: Subscriber, + { + dispatch_layer!(self.boxed()) + } +} + +// I guess tracing types weren't supposed to be written, but we have to. +// If this type has to be changed, the easiest way to figure it out is to attempt +// constructing the object, e.g.: +// ``` +// let layer = fmt::Layer::default() +// .with_file(true) +// .with_line_number(true) +// .with_timer(timer) +// .json(); +// ``` +// Compiler will complain and tell the type for you. +type JsonLayer = tracing_subscriber::fmt::Layer< + S, + tracing_subscriber::fmt::format::JsonFields, + tracing_subscriber::fmt::format::Format< + tracing_subscriber::fmt::format::Json, + tracing_subscriber::fmt::time::UtcTime, + >, +>; diff --git a/core/lib/vlog/src/logs/mod.rs b/core/lib/vlog/src/logs/mod.rs new file mode 100644 index 000000000000..0ecf1c6d9f0b --- /dev/null +++ b/core/lib/vlog/src/logs/mod.rs @@ -0,0 +1,163 @@ +use std::{backtrace::Backtrace, panic::PanicInfo, str::FromStr}; + +use serde::Deserialize; +use tracing_subscriber::{fmt, registry::LookupSpan, EnvFilter, Layer}; + +mod layer; + +/// Specifies the format of the logs in stdout. +#[derive(Debug, Clone, Copy, Default, Deserialize)] +#[serde(rename_all = "lowercase")] +pub enum LogFormat { + #[default] + Plain, + Json, +} + +impl FromStr for LogFormat { + type Err = LogFormatError; + + fn from_str(s: &str) -> Result { + match s { + "plain" => Ok(Self::Plain), + "json" => Ok(Self::Json), + _ => Err(LogFormatError::InvalidFormat), + } + } +} + +#[derive(Debug, thiserror::Error)] +#[non_exhaustive] +pub enum LogFormatError { + #[error("Invalid log format")] + InvalidFormat, +} + +#[derive(Debug, Default)] +pub struct Logs { + format: LogFormat, + log_directives: Option, + disable_default_logs: bool, +} + +impl From for Logs { + fn from(format: LogFormat) -> Self { + Self { + format, + log_directives: None, + disable_default_logs: false, + } + } +} + +impl Logs { + pub fn new(format: &str) -> Result { + Ok(Self { + format: format.parse()?, + log_directives: None, + disable_default_logs: false, + }) + } + + /// Builds a filter for the logs. + /// + /// Unless `disable_default_logs` was set, uses `zksync=info` as a default which is then merged + /// with user-defined directives. Provided directives can extend/override the default value. + /// + /// The provided default convers all the crates with a name starting with `zksync` (per `tracing` + /// [documentation][1]), which is a good enough default for any project. + /// + /// If `log_directives` are provided via `with_log_directives`, they will be used. + /// Otherwise, the value will be parsed from the environment variable `RUST_LOG`. + /// + /// [1]: https://docs.rs/tracing-subscriber/0.3.18/tracing_subscriber/filter/targets/struct.Targets.html#filtering-with-targets + pub(super) fn build_filter(&self) -> EnvFilter { + let mut directives = if self.disable_default_logs { + "".to_string() + } else { + "zksync=info,".to_string() + }; + if let Some(log_directives) = &self.log_directives { + directives.push_str(log_directives); + } else if let Ok(env_directives) = std::env::var(EnvFilter::DEFAULT_ENV) { + directives.push_str(&env_directives); + }; + EnvFilter::new(directives) + } + + pub fn with_log_directives(mut self, log_directives: Option) -> Self { + self.log_directives = log_directives; + self + } + + pub fn disable_default_logs(mut self) -> Self { + self.disable_default_logs = true; + self + } + + pub fn install_panic_hook(&self) { + // Check whether we need to change the default panic handler. + // Note that this must happen before we initialize Sentry, since otherwise + // Sentry's panic handler will also invoke the default one, resulting in unformatted + // panic info being output to stderr. + if matches!(self.format, LogFormat::Json) { + // Remove any existing hook. We expect that no hook is set by default. + let _ = std::panic::take_hook(); + // Override the default panic handler to print the panic in JSON format. + std::panic::set_hook(Box::new(json_panic_handler)); + }; + } + + pub fn into_layer(self) -> impl Layer + where + S: tracing::Subscriber + for<'span> LookupSpan<'span> + Send + Sync, + { + let filter = self.build_filter(); + let layer = match self.format { + LogFormat::Plain => layer::LogsLayer::Plain(fmt::Layer::new()), + LogFormat::Json => { + let timer = tracing_subscriber::fmt::time::UtcTime::rfc_3339(); + let json_layer = fmt::Layer::default() + .with_file(true) + .with_line_number(true) + .with_timer(timer) + .json(); + layer::LogsLayer::Json(json_layer) + } + }; + layer.with_filter(filter) + } +} + +fn json_panic_handler(panic_info: &PanicInfo) { + let backtrace = Backtrace::force_capture(); + let timestamp = chrono::Utc::now(); + let panic_message = if let Some(s) = panic_info.payload().downcast_ref::() { + s.as_str() + } else if let Some(s) = panic_info.payload().downcast_ref::<&str>() { + s + } else { + "Panic occurred without additional info" + }; + + let panic_location = panic_info + .location() + .map(|val| val.to_string()) + .unwrap_or_else(|| "Unknown location".to_owned()); + + let backtrace_str = backtrace.to_string(); + let timestamp_str = timestamp.format("%Y-%m-%dT%H:%M:%S%.fZ").to_string(); + + println!( + "{}", + serde_json::json!({ + "timestamp": timestamp_str, + "level": "CRITICAL", + "fields": { + "message": panic_message, + "location": panic_location, + "backtrace": backtrace_str, + } + }) + ); +} diff --git a/core/lib/vlog/src/opentelemetry/mod.rs b/core/lib/vlog/src/opentelemetry/mod.rs new file mode 100644 index 000000000000..64049df8ce9b --- /dev/null +++ b/core/lib/vlog/src/opentelemetry/mod.rs @@ -0,0 +1,191 @@ +use std::str::FromStr; + +use opentelemetry::{trace::TracerProvider, KeyValue}; +use opentelemetry_otlp::WithExportConfig; +use opentelemetry_sdk::{ + propagation::TraceContextPropagator, + trace::{RandomIdGenerator, Sampler}, + Resource, +}; +use opentelemetry_semantic_conventions::resource::{ + K8S_NAMESPACE_NAME, K8S_POD_NAME, SERVICE_NAME, +}; +use tracing_subscriber::{registry::LookupSpan, EnvFilter, Layer}; +use url::Url; + +/// Information about the service. +#[derive(Debug, Default)] +#[non_exhaustive] +pub struct ServiceDescriptor { + /// Name of the k8s pod. + pub k8s_pod_name: Option, + /// Name of the k8s namespace. + pub k8s_namespace_name: Option, + /// Name of the service. + pub service_name: Option, +} + +impl ServiceDescriptor { + pub fn new() -> Self { + Self::default() + } + + pub fn with_k8s_pod_name(mut self, k8s_pod_name: Option) -> Self { + self.k8s_pod_name = k8s_pod_name; + self + } + + pub fn with_k8s_namespace_name(mut self, k8s_namespace_name: Option) -> Self { + self.k8s_namespace_name = k8s_namespace_name; + self + } + + pub fn with_service_name(mut self, service_name: Option) -> Self { + self.service_name = service_name; + self + } + + /// Tries to fill empty fields from environment variables. + /// + /// The following environment variables are used: + /// - `POD_NAME` + /// - `POD_NAMESPACE` + /// - `SERVICE_NAME` + pub fn fill_from_env(mut self) -> Self { + if self.k8s_pod_name.is_none() { + self.k8s_pod_name = std::env::var("POD_NAME").ok(); + } + if self.k8s_namespace_name.is_none() { + self.k8s_namespace_name = std::env::var("POD_NAMESPACE").ok(); + } + if self.service_name.is_none() { + self.service_name = std::env::var("SERVICE_NAME").ok(); + } + self + } + + fn into_otlp_resource(self) -> Resource { + let mut attributes = vec![]; + if let Some(pod_name) = self.k8s_pod_name { + attributes.push(KeyValue::new(K8S_POD_NAME, pod_name)); + } + if let Some(pod_namespace) = self.k8s_namespace_name { + attributes.push(KeyValue::new(K8S_NAMESPACE_NAME, pod_namespace)); + } + if let Some(service_name) = self.service_name { + attributes.push(KeyValue::new(SERVICE_NAME, service_name)); + } + Resource::new(attributes) + } +} + +#[derive(Debug)] +pub struct OpenTelemetry { + /// Enables export of span data of specified level (and above) using opentelemetry exporters. + pub opentelemetry_level: OpenTelemetryLevel, + /// Opentelemetry HTTP collector endpoint. + pub otlp_endpoint: Url, + /// Information about service + pub service: Option, +} + +impl OpenTelemetry { + pub fn new( + opentelemetry_level: &str, + otlp_endpoint: String, + ) -> Result { + Ok(Self { + opentelemetry_level: opentelemetry_level.parse()?, + otlp_endpoint: otlp_endpoint + .parse() + .map_err(|e| OpenTelemetryLayerError::InvalidUrl(otlp_endpoint, e))?, + service: None, + }) + } + + pub fn with_service_descriptor(mut self, service: ServiceDescriptor) -> Self { + self.service = Some(service); + self + } + + pub(super) fn into_layer(self) -> impl Layer + where + S: tracing::Subscriber + for<'span> LookupSpan<'span> + Send + Sync, + { + let filter = match self.opentelemetry_level { + OpenTelemetryLevel::OFF => EnvFilter::new("off"), + OpenTelemetryLevel::INFO => EnvFilter::new("info"), + OpenTelemetryLevel::DEBUG => EnvFilter::new("debug"), + OpenTelemetryLevel::TRACE => EnvFilter::new("trace"), + }; + // `otel::tracing` should be a level info to emit opentelemetry trace & span + // `otel` set to debug to log detected resources, configuration read and inferred + let filter = filter + .add_directive("otel::tracing=trace".parse().unwrap()) + .add_directive("otel=debug".parse().unwrap()); + + let service = self.service.unwrap_or_default().fill_from_env(); + let service_name = service + .service_name + .clone() + .unwrap_or_else(|| "zksync_vlog".to_string()); + let resource = service.into_otlp_resource(); + + let exporter = opentelemetry_otlp::new_exporter() + .http() + .with_endpoint(self.otlp_endpoint) + .build_span_exporter() + .expect("Failed to create OTLP exporter"); // URL is validated. + + let config = opentelemetry_sdk::trace::Config::default() + .with_id_generator(RandomIdGenerator::default()) + .with_sampler(Sampler::AlwaysOn) + .with_resource(resource); + + let provider = opentelemetry_sdk::trace::TracerProvider::builder() + .with_batch_exporter(exporter, opentelemetry_sdk::runtime::Tokio) + .with_config(config) + .build(); + + // TODO: Version and other metadata + let tracer = provider.tracer_builder(service_name).build(); + + opentelemetry::global::set_text_map_propagator(TraceContextPropagator::new()); + tracing_opentelemetry::layer() + .with_tracer(tracer) + .with_filter(filter) + } +} + +// Doesn't define WARN and ERROR, because the highest verbosity of spans is INFO. +#[derive(Copy, Clone, Debug, Default)] +pub enum OpenTelemetryLevel { + #[default] + OFF, + INFO, + DEBUG, + TRACE, +} + +#[derive(Debug, thiserror::Error)] +#[non_exhaustive] +pub enum OpenTelemetryLayerError { + #[error("Invalid OpenTelemetry level format")] + InvalidFormat, + #[error("Invalid URL: \"{0}\" - {1}")] + InvalidUrl(String, url::ParseError), +} + +impl FromStr for OpenTelemetryLevel { + type Err = OpenTelemetryLayerError; + + fn from_str(s: &str) -> Result { + match s { + "off" => Ok(OpenTelemetryLevel::OFF), + "info" => Ok(OpenTelemetryLevel::INFO), + "debug" => Ok(OpenTelemetryLevel::DEBUG), + "trace" => Ok(OpenTelemetryLevel::TRACE), + _ => Err(OpenTelemetryLayerError::InvalidFormat), + } + } +} diff --git a/core/lib/vlog/src/sentry.rs b/core/lib/vlog/src/sentry.rs new file mode 100644 index 000000000000..5102efd9a1a7 --- /dev/null +++ b/core/lib/vlog/src/sentry.rs @@ -0,0 +1,38 @@ +use std::borrow::Cow; + +// Temporary re-export of `sentry::capture_message` aiming to simplify the transition from `vlog` to using +// crates directly. +pub use sentry::{capture_message, Level as AlertLevel}; +use sentry::{types::Dsn, ClientInitGuard}; + +#[derive(Debug)] +pub struct Sentry { + url: Dsn, + environment: Option, +} + +impl Sentry { + pub fn new(url: &str) -> Result { + Ok(Self { + url: url.parse()?, + environment: None, + }) + } + + pub fn with_environment(mut self, environment: Option) -> Self { + self.environment = environment; + self + } + + pub fn install(self) -> ClientInitGuard { + // Initialize the Sentry. + let options = sentry::ClientOptions { + release: sentry::release_name!(), + environment: self.environment.map(Cow::from), + attach_stacktrace: true, + ..Default::default() + }; + + sentry::init((self.url, options)) + } +} diff --git a/core/node/node_framework/examples/main_node.rs b/core/node/node_framework/examples/main_node.rs deleted file mode 100644 index 38f989bda85f..000000000000 --- a/core/node/node_framework/examples/main_node.rs +++ /dev/null @@ -1,419 +0,0 @@ -//! An incomplete example of how node initialization looks like. -//! This example defines a `ResourceProvider` that works using the main node env config, and -//! initializes a single task with a health check server. - -use anyhow::Context; -use zksync_config::{ - configs::{ - chain::{ - CircuitBreakerConfig, MempoolConfig, NetworkConfig, OperationsManagerConfig, - StateKeeperConfig, - }, - fri_prover_group::FriProverGroupConfig, - house_keeper::HouseKeeperConfig, - wallets::Wallets, - DatabaseSecrets, FriProofCompressorConfig, FriProverConfig, FriWitnessGeneratorConfig, - L1Secrets, ObservabilityConfig, ProofDataHandlerConfig, - }, - ApiConfig, ContractVerifierConfig, ContractsConfig, DBConfig, EthConfig, EthWatchConfig, - GasAdjusterConfig, GenesisConfig, ObjectStoreConfig, PostgresConfig, -}; -use zksync_env_config::FromEnv; -use zksync_metadata_calculator::MetadataCalculatorConfig; -use zksync_node_api_server::{ - tx_sender::{ApiContracts, TxSenderConfig}, - web3::{state::InternalApiConfig, Namespace}, -}; -use zksync_node_framework::{ - implementations::layers::{ - circuit_breaker_checker::CircuitBreakerCheckerLayer, - commitment_generator::CommitmentGeneratorLayer, - contract_verification_api::ContractVerificationApiLayer, - eth_sender::{EthTxAggregatorLayer, EthTxManagerLayer}, - eth_watch::EthWatchLayer, - healtcheck_server::HealthCheckLayer, - house_keeper::HouseKeeperLayer, - l1_gas::SequencerL1GasLayer, - metadata_calculator::MetadataCalculatorLayer, - object_store::ObjectStoreLayer, - pk_signing_eth_client::PKSigningEthClientLayer, - pools_layer::PoolsLayerBuilder, - proof_data_handler::ProofDataHandlerLayer, - query_eth_client::QueryEthClientLayer, - sigint::SigintHandlerLayer, - state_keeper::{ - main_batch_executor::MainBatchExecutorLayer, mempool_io::MempoolIOLayer, - output_handler::OutputHandlerLayer, StateKeeperLayer, - }, - web3_api::{ - caches::MempoolCacheLayer, - server::{Web3ServerLayer, Web3ServerOptionalConfig}, - tree_api_client::TreeApiClientLayer, - tx_sender::{PostgresStorageCachesConfig, TxSenderLayer}, - tx_sink::MasterPoolSinkLayer, - }, - }, - service::{ZkStackService, ZkStackServiceBuilder, ZkStackServiceError}, -}; -use zksync_state::RocksdbStorageOptions; - -struct MainNodeBuilder { - node: ZkStackServiceBuilder, -} - -impl MainNodeBuilder { - fn new() -> Self { - Self { - node: ZkStackServiceBuilder::new(), - } - } - - fn add_sigint_handler_layer(mut self) -> anyhow::Result { - self.node.add_layer(SigintHandlerLayer); - Ok(self) - } - - fn add_pools_layer(mut self) -> anyhow::Result { - let config = PostgresConfig::from_env()?; - let secrets = DatabaseSecrets::from_env()?; - let pools_layer = PoolsLayerBuilder::empty(config, secrets) - .with_master(true) - .with_replica(true) - .with_prover(true) - .build(); - self.node.add_layer(pools_layer); - Ok(self) - } - - fn add_pk_signing_client_layer(mut self) -> anyhow::Result { - let genesis = GenesisConfig::from_env()?; - let eth_config = EthConfig::from_env()?; - let wallets = Wallets::from_env()?; - self.node.add_layer(PKSigningEthClientLayer::new( - eth_config, - ContractsConfig::from_env()?, - genesis.l1_chain_id, - wallets.eth_sender.context("Eth sender configs")?, - )); - Ok(self) - } - - fn add_query_eth_client_layer(mut self) -> anyhow::Result { - let genesis = GenesisConfig::from_env()?; - let eth_config = L1Secrets::from_env()?; - let query_eth_client_layer = - QueryEthClientLayer::new(genesis.l1_chain_id, eth_config.l1_rpc_url); - self.node.add_layer(query_eth_client_layer); - Ok(self) - } - - fn add_sequencer_l1_gas_layer(mut self) -> anyhow::Result { - let gas_adjuster_config = GasAdjusterConfig::from_env()?; - let state_keeper_config = StateKeeperConfig::from_env()?; - let genesis_config = GenesisConfig::from_env()?; - let eth_sender_config = EthConfig::from_env()?; - let sequencer_l1_gas_layer = SequencerL1GasLayer::new( - gas_adjuster_config, - genesis_config, - state_keeper_config, - eth_sender_config - .sender - .context("eth_sender")? - .pubdata_sending_mode, - ); - self.node.add_layer(sequencer_l1_gas_layer); - Ok(self) - } - - fn add_object_store_layer(mut self) -> anyhow::Result { - let object_store_config = ObjectStoreConfig::from_env()?; - self.node - .add_layer(ObjectStoreLayer::new(object_store_config)); - Ok(self) - } - - fn add_metadata_calculator_layer(mut self) -> anyhow::Result { - let merkle_tree_env_config = DBConfig::from_env()?.merkle_tree; - let operations_manager_env_config = OperationsManagerConfig::from_env()?; - let state_keeper_env_config = StateKeeperConfig::from_env()?; - let metadata_calculator_config = MetadataCalculatorConfig::for_main_node( - &merkle_tree_env_config, - &operations_manager_env_config, - &state_keeper_env_config, - ); - self.node - .add_layer(MetadataCalculatorLayer::new(metadata_calculator_config)); - Ok(self) - } - - fn add_state_keeper_layer(mut self) -> anyhow::Result { - let wallets = Wallets::from_env()?; - let contracts_config = ContractsConfig::from_env()?; - let sk_config = StateKeeperConfig::from_env()?; - let persisence_layer = OutputHandlerLayer::new( - contracts_config.l2_shared_bridge_addr.unwrap(), - sk_config.l2_block_seal_queue_capacity, - ); - let mempool_io_layer = MempoolIOLayer::new( - NetworkConfig::from_env()?.zksync_network_id, - sk_config, - MempoolConfig::from_env()?, - wallets.state_keeper.context("State keeper wallets")?, - ); - let main_node_batch_executor_builder_layer = - MainBatchExecutorLayer::new(StateKeeperConfig::from_env()?.save_call_traces, true); - let db_config = DBConfig::from_env()?; - - let rocksdb_options = RocksdbStorageOptions { - block_cache_capacity: db_config - .experimental - .state_keeper_db_block_cache_capacity(), - max_open_files: db_config.experimental.state_keeper_db_max_open_files, - }; - let state_keeper_layer = - StateKeeperLayer::new(db_config.state_keeper_db_path, rocksdb_options); - self.node - .add_layer(persisence_layer) - .add_layer(mempool_io_layer) - .add_layer(main_node_batch_executor_builder_layer) - .add_layer(state_keeper_layer); - Ok(self) - } - - fn add_eth_watch_layer(mut self) -> anyhow::Result { - self.node.add_layer(EthWatchLayer::new( - EthWatchConfig::from_env()?, - ContractsConfig::from_env()?, - )); - Ok(self) - } - - fn add_proof_data_handler_layer(mut self) -> anyhow::Result { - let genesis_config = GenesisConfig::from_env()?; - self.node.add_layer(ProofDataHandlerLayer::new( - ProofDataHandlerConfig::from_env()?, - genesis_config.l1_batch_commit_data_generator_mode, - )); - Ok(self) - } - - fn add_healthcheck_layer(mut self) -> anyhow::Result { - let healthcheck_config = ApiConfig::from_env()?.healthcheck; - self.node.add_layer(HealthCheckLayer(healthcheck_config)); - Ok(self) - } - - fn add_tx_sender_layer(mut self) -> anyhow::Result { - let state_keeper_config = StateKeeperConfig::from_env()?; - let rpc_config = ApiConfig::from_env()?.web3_json_rpc; - let network_config = NetworkConfig::from_env()?; - let postgres_storage_caches_config = PostgresStorageCachesConfig { - factory_deps_cache_size: rpc_config.factory_deps_cache_size() as u64, - initial_writes_cache_size: rpc_config.initial_writes_cache_size() as u64, - latest_values_cache_size: rpc_config.latest_values_cache_size() as u64, - }; - let wallets = Wallets::from_env()?; - - // On main node we always use master pool sink. - self.node.add_layer(MasterPoolSinkLayer); - self.node.add_layer(TxSenderLayer::new( - TxSenderConfig::new( - &state_keeper_config, - &rpc_config, - wallets - .state_keeper - .context("StateKeeper wallets")? - .fee_account - .address(), - network_config.zksync_network_id, - ), - postgres_storage_caches_config, - rpc_config.vm_concurrency_limit(), - ApiContracts::load_from_disk_blocking(), // TODO (BFT-138): Allow to dynamically reload API contracts - )); - Ok(self) - } - - fn add_api_caches_layer(mut self) -> anyhow::Result { - let rpc_config = ApiConfig::from_env()?.web3_json_rpc; - self.node.add_layer(MempoolCacheLayer::new( - rpc_config.mempool_cache_size(), - rpc_config.mempool_cache_update_interval(), - )); - Ok(self) - } - - fn add_tree_api_client_layer(mut self) -> anyhow::Result { - let rpc_config = ApiConfig::from_env()?.web3_json_rpc; - self.node - .add_layer(TreeApiClientLayer::http(rpc_config.tree_api_url)); - Ok(self) - } - - fn add_http_web3_api_layer(mut self) -> anyhow::Result { - let rpc_config = ApiConfig::from_env()?.web3_json_rpc; - let contracts_config = ContractsConfig::from_env()?; - let state_keeper_config = StateKeeperConfig::from_env()?; - let with_debug_namespace = state_keeper_config.save_call_traces; - let genesis_config = GenesisConfig::from_env()?; - - let mut namespaces = Namespace::DEFAULT.to_vec(); - if with_debug_namespace { - namespaces.push(Namespace::Debug) - } - namespaces.push(Namespace::Snapshots); - - let optional_config = Web3ServerOptionalConfig { - namespaces: Some(namespaces), - filters_limit: Some(rpc_config.filters_limit()), - subscriptions_limit: Some(rpc_config.subscriptions_limit()), - batch_request_size_limit: Some(rpc_config.max_batch_request_size()), - response_body_size_limit: Some(rpc_config.max_response_body_size()), - ..Default::default() - }; - self.node.add_layer(Web3ServerLayer::http( - rpc_config.http_port, - InternalApiConfig::new(&rpc_config, &contracts_config, &genesis_config), - optional_config, - )); - - Ok(self) - } - - fn add_ws_web3_api_layer(mut self) -> anyhow::Result { - let rpc_config = ApiConfig::from_env()?.web3_json_rpc; - let contracts_config = ContractsConfig::from_env()?; - let genesis_config = GenesisConfig::from_env()?; - let state_keeper_config = StateKeeperConfig::from_env()?; - let circuit_breaker_config = CircuitBreakerConfig::from_env()?; - let with_debug_namespace = state_keeper_config.save_call_traces; - - let mut namespaces = Namespace::DEFAULT.to_vec(); - if with_debug_namespace { - namespaces.push(Namespace::Debug) - } - namespaces.push(Namespace::Snapshots); - - let optional_config = Web3ServerOptionalConfig { - namespaces: Some(namespaces), - filters_limit: Some(rpc_config.filters_limit()), - subscriptions_limit: Some(rpc_config.subscriptions_limit()), - batch_request_size_limit: Some(rpc_config.max_batch_request_size()), - response_body_size_limit: Some(rpc_config.max_response_body_size()), - websocket_requests_per_minute_limit: Some( - rpc_config.websocket_requests_per_minute_limit(), - ), - replication_lag_limit: circuit_breaker_config.replication_lag_limit(), - with_extended_tracing: rpc_config.extended_api_tracing, - ..Default::default() - }; - self.node.add_layer(Web3ServerLayer::ws( - rpc_config.ws_port, - InternalApiConfig::new(&rpc_config, &contracts_config, &genesis_config), - optional_config, - )); - - Ok(self) - } - fn add_eth_sender_layer(mut self) -> anyhow::Result { - let eth_sender_config = EthConfig::from_env()?; - let contracts_config = ContractsConfig::from_env()?; - let network_config = NetworkConfig::from_env()?; - let genesis_config = GenesisConfig::from_env()?; - - self.node.add_layer(EthTxAggregatorLayer::new( - eth_sender_config.clone(), - contracts_config, - network_config.zksync_network_id, - genesis_config.l1_batch_commit_data_generator_mode, - )); - self.node - .add_layer(EthTxManagerLayer::new(eth_sender_config)); - - Ok(self) - } - - fn add_house_keeper_layer(mut self) -> anyhow::Result { - let house_keeper_config = HouseKeeperConfig::from_env()?; - let fri_prover_config = FriProverConfig::from_env()?; - let fri_witness_generator_config = FriWitnessGeneratorConfig::from_env()?; - let fri_prover_group_config = FriProverGroupConfig::from_env()?; - let fri_proof_compressor_config = FriProofCompressorConfig::from_env()?; - - self.node.add_layer(HouseKeeperLayer::new( - house_keeper_config, - fri_prover_config, - fri_witness_generator_config, - fri_prover_group_config, - fri_proof_compressor_config, - )); - - Ok(self) - } - - fn add_commitment_generator_layer(mut self) -> anyhow::Result { - let genesis = GenesisConfig::from_env()?; - self.node.add_layer(CommitmentGeneratorLayer::new( - genesis.l1_batch_commit_data_generator_mode, - )); - - Ok(self) - } - - fn add_circuit_breaker_checker_layer(mut self) -> anyhow::Result { - let circuit_breaker_config = CircuitBreakerConfig::from_env()?; - self.node - .add_layer(CircuitBreakerCheckerLayer(circuit_breaker_config)); - - Ok(self) - } - - fn add_contract_verification_api_layer(mut self) -> anyhow::Result { - let config = ContractVerifierConfig::from_env()?; - self.node.add_layer(ContractVerificationApiLayer(config)); - Ok(self) - } - - fn build(mut self) -> Result { - self.node.build() - } -} - -fn main() -> anyhow::Result<()> { - let observability_config = - ObservabilityConfig::from_env().context("ObservabilityConfig::from_env()")?; - let log_format: zksync_vlog::LogFormat = observability_config - .log_format - .parse() - .context("Invalid log format")?; - let _guard = zksync_vlog::ObservabilityBuilder::new() - .with_log_format(log_format) - .build(); - - MainNodeBuilder::new() - .add_sigint_handler_layer()? - .add_pools_layer()? - .add_circuit_breaker_checker_layer()? - .add_query_eth_client_layer()? - .add_sequencer_l1_gas_layer()? - .add_object_store_layer()? - .add_metadata_calculator_layer()? - .add_state_keeper_layer()? - .add_eth_watch_layer()? - .add_pk_signing_client_layer()? - .add_eth_sender_layer()? - .add_proof_data_handler_layer()? - .add_healthcheck_layer()? - .add_tx_sender_layer()? - .add_tree_api_client_layer()? - .add_api_caches_layer()? - .add_http_web3_api_layer()? - .add_ws_web3_api_layer()? - .add_house_keeper_layer()? - .add_commitment_generator_layer()? - .add_contract_verification_api_layer()? - .build()? - .run()?; - - Ok(()) -} diff --git a/core/node/node_framework/examples/showcase.rs b/core/node/node_framework/examples/showcase.rs index 3dbb576c1935..1cdc5e2f5a19 100644 --- a/core/node/node_framework/examples/showcase.rs +++ b/core/node/node_framework/examples/showcase.rs @@ -251,10 +251,10 @@ impl WiringLayer for TasksLayer { } fn main() -> anyhow::Result<()> { - ZkStackServiceBuilder::new() - .add_layer(DatabaseLayer) - .add_layer(TasksLayer) - .build()? - .run()?; + let mut builder = ZkStackServiceBuilder::new()?; + + builder.add_layer(DatabaseLayer).add_layer(TasksLayer); + + builder.build().run()?; Ok(()) } diff --git a/core/node/node_framework/src/service/mod.rs b/core/node/node_framework/src/service/mod.rs index 22102a60efb7..f5019be01a79 100644 --- a/core/node/node_framework/src/service/mod.rs +++ b/core/node/node_framework/src/service/mod.rs @@ -36,17 +36,37 @@ mod tests; const TASK_SHUTDOWN_TIMEOUT: Duration = Duration::from_secs(30); /// A builder for [`ZkStackService`]. -#[derive(Default, Debug)] +#[derive(Debug)] pub struct ZkStackServiceBuilder { /// List of wiring layers. // Note: It has to be a `Vec` and not e.g. `HashMap` because the order in which we // iterate through it matters. layers: Vec<(&'static str, WireFn)>, + /// Tokio runtime used to spawn tasks. + runtime: Runtime, } impl ZkStackServiceBuilder { - pub fn new() -> Self { - Self { layers: Vec::new() } + /// Creates a new builder. + /// + /// Returns an error if called within a Tokio runtime context. + pub fn new() -> Result { + if tokio::runtime::Handle::try_current().is_ok() { + return Err(ZkStackServiceError::RuntimeDetected); + } + let runtime = tokio::runtime::Builder::new_multi_thread() + .enable_all() + .build() + .unwrap(); + Ok(Self { + layers: Vec::new(), + runtime, + }) + } + + /// Returns a handle to the Tokio runtime used by the service. + pub fn runtime_handle(&self) -> tokio::runtime::Handle { + self.runtime.handle().clone() } /// Adds a wiring layer. @@ -71,28 +91,17 @@ impl ZkStackServiceBuilder { } /// Builds the service. - /// - /// In case of errors during wiring phase, will return the list of all the errors that happened, in the order - /// of their occurrence. - pub fn build(&mut self) -> Result { - if tokio::runtime::Handle::try_current().is_ok() { - return Err(ZkStackServiceError::RuntimeDetected); - } - let runtime = tokio::runtime::Builder::new_multi_thread() - .enable_all() - .build() - .unwrap(); - + pub fn build(self) -> ZkStackService { let (stop_sender, _stop_receiver) = watch::channel(false); - Ok(ZkStackService { - layers: std::mem::take(&mut self.layers), + ZkStackService { + layers: self.layers, resources: Default::default(), runnables: Default::default(), stop_sender, - runtime, + runtime: self.runtime, errors: Vec::new(), - }) + } } } @@ -120,6 +129,9 @@ type TaskFuture = NamedFuture>>>; impl ZkStackService { /// Runs the system. + /// + /// In case of errors during wiring phase, will return the list of all the errors that happened, in the order + /// of their occurrence. pub fn run(mut self) -> Result<(), ZkStackServiceError> { self.wire()?; diff --git a/core/node/node_framework/src/service/tests.rs b/core/node/node_framework/src/service/tests.rs index e801e97b7e96..4fae955201d9 100644 --- a/core/node/node_framework/src/service/tests.rs +++ b/core/node/node_framework/src/service/tests.rs @@ -16,7 +16,7 @@ fn test_new_with_nested_runtime() { let runtime = Runtime::new().unwrap(); let initialization_result = - runtime.block_on(async { ZkStackServiceBuilder::new().build().unwrap_err() }); + runtime.block_on(async { ZkStackServiceBuilder::new().unwrap_err() }); assert_matches!(initialization_result, ZkStackServiceError::RuntimeDetected); } @@ -43,7 +43,7 @@ impl WiringLayer for DefaultLayer { // `add_layer` should add multiple layers. #[test] fn test_add_layer() { - let mut zk_stack_service = ZkStackServiceBuilder::new(); + let mut zk_stack_service = ZkStackServiceBuilder::new().unwrap(); zk_stack_service .add_layer(DefaultLayer { name: "first_layer", @@ -61,7 +61,7 @@ fn test_add_layer() { // `add_layer` should ignore already added layers. #[test] fn test_layers_are_unique() { - let mut zk_stack_service = ZkStackServiceBuilder::new(); + let mut zk_stack_service = ZkStackServiceBuilder::new().unwrap(); zk_stack_service .add_layer(DefaultLayer { name: "default_layer", @@ -79,7 +79,7 @@ fn test_layers_are_unique() { // `ZkStack` Service's `run()` method has to return error if there is no tasks added. #[test] fn test_run_with_no_tasks() { - let empty_run_result = ZkStackServiceBuilder::new().build().unwrap().run(); + let empty_run_result = ZkStackServiceBuilder::new().unwrap().build().run(); assert_matches!(empty_run_result.unwrap_err(), ZkStackServiceError::NoTasks); } @@ -103,10 +103,10 @@ impl WiringLayer for WireErrorLayer { // `ZkStack` Service's `run()` method has to take into account errors on wiring step. #[test] fn test_run_with_error_tasks() { - let mut zk_stack_service = ZkStackServiceBuilder::new(); + let mut zk_stack_service = ZkStackServiceBuilder::new().unwrap(); let error_layer = WireErrorLayer; zk_stack_service.add_layer(error_layer); - let result = zk_stack_service.build().unwrap().run(); + let result = zk_stack_service.build().run(); assert_matches!(result.unwrap_err(), ZkStackServiceError::Wiring(_)); } @@ -151,9 +151,9 @@ impl Task for ErrorTask { // `ZkStack` Service's `run()` method has to take into account errors inside task execution. #[test] fn test_run_with_failed_tasks() { - let mut zk_stack_service: ZkStackServiceBuilder = ZkStackServiceBuilder::new(); + let mut zk_stack_service: ZkStackServiceBuilder = ZkStackServiceBuilder::new().unwrap(); zk_stack_service.add_layer(TaskErrorLayer); - let result = zk_stack_service.build().unwrap().run(); + let result = zk_stack_service.build().run(); assert_matches!(result.unwrap_err(), ZkStackServiceError::Task(_)); } @@ -235,7 +235,7 @@ fn test_task_run() { let successful_task_was_run = Arc::new(Mutex::new(false)); let remaining_task_was_run = Arc::new(Mutex::new(false)); - let mut zk_stack_service = ZkStackServiceBuilder::new(); + let mut zk_stack_service = ZkStackServiceBuilder::new().unwrap(); zk_stack_service.add_layer(TasksLayer { successful_task_was_run: successful_task_was_run.clone(), @@ -243,7 +243,7 @@ fn test_task_run() { }); assert!( - zk_stack_service.build().unwrap().run().is_ok(), + zk_stack_service.build().run().is_ok(), "ZkStackServiceBuilder run finished with an error, but it shouldn't" ); let res1 = *successful_task_was_run.lock().unwrap(); diff --git a/core/tests/loadnext/src/main.rs b/core/tests/loadnext/src/main.rs index 7ba6e762ea26..81185cc1c63e 100644 --- a/core/tests/loadnext/src/main.rs +++ b/core/tests/loadnext/src/main.rs @@ -6,6 +6,7 @@ use std::time::Duration; +use anyhow::Context as _; use loadnext::{ command::TxType, config::{ExecutionConfig, LoadtestConfig}, @@ -21,7 +22,7 @@ async fn main() -> anyhow::Result<()> { // We don't want to introduce dependency on `zksync_env_config` in loadnext, // but we historically rely on the environment variables for the observability configuration, // so we load them directly here. - let log_format: zksync_vlog::LogFormat = std::env::var("MISC_LOG_FORMAT") + let log_format: zksync_vlog::logs::LogFormat = std::env::var("MISC_LOG_FORMAT") .ok() .unwrap_or("plain".to_string()) .parse()?; @@ -39,14 +40,20 @@ async fn main() -> anyhow::Result<()> { } }; - let mut builder = zksync_vlog::ObservabilityBuilder::new().with_log_format(log_format); - if let Some(sentry_url) = sentry_url { - builder = builder - .with_sentry_url(&sentry_url) - .expect("Invalid Sentry URL") - .with_sentry_environment(environment); - } - let _guard = builder.build(); + let logs = zksync_vlog::Logs::from(log_format); + let sentry = sentry_url + .map(|url| { + anyhow::Ok( + zksync_vlog::Sentry::new(&url) + .context("Invalid Sentry URL")? + .with_environment(environment), + ) + }) + .transpose()?; + let _guard = zksync_vlog::ObservabilityBuilder::new() + .with_logs(Some(logs)) + .with_sentry(sentry) + .build(); let config = LoadtestConfig::from_env() .expect("Config parameters should be loaded from env or from default values"); diff --git a/etc/env/file_based/general.yaml b/etc/env/file_based/general.yaml index 7914ece95c70..34ca63e4a99c 100644 --- a/etc/env/file_based/general.yaml +++ b/etc/env/file_based/general.yaml @@ -327,14 +327,15 @@ prometheus: observability: log_format: plain log_directives: "zksync_node_test_utils=info,zksync_state_keeper=info,zksync_reorg_detector=info,zksync_consistency_checker=info,zksync_metadata_calculator=info,zksync_node_sync=info,zksync_node_consensus=info,zksync_contract_verification_server=info,zksync_node_api_server=info,zksync_tee_verifier_input_producer=info,zksync_node_framework=info,zksync_block_reverter=info,zksync_commitment_generator=info,zksync_node_db_pruner=info,zksync_eth_sender=info,zksync_node_fee_model=info,zksync_node_genesis=info,zksync_house_keeper=info,zksync_proof_data_handler=info,zksync_shared_metrics=info,zksync_node_test_utils=info,zksync_vm_runner=info,zksync_consensus_bft=info,zksync_consensus_network=info,zksync_consensus_storage=info,zksync_core_leftovers=debug,zksync_server=debug,zksync_contract_verifier=debug,zksync_dal=info,zksync_db_connection=info,zksync_eth_client=info,zksync_eth_watch=debug,zksync_storage=info,zksync_db_manager=info,zksync_merkle_tree=info,zksync_state=debug,zksync_utils=debug,zksync_queued_job_processor=info,zksync_types=info,zksync_mempool=debug,loadnext=info,vm=info,zksync_object_store=info,zksync_external_node=info,zksync_witness_generator=info,zksync_prover_fri=info,zksync_witness_vector_generator=info,zksync_web3_decl=debug,zksync_health_check=debug,zksync_proof_fri_compressor=info,vise_exporter=error,snapshots_creator=debug,zksync_base_token_adjuster=debug,zksync_external_price_api=debug" - sentry: - url: unset - panic_interval: 1800 - error_interval: 10800 - environment: localhost - opentelemetry: - endpoint: unset - level: debug + # Uncomment only if needed + # sentry: + # url: unset + # panic_interval: 1800 + # error_interval: 10800 + # environment: localhost + # opentelemetry: + # endpoint: unset + # level: debug protective_reads_writer: db_path: "./db/main/protective_reads" diff --git a/prover/Cargo.lock b/prover/Cargo.lock index 6be3ab0db106..0afe435859d6 100644 --- a/prover/Cargo.lock +++ b/prover/Cargo.lock @@ -288,18 +288,17 @@ dependencies = [ [[package]] name = "axum" -version = "0.6.20" +version = "0.7.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3b829e4e32b91e643de6eafe82b1d90675f5874230191a4ffbc1b336dec4d6bf" +checksum = "3a6c9af12842a67734c9a2e355436e5d03b22383ed60cf13cd0c18fbfe3dcbcf" dependencies = [ "async-trait", "axum-core", - "bitflags 1.3.2", "bytes", "futures-util", - "http 0.2.12", - "http-body 0.4.6", - "hyper 0.14.29", + "http 1.1.0", + "http-body 1.0.0", + "http-body-util", "itoa", "matchit", "memchr", @@ -308,7 +307,7 @@ dependencies = [ "pin-project-lite", "rustversion", "serde", - "sync_wrapper 0.1.2", + "sync_wrapper 1.0.1", "tower", "tower-layer", "tower-service", @@ -316,17 +315,20 @@ dependencies = [ [[package]] name = "axum-core" -version = "0.3.4" +version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "759fa577a247914fd3f7f76d62972792636412fbfd634cd452f6a385a74d2d2c" +checksum = "a15c63fd72d41492dc4f497196f5da1fb04fb7529e631d73630d1b491e47a2e3" dependencies = [ "async-trait", "bytes", "futures-util", - "http 0.2.12", - "http-body 0.4.6", + "http 1.1.0", + "http-body 1.0.0", + "http-body-util", "mime", + "pin-project-lite", "rustversion", + "sync_wrapper 0.1.2", "tower-layer", "tower-service", ] @@ -2726,6 +2728,7 @@ dependencies = [ "http 1.1.0", "http-body 1.0.0", "httparse", + "httpdate", "itoa", "pin-project-lite", "smallvec", @@ -2753,14 +2756,15 @@ dependencies = [ [[package]] name = "hyper-timeout" -version = "0.4.1" +version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bbb958482e8c7be4bc3cf272a766a2b0bf1a6755e7a6ae777f017a31d11b13b1" +checksum = "3203a961e5c83b6f5498933e78b6b263e208c197b63e9c6c53cc82ffd3f63793" dependencies = [ - "hyper 0.14.29", + "hyper 1.3.1", + "hyper-util", "pin-project-lite", "tokio", - "tokio-io-timeout", + "tower-service", ] [[package]] @@ -3890,43 +3894,46 @@ dependencies = [ [[package]] name = "opentelemetry" -version = "0.20.0" +version = "0.24.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9591d937bc0e6d2feb6f71a559540ab300ea49955229c347a517a28d27784c54" +checksum = "4c365a63eec4f55b7efeceb724f1336f26a9cf3427b70e59e2cd2a5b947fba96" dependencies = [ - "opentelemetry_api", - "opentelemetry_sdk", + "futures-core", + "futures-sink", + "js-sys", + "once_cell", + "pin-project-lite", + "thiserror", ] [[package]] name = "opentelemetry-http" -version = "0.9.0" +version = "0.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c7594ec0e11d8e33faf03530a4c49af7064ebba81c1480e01be67d90b356508b" +checksum = "ad31e9de44ee3538fb9d64fe3376c1362f406162434609e79aea2a41a0af78ab" dependencies = [ "async-trait", "bytes", - "http 0.2.12", - "opentelemetry_api", - "reqwest 0.11.27", + "http 1.1.0", + "opentelemetry", + "reqwest 0.12.5", ] [[package]] name = "opentelemetry-otlp" -version = "0.13.0" +version = "0.17.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7e5e5a5c4135864099f3faafbe939eb4d7f9b80ebf68a8448da961b32a7c1275" +checksum = "6b925a602ffb916fb7421276b86756027b37ee708f9dce2dbdcc51739f07e727" dependencies = [ "async-trait", "futures-core", - "http 0.2.12", + "http 1.1.0", + "opentelemetry", "opentelemetry-http", "opentelemetry-proto", - "opentelemetry-semantic-conventions", - "opentelemetry_api", "opentelemetry_sdk", - "prost 0.11.9", - "reqwest 0.11.27", + "prost 0.13.1", + "reqwest 0.12.5", "thiserror", "tokio", "tonic", @@ -3934,58 +3941,37 @@ dependencies = [ [[package]] name = "opentelemetry-proto" -version = "0.3.0" +version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b1e3f814aa9f8c905d0ee4bde026afd3b2577a97c10e1699912e3e44f0c4cbeb" +checksum = "30ee9f20bff9c984511a02f082dc8ede839e4a9bf15cc2487c8d6fea5ad850d9" dependencies = [ - "opentelemetry_api", + "opentelemetry", "opentelemetry_sdk", - "prost 0.11.9", + "prost 0.13.1", "tonic", ] [[package]] name = "opentelemetry-semantic-conventions" -version = "0.12.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "73c9f9340ad135068800e7f1b24e9e09ed9e7143f5bf8518ded3d3ec69789269" -dependencies = [ - "opentelemetry", -] - -[[package]] -name = "opentelemetry_api" -version = "0.20.0" +version = "0.16.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8a81f725323db1b1206ca3da8bb19874bbd3f57c3bcd59471bfb04525b265b9b" -dependencies = [ - "futures-channel", - "futures-util", - "indexmap 1.9.3", - "js-sys", - "once_cell", - "pin-project-lite", - "thiserror", - "urlencoding", -] +checksum = "1cefe0543875379e47eb5f1e68ff83f45cc41366a92dfd0d073d513bf68e9a05" [[package]] name = "opentelemetry_sdk" -version = "0.20.0" +version = "0.24.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fa8e705a0612d48139799fcbaba0d4a90f06277153e43dd2bdc16c6f0edd8026" +checksum = "692eac490ec80f24a17828d49b40b60f5aeaccdfe6a503f939713afd22bc28df" dependencies = [ "async-trait", - "crossbeam-channel 0.5.13", "futures-channel", "futures-executor", "futures-util", + "glob", "once_cell", - "opentelemetry_api", - "ordered-float 3.9.2", + "opentelemetry", "percent-encoding", "rand 0.8.5", - "regex", "serde_json", "thiserror", "tokio", @@ -4001,15 +3987,6 @@ dependencies = [ "num-traits", ] -[[package]] -name = "ordered-float" -version = "3.9.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f1e1c390732d15f1d48471625cd92d154e66db2c56645e29a9cd26f4699f72dc" -dependencies = [ - "num-traits", -] - [[package]] name = "os_info" version = "3.8.2" @@ -4382,22 +4359,22 @@ dependencies = [ [[package]] name = "prost" -version = "0.11.9" +version = "0.12.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0b82eaa1d779e9a4bc1c3217db8ffbeabaae1dca241bf70183242128d48681cd" +checksum = "deb1435c188b76130da55f17a466d252ff7b1418b2ad3e037d127b94e3411f29" dependencies = [ "bytes", - "prost-derive 0.11.9", + "prost-derive 0.12.6", ] [[package]] name = "prost" -version = "0.12.6" +version = "0.13.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "deb1435c188b76130da55f17a466d252ff7b1418b2ad3e037d127b94e3411f29" +checksum = "e13db3d3fde688c61e2446b4d843bc27a7e8af269a69440c0308021dc92333cc" dependencies = [ "bytes", - "prost-derive 0.12.6", + "prost-derive 0.13.1", ] [[package]] @@ -4423,25 +4400,25 @@ dependencies = [ [[package]] name = "prost-derive" -version = "0.11.9" +version = "0.12.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e5d2d8d10f3c6ded6da8b05b5fb3b8a5082514344d56c9f871412d29b4e075b4" +checksum = "81bddcdb20abf9501610992b6759a4c888aef7d1a7247ef75e2404275ac24af1" dependencies = [ "anyhow", - "itertools 0.10.5", + "itertools 0.12.1", "proc-macro2 1.0.85", "quote 1.0.36", - "syn 1.0.109", + "syn 2.0.66", ] [[package]] name = "prost-derive" -version = "0.12.6" +version = "0.13.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "81bddcdb20abf9501610992b6759a4c888aef7d1a7247ef75e2404275ac24af1" +checksum = "18bec9b0adc4eba778b33684b7ba3e7137789434769ee3ce3930463ef904cfca" dependencies = [ "anyhow", - "itertools 0.12.1", + "itertools 0.13.0", "proc-macro2 1.0.85", "quote 1.0.36", "syn 2.0.66", @@ -5434,7 +5411,7 @@ version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f3a1a3341211875ef120e117ea7fd5228530ae7e7036a779fdc9117be6b3282c" dependencies = [ - "ordered-float 2.10.1", + "ordered-float", "serde", ] @@ -6356,16 +6333,6 @@ dependencies = [ "windows-sys 0.48.0", ] -[[package]] -name = "tokio-io-timeout" -version = "1.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "30b74022ada614a1b4834de765f9bb43877f910cc8ce4be40e89042c9223a8bf" -dependencies = [ - "pin-project-lite", - "tokio", -] - [[package]] name = "tokio-macros" version = "2.3.0" @@ -6475,24 +6442,26 @@ dependencies = [ [[package]] name = "tonic" -version = "0.9.2" +version = "0.12.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3082666a3a6433f7f511c7192923fa1fe07c69332d3c6a2e6bb040b569199d5a" +checksum = "38659f4a91aba8598d27821589f5db7dddd94601e7a01b1e485a50e5484c7401" dependencies = [ + "async-stream", "async-trait", "axum", - "base64 0.21.7", + "base64 0.22.1", "bytes", - "futures-core", - "futures-util", - "h2 0.3.26", - "http 0.2.12", - "http-body 0.4.6", - "hyper 0.14.29", + "h2 0.4.5", + "http 1.1.0", + "http-body 1.0.0", + "http-body-util", + "hyper 1.3.1", "hyper-timeout", + "hyper-util", "percent-encoding", "pin-project", - "prost 0.11.9", + "prost 0.13.1", + "socket2", "tokio", "tokio-stream", "tower", @@ -6566,17 +6535,6 @@ dependencies = [ "valuable", ] -[[package]] -name = "tracing-log" -version = "0.1.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f751112709b4e791d8ce53e32c4ed2d353565a795ce84da2285393f41557bdf2" -dependencies = [ - "log", - "once_cell", - "tracing-core", -] - [[package]] name = "tracing-log" version = "0.2.0" @@ -6590,18 +6548,20 @@ dependencies = [ [[package]] name = "tracing-opentelemetry" -version = "0.21.0" +version = "0.25.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "75327c6b667828ddc28f5e3f169036cb793c3f588d83bf0f262a7f062ffed3c8" +checksum = "a9784ed4da7d921bc8df6963f8c80a0e4ce34ba6ba76668acadd3edbd985ff3b" dependencies = [ + "js-sys", "once_cell", "opentelemetry", "opentelemetry_sdk", "smallvec", "tracing", "tracing-core", - "tracing-log 0.1.4", + "tracing-log", "tracing-subscriber", + "web-time", ] [[package]] @@ -6632,7 +6592,7 @@ dependencies = [ "time", "tracing", "tracing-core", - "tracing-log 0.2.0", + "tracing-log", "tracing-serde", ] @@ -7044,6 +7004,16 @@ dependencies = [ "wasm-bindgen", ] +[[package]] +name = "web-time" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5a6580f308b1fad9207618087a65c04e7a10bc77e02c8e84e9b00dd4b12fa0bb" +dependencies = [ + "js-sys", + "wasm-bindgen", +] + [[package]] name = "webpki-roots" version = "0.26.2" @@ -7758,6 +7728,7 @@ dependencies = [ "zksync_concurrency", "zksync_consensus_utils", "zksync_crypto_primitives", + "zksync_vlog", ] [[package]] @@ -8123,6 +8094,7 @@ dependencies = [ "vk_setup_data_generator_server_fri", "zkevm_test_harness 0.150.2-rc.1", "zksync-wrapper-prover", + "zksync_config", "zksync_core_leftovers", "zksync_env_config", "zksync_object_store", @@ -8432,13 +8404,17 @@ dependencies = [ "opentelemetry", "opentelemetry-otlp", "opentelemetry-semantic-conventions", + "opentelemetry_sdk", "sentry", "serde", "serde_json", + "thiserror", + "time", "tokio", "tracing", "tracing-opentelemetry", "tracing-subscriber", + "url", "vise", "vise-exporter", ] diff --git a/prover/crates/bin/proof_fri_compressor/Cargo.toml b/prover/crates/bin/proof_fri_compressor/Cargo.toml index 0c01a40874f2..a44244c97b57 100644 --- a/prover/crates/bin/proof_fri_compressor/Cargo.toml +++ b/prover/crates/bin/proof_fri_compressor/Cargo.toml @@ -13,6 +13,7 @@ categories.workspace = true vise.workspace = true zksync_types.workspace = true zksync_prover_dal.workspace = true +zksync_config = { workspace = true, features = ["observability_ext"] } zksync_env_config.workspace = true zksync_object_store.workspace = true zksync_prover_interface.workspace = true diff --git a/prover/crates/bin/proof_fri_compressor/src/main.rs b/prover/crates/bin/proof_fri_compressor/src/main.rs index 8be498be5e00..a1a8ac90253e 100644 --- a/prover/crates/bin/proof_fri_compressor/src/main.rs +++ b/prover/crates/bin/proof_fri_compressor/src/main.rs @@ -47,28 +47,7 @@ async fn main() -> anyhow::Result<()> { .observability .expect("observability config") .clone(); - let log_format: zksync_vlog::LogFormat = observability_config - .log_format - .parse() - .context("Invalid log format")?; - - let mut builder = zksync_vlog::ObservabilityBuilder::new().with_log_format(log_format); - if let Some(sentry_url) = &observability_config.sentry_url { - builder = builder - .with_sentry_url(sentry_url) - .expect("Invalid Sentry URL") - .with_sentry_environment(observability_config.sentry_environment); - } - if let Some(opentelemetry) = observability_config.opentelemetry { - builder = builder - .with_opentelemetry( - &opentelemetry.level, - opentelemetry.endpoint, - "zksync-prover-fri-compressor".into(), - ) - .expect("Invalid OpenTelemetry config"); - } - let _guard = builder.build(); + let _observability_guard = observability_config.install()?; let config = general_config .proof_compressor_config diff --git a/prover/crates/bin/prover_fri/Cargo.toml b/prover/crates/bin/prover_fri/Cargo.toml index 4f343e8c4e91..0d2e92be0481 100644 --- a/prover/crates/bin/prover_fri/Cargo.toml +++ b/prover/crates/bin/prover_fri/Cargo.toml @@ -13,7 +13,7 @@ categories.workspace = true vise.workspace = true zksync_types.workspace = true zksync_prover_dal.workspace = true -zksync_config.workspace = true +zksync_config = { workspace = true, features = ["observability_ext"] } zksync_env_config.workspace = true zksync_vlog.workspace = true zksync_object_store.workspace = true diff --git a/prover/crates/bin/prover_fri/src/main.rs b/prover/crates/bin/prover_fri/src/main.rs index e4b2fd5a6709..db813394c194 100644 --- a/prover/crates/bin/prover_fri/src/main.rs +++ b/prover/crates/bin/prover_fri/src/main.rs @@ -63,36 +63,7 @@ async fn main() -> anyhow::Result<()> { let observability_config = general_config .observability .context("observability config")?; - let log_format: zksync_vlog::LogFormat = observability_config - .log_format - .parse() - .context("Invalid log format")?; - - let mut builder = zksync_vlog::ObservabilityBuilder::new().with_log_format(log_format); - if let Some(sentry_url) = &observability_config.sentry_url { - builder = builder - .with_sentry_url(sentry_url) - .expect("Invalid Sentry URL") - .with_sentry_environment(observability_config.sentry_environment); - } - - if let Some(opentelemetry) = observability_config.opentelemetry { - builder = builder - .with_opentelemetry( - &opentelemetry.level, - opentelemetry.endpoint, - "zksync-prover-fri".into(), - ) - .expect("Invalid OpenTelemetry config"); - } - let _guard = builder.build(); - - // Report whether sentry is running after the logging subsystem was initialized. - if let Some(sentry_url) = observability_config.sentry_url { - tracing::info!("Sentry configured with URL: {sentry_url}",); - } else { - tracing::info!("No sentry URL was provided"); - } + let _observability_guard = observability_config.install()?; let prover_config = general_config.prover_config.context("fri_prover config")?; let exporter_config = PrometheusExporterConfig::pull(prover_config.prometheus_port); diff --git a/prover/crates/bin/prover_fri_gateway/Cargo.toml b/prover/crates/bin/prover_fri_gateway/Cargo.toml index 6dd54d5d677d..8d116c4219d6 100644 --- a/prover/crates/bin/prover_fri_gateway/Cargo.toml +++ b/prover/crates/bin/prover_fri_gateway/Cargo.toml @@ -13,7 +13,7 @@ categories.workspace = true vise.workspace = true zksync_types.workspace = true zksync_prover_dal.workspace = true -zksync_config.workspace = true +zksync_config = { workspace = true, features = ["observability_ext"] } zksync_env_config.workspace = true zksync_core_leftovers.workspace = true zksync_object_store.workspace = true diff --git a/prover/crates/bin/prover_fri_gateway/src/main.rs b/prover/crates/bin/prover_fri_gateway/src/main.rs index c204fb7395f2..ed0574e7fba1 100644 --- a/prover/crates/bin/prover_fri_gateway/src/main.rs +++ b/prover/crates/bin/prover_fri_gateway/src/main.rs @@ -29,20 +29,7 @@ async fn main() -> anyhow::Result<()> { let observability_config = general_config .observability .context("observability config")?; - - let log_format: zksync_vlog::LogFormat = observability_config - .log_format - .parse() - .context("Invalid log format")?; - - let mut builder = zksync_vlog::ObservabilityBuilder::new().with_log_format(log_format); - if let Some(sentry_url) = &observability_config.sentry_url { - builder = builder - .with_sentry_url(sentry_url) - .expect("Invalid Sentry URL") - .with_sentry_environment(observability_config.sentry_environment); - } - let _guard = builder.build(); + let _observability_guard = observability_config.install()?; let config = general_config .prover_gateway diff --git a/prover/crates/bin/witness_generator/Cargo.toml b/prover/crates/bin/witness_generator/Cargo.toml index 64c6713540fa..fe73a02ba2af 100644 --- a/prover/crates/bin/witness_generator/Cargo.toml +++ b/prover/crates/bin/witness_generator/Cargo.toml @@ -12,7 +12,7 @@ categories.workspace = true [dependencies] vise.workspace = true zksync_prover_dal.workspace = true -zksync_config.workspace = true +zksync_config = { workspace = true, features = ["observability_ext"] } zksync_prover_interface.workspace = true zksync_env_config.workspace = true zksync_system_constants.workspace = true diff --git a/prover/crates/bin/witness_generator/src/main.rs b/prover/crates/bin/witness_generator/src/main.rs index d337778aba6c..38b2e46ef74b 100644 --- a/prover/crates/bin/witness_generator/src/main.rs +++ b/prover/crates/bin/witness_generator/src/main.rs @@ -77,35 +77,7 @@ async fn main() -> anyhow::Result<()> { let observability_config = general_config .observability .context("observability config")?; - let log_format: zksync_vlog::LogFormat = observability_config - .log_format - .parse() - .context("Invalid log format")?; - - let mut builder = zksync_vlog::ObservabilityBuilder::new().with_log_format(log_format); - if let Some(sentry_url) = &observability_config.sentry_url { - builder = builder - .with_sentry_url(sentry_url) - .expect("Invalid Sentry URL") - .with_sentry_environment(observability_config.sentry_environment); - } - if let Some(opentelemetry) = observability_config.opentelemetry { - builder = builder - .with_opentelemetry( - &opentelemetry.level, - opentelemetry.endpoint, - "zksync-witness-generator".into(), - ) - .expect("Invalid OpenTelemetry config"); - } - let _guard = builder.build(); - - // Report whether sentry is running after the logging subsystem was initialized. - if let Some(sentry_url) = observability_config.sentry_url { - tracing::info!("Sentry configured with URL: {sentry_url}",); - } else { - tracing::info!("No sentry URL was provided"); - } + let _observability_guard = observability_config.install()?; let started_at = Instant::now(); let use_push_gateway = opt.batch_size.is_some(); diff --git a/prover/crates/bin/witness_vector_generator/Cargo.toml b/prover/crates/bin/witness_vector_generator/Cargo.toml index e8edecdf87b3..6a1d0af861c6 100644 --- a/prover/crates/bin/witness_vector_generator/Cargo.toml +++ b/prover/crates/bin/witness_vector_generator/Cargo.toml @@ -13,7 +13,7 @@ categories.workspace = true vise.workspace = true zksync_types.workspace = true zksync_prover_dal.workspace = true -zksync_config.workspace = true +zksync_config = { workspace = true, features = ["observability_ext"] } zksync_env_config.workspace = true zksync_object_store.workspace = true zksync_prover_fri_utils.workspace = true diff --git a/prover/crates/bin/witness_vector_generator/src/main.rs b/prover/crates/bin/witness_vector_generator/src/main.rs index 4451788ca9a4..1d3113ebf1aa 100644 --- a/prover/crates/bin/witness_vector_generator/src/main.rs +++ b/prover/crates/bin/witness_vector_generator/src/main.rs @@ -48,28 +48,7 @@ async fn main() -> anyhow::Result<()> { let observability_config = general_config .observability .context("observability config")?; - let log_format: zksync_vlog::LogFormat = observability_config - .log_format - .parse() - .context("Invalid log format")?; - - let mut builder = zksync_vlog::ObservabilityBuilder::new().with_log_format(log_format); - if let Some(sentry_url) = &observability_config.sentry_url { - builder = builder - .with_sentry_url(sentry_url) - .expect("Invalid Sentry URL") - .with_sentry_environment(observability_config.sentry_environment); - } - if let Some(opentelemetry) = observability_config.opentelemetry { - builder = builder - .with_opentelemetry( - &opentelemetry.level, - opentelemetry.endpoint, - "zksync-witness-vector-generator".into(), - ) - .expect("Invalid OpenTelemetry config"); - } - let _guard = builder.build(); + let _observability_guard = observability_config.install()?; let config = general_config .witness_vector_generator diff --git a/zk_toolbox/Cargo.lock b/zk_toolbox/Cargo.lock index 9d738fdf7231..375e35b060c2 100644 --- a/zk_toolbox/Cargo.lock +++ b/zk_toolbox/Cargo.lock @@ -151,6 +151,28 @@ dependencies = [ "term", ] +[[package]] +name = "async-stream" +version = "0.3.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cd56dd203fef61ac097dd65721a419ddccb106b2d2b70ba60a6b529f03961a51" +dependencies = [ + "async-stream-impl", + "futures-core", + "pin-project-lite", +] + +[[package]] +name = "async-stream-impl" +version = "0.3.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "16e62a023e7c117e27523144c5d2459f4397fcc3cab0085af8e2224f643a0193" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.68", +] + [[package]] name = "async-trait" version = "0.1.80" @@ -207,18 +229,17 @@ checksum = "0c4b4d0bd25bd0b74681c0ad21497610ce1b7c91b1022cd21c80c6fbdd9476b0" [[package]] name = "axum" -version = "0.6.20" +version = "0.7.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3b829e4e32b91e643de6eafe82b1d90675f5874230191a4ffbc1b336dec4d6bf" +checksum = "3a6c9af12842a67734c9a2e355436e5d03b22383ed60cf13cd0c18fbfe3dcbcf" dependencies = [ "async-trait", "axum-core", - "bitflags 1.3.2", "bytes", "futures-util", - "http 0.2.12", - "http-body 0.4.6", - "hyper 0.14.29", + "http 1.1.0", + "http-body 1.0.0", + "http-body-util", "itoa", "matchit", "memchr", @@ -227,7 +248,7 @@ dependencies = [ "pin-project-lite", "rustversion", "serde", - "sync_wrapper 0.1.2", + "sync_wrapper 1.0.1", "tower", "tower-layer", "tower-service", @@ -235,17 +256,20 @@ dependencies = [ [[package]] name = "axum-core" -version = "0.3.4" +version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "759fa577a247914fd3f7f76d62972792636412fbfd634cd452f6a385a74d2d2c" +checksum = "a15c63fd72d41492dc4f497196f5da1fb04fb7529e631d73630d1b491e47a2e3" dependencies = [ "async-trait", "bytes", "futures-util", - "http 0.2.12", - "http-body 0.4.6", + "http 1.1.0", + "http-body 1.0.0", + "http-body-util", "mime", + "pin-project-lite", "rustversion", + "sync_wrapper 0.1.2", "tower-layer", "tower-service", ] @@ -765,15 +789,6 @@ dependencies = [ "cfg-if", ] -[[package]] -name = "crossbeam-channel" -version = "0.5.13" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "33480d6946193aa8033910124896ca395333cae7e2d1113d1fef6c3272217df2" -dependencies = [ - "crossbeam-utils", -] - [[package]] name = "crossbeam-deque" version = "0.8.5" @@ -2121,6 +2136,7 @@ dependencies = [ "http 1.1.0", "http-body 1.0.0", "httparse", + "httpdate", "itoa", "pin-project-lite", "smallvec", @@ -2161,14 +2177,15 @@ dependencies = [ [[package]] name = "hyper-timeout" -version = "0.4.1" +version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bbb958482e8c7be4bc3cf272a766a2b0bf1a6755e7a6ae777f017a31d11b13b1" +checksum = "3203a961e5c83b6f5498933e78b6b263e208c197b63e9c6c53cc82ffd3f63793" dependencies = [ - "hyper 0.14.29", + "hyper 1.4.0", + "hyper-util", "pin-project-lite", "tokio", - "tokio-io-timeout", + "tower-service", ] [[package]] @@ -3006,43 +3023,46 @@ dependencies = [ [[package]] name = "opentelemetry" -version = "0.20.0" +version = "0.24.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9591d937bc0e6d2feb6f71a559540ab300ea49955229c347a517a28d27784c54" +checksum = "4c365a63eec4f55b7efeceb724f1336f26a9cf3427b70e59e2cd2a5b947fba96" dependencies = [ - "opentelemetry_api", - "opentelemetry_sdk", + "futures-core", + "futures-sink", + "js-sys", + "once_cell", + "pin-project-lite", + "thiserror", ] [[package]] name = "opentelemetry-http" -version = "0.9.0" +version = "0.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c7594ec0e11d8e33faf03530a4c49af7064ebba81c1480e01be67d90b356508b" +checksum = "ad31e9de44ee3538fb9d64fe3376c1362f406162434609e79aea2a41a0af78ab" dependencies = [ "async-trait", "bytes", - "http 0.2.12", - "opentelemetry_api", - "reqwest 0.11.27", + "http 1.1.0", + "opentelemetry", + "reqwest 0.12.5", ] [[package]] name = "opentelemetry-otlp" -version = "0.13.0" +version = "0.17.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7e5e5a5c4135864099f3faafbe939eb4d7f9b80ebf68a8448da961b32a7c1275" +checksum = "6b925a602ffb916fb7421276b86756027b37ee708f9dce2dbdcc51739f07e727" dependencies = [ "async-trait", "futures-core", - "http 0.2.12", + "http 1.1.0", + "opentelemetry", "opentelemetry-http", "opentelemetry-proto", - "opentelemetry-semantic-conventions", - "opentelemetry_api", "opentelemetry_sdk", - "prost 0.11.9", - "reqwest 0.11.27", + "prost 0.13.1", + "reqwest 0.12.5", "thiserror", "tokio", "tonic", @@ -3050,58 +3070,37 @@ dependencies = [ [[package]] name = "opentelemetry-proto" -version = "0.3.0" +version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b1e3f814aa9f8c905d0ee4bde026afd3b2577a97c10e1699912e3e44f0c4cbeb" +checksum = "30ee9f20bff9c984511a02f082dc8ede839e4a9bf15cc2487c8d6fea5ad850d9" dependencies = [ - "opentelemetry_api", + "opentelemetry", "opentelemetry_sdk", - "prost 0.11.9", + "prost 0.13.1", "tonic", ] [[package]] name = "opentelemetry-semantic-conventions" -version = "0.12.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "73c9f9340ad135068800e7f1b24e9e09ed9e7143f5bf8518ded3d3ec69789269" -dependencies = [ - "opentelemetry", -] - -[[package]] -name = "opentelemetry_api" -version = "0.20.0" +version = "0.16.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8a81f725323db1b1206ca3da8bb19874bbd3f57c3bcd59471bfb04525b265b9b" -dependencies = [ - "futures-channel", - "futures-util", - "indexmap 1.9.3", - "js-sys", - "once_cell", - "pin-project-lite", - "thiserror", - "urlencoding", -] +checksum = "1cefe0543875379e47eb5f1e68ff83f45cc41366a92dfd0d073d513bf68e9a05" [[package]] name = "opentelemetry_sdk" -version = "0.20.0" +version = "0.24.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fa8e705a0612d48139799fcbaba0d4a90f06277153e43dd2bdc16c6f0edd8026" +checksum = "692eac490ec80f24a17828d49b40b60f5aeaccdfe6a503f939713afd22bc28df" dependencies = [ "async-trait", - "crossbeam-channel", "futures-channel", "futures-executor", "futures-util", + "glob", "once_cell", - "opentelemetry_api", - "ordered-float 3.9.2", + "opentelemetry", "percent-encoding", "rand", - "regex", "serde_json", "thiserror", "tokio", @@ -3123,15 +3122,6 @@ dependencies = [ "num-traits", ] -[[package]] -name = "ordered-float" -version = "3.9.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f1e1c390732d15f1d48471625cd92d154e66db2c56645e29a9cd26f4699f72dc" -dependencies = [ - "num-traits", -] - [[package]] name = "os_info" version = "3.8.2" @@ -3524,22 +3514,22 @@ dependencies = [ [[package]] name = "prost" -version = "0.11.9" +version = "0.12.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0b82eaa1d779e9a4bc1c3217db8ffbeabaae1dca241bf70183242128d48681cd" +checksum = "deb1435c188b76130da55f17a466d252ff7b1418b2ad3e037d127b94e3411f29" dependencies = [ "bytes", - "prost-derive 0.11.9", + "prost-derive 0.12.6", ] [[package]] name = "prost" -version = "0.12.6" +version = "0.13.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "deb1435c188b76130da55f17a466d252ff7b1418b2ad3e037d127b94e3411f29" +checksum = "e13db3d3fde688c61e2446b4d843bc27a7e8af269a69440c0308021dc92333cc" dependencies = [ "bytes", - "prost-derive 0.12.6", + "prost-derive 0.13.1", ] [[package]] @@ -3565,22 +3555,22 @@ dependencies = [ [[package]] name = "prost-derive" -version = "0.11.9" +version = "0.12.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e5d2d8d10f3c6ded6da8b05b5fb3b8a5082514344d56c9f871412d29b4e075b4" +checksum = "81bddcdb20abf9501610992b6759a4c888aef7d1a7247ef75e2404275ac24af1" dependencies = [ "anyhow", - "itertools 0.10.5", + "itertools 0.12.1", "proc-macro2", "quote", - "syn 1.0.109", + "syn 2.0.68", ] [[package]] name = "prost-derive" -version = "0.12.6" +version = "0.13.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "81bddcdb20abf9501610992b6759a4c888aef7d1a7247ef75e2404275ac24af1" +checksum = "18bec9b0adc4eba778b33684b7ba3e7137789434769ee3ce3930463ef904cfca" dependencies = [ "anyhow", "itertools 0.12.1", @@ -4405,7 +4395,7 @@ version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f3a1a3341211875ef120e117ea7fd5228530ae7e7036a779fdc9117be6b3282c" dependencies = [ - "ordered-float 2.10.1", + "ordered-float", "serde", ] @@ -5217,16 +5207,6 @@ dependencies = [ "windows-sys 0.48.0", ] -[[package]] -name = "tokio-io-timeout" -version = "1.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "30b74022ada614a1b4834de765f9bb43877f910cc8ce4be40e89042c9223a8bf" -dependencies = [ - "pin-project-lite", - "tokio", -] - [[package]] name = "tokio-macros" version = "2.3.0" @@ -5366,24 +5346,26 @@ dependencies = [ [[package]] name = "tonic" -version = "0.9.2" +version = "0.12.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3082666a3a6433f7f511c7192923fa1fe07c69332d3c6a2e6bb040b569199d5a" +checksum = "38659f4a91aba8598d27821589f5db7dddd94601e7a01b1e485a50e5484c7401" dependencies = [ + "async-stream", "async-trait", "axum", - "base64 0.21.7", + "base64 0.22.1", "bytes", - "futures-core", - "futures-util", - "h2 0.3.26", - "http 0.2.12", - "http-body 0.4.6", - "hyper 0.14.29", + "h2 0.4.5", + "http 1.1.0", + "http-body 1.0.0", + "http-body-util", + "hyper 1.4.0", "hyper-timeout", + "hyper-util", "percent-encoding", "pin-project", - "prost 0.11.9", + "prost 0.13.1", + "socket2", "tokio", "tokio-stream", "tower", @@ -5467,17 +5449,6 @@ dependencies = [ "tracing", ] -[[package]] -name = "tracing-log" -version = "0.1.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f751112709b4e791d8ce53e32c4ed2d353565a795ce84da2285393f41557bdf2" -dependencies = [ - "log", - "once_cell", - "tracing-core", -] - [[package]] name = "tracing-log" version = "0.2.0" @@ -5491,18 +5462,20 @@ dependencies = [ [[package]] name = "tracing-opentelemetry" -version = "0.21.0" +version = "0.25.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "75327c6b667828ddc28f5e3f169036cb793c3f588d83bf0f262a7f062ffed3c8" +checksum = "a9784ed4da7d921bc8df6963f8c80a0e4ce34ba6ba76668acadd3edbd985ff3b" dependencies = [ + "js-sys", "once_cell", "opentelemetry", "opentelemetry_sdk", "smallvec", "tracing", "tracing-core", - "tracing-log 0.1.4", + "tracing-log", "tracing-subscriber", + "web-time", ] [[package]] @@ -5533,7 +5506,7 @@ dependencies = [ "time", "tracing", "tracing-core", - "tracing-log 0.2.0", + "tracing-log", "tracing-serde", ] @@ -5909,6 +5882,16 @@ dependencies = [ "wasm-bindgen", ] +[[package]] +name = "web-time" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5a6580f308b1fad9207618087a65c04e7a10bc77e02c8e84e9b00dd4b12fa0bb" +dependencies = [ + "js-sys", + "wasm-bindgen", +] + [[package]] name = "webpki-roots" version = "0.25.4" @@ -6572,13 +6555,17 @@ dependencies = [ "opentelemetry", "opentelemetry-otlp", "opentelemetry-semantic-conventions", + "opentelemetry_sdk", "sentry", "serde", "serde_json", + "thiserror", + "time", "tokio", "tracing", "tracing-opentelemetry", "tracing-subscriber", + "url", "vise", "vise-exporter", ]