diff --git a/Cargo.toml b/Cargo.toml index f1f5d87..6033d1d 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,3 +1,4 @@ [workspace] +resolver = "2" members = ["abci", "proto-compiler", "proto"] diff --git a/abci/Cargo.toml b/abci/Cargo.toml index 2b8b8e7..cf2aea9 100644 --- a/abci/Cargo.toml +++ b/abci/Cargo.toml @@ -23,14 +23,14 @@ server = [ crypto = ["dep:lhash"] tcp = ["server"] unix = ["server"] -tracing-span = ["dep:uuid"] +tracing-span = ["dep:uuid", "dep:lhash", "lhash/md5"] [[example]] name = "echo_socket" required-features = ["server"] [dependencies] -uuid = { version = "1.4.1", features = ["v4", "fast-rng"], optional = true } +uuid = { version = "1.4.1", default-features = false, optional = true } tenderdash-proto = { version = "0.13.0", path = "../proto" } bytes = { version = "1.0" } prost = { version = "0.11" } diff --git a/abci/src/application.rs b/abci/src/application.rs index 914373d..c8f150a 100644 --- a/abci/src/application.rs +++ b/abci/src/application.rs @@ -151,7 +151,7 @@ pub trait RequestDispatcher { impl RequestDispatcher for A { fn handle(&self, request: abci::Request) -> Option { #[cfg(feature = "tracing-span")] - let _span = super::tracing_span::span(request.clone().value?); + let _span = super::tracing_span::span(&request); tracing::trace!(?request, "received ABCI request"); let response: response::Value = match request.value? { diff --git a/abci/src/tracing_span.rs b/abci/src/tracing_span.rs index 96d58fa..cc44bcc 100644 --- a/abci/src/tracing_span.rs +++ b/abci/src/tracing_span.rs @@ -1,4 +1,5 @@ -use tenderdash_proto::abci::request::Value; +use prost::Message; +use tenderdash_proto::abci::{self, request::Value}; use tracing::Level; const SPAN_NAME: &str = "abci"; @@ -20,16 +21,18 @@ macro_rules! block_span { /// /// This function creates a new `tracing::span::EnteredSpan` based on the /// provided request. It uses the request to determine the endpoint and includes -/// a unique request ID in the span. +/// a request ID in the span. +/// +/// Request ID is deterministic and is based on the request value. It is +/// not guaranteed to be unique, as the same request can be sent multiple times. +/// However, it should be the same on all nodes for the same request. /// /// The level of the span is set to ERROR, so it will be included on all log /// levels. /// /// # Arguments /// -/// * `request` - A value that can be converted into a `Value`. Depending on the -/// specific variant of `Value`, additional information like height, round, or -/// path might be included in the span. +/// * `request` - request to create a span for. /// /// # Returns /// @@ -38,20 +41,28 @@ macro_rules! block_span { /// # Examples /// /// ``` -/// # use tenderdash_proto::abci::{RequestInfo, request}; +/// # use tenderdash_proto::abci::{RequestInfo, Request, request::Value}; /// # use tenderdash_abci::tracing_span::span; /// -/// let request = request::Value::Info(RequestInfo::default()); -/// let span = span(request); +/// let request = Request { +/// value: Some(Value::Info(Default::default())), +/// }; +/// let span = span(&request); /// ``` -pub fn span(request: T) -> tracing::span::EnteredSpan +pub fn span(request: &abci::Request) -> tracing::span::EnteredSpan where - T: Into, { - let value = request.into(); + let value = request.value.as_ref().expect("request value is missing"); + + // we use md5 as we need 16-byte request id for uuid, and it doesn't have to be + // cryptographically secure + let mut md5 = lhash::Md5::new(); + md5.update(&request.encode_to_vec()); + let request_id = uuid::Uuid::from_bytes(md5.result()) + .as_hyphenated() + .to_string(); - let endpoint = abci_method_name(&value); - let request_id = uuid::Uuid::new_v4().to_string(); + let endpoint = abci_method_name(value); let span = match value { Value::Info(_r) => tracing::span!(LEVEL, SPAN_NAME, endpoint, request_id), diff --git a/proto-compiler/src/functions.rs b/proto-compiler/src/functions.rs index fb73454..857a49d 100644 --- a/proto-compiler/src/functions.rs +++ b/proto-compiler/src/functions.rs @@ -142,7 +142,7 @@ pub fn abci_version>(dir: T) -> String { let contents = read_to_string(&file_path).expect("cannot read version/version.go"); use regex::Regex; - let re = Regex::new(r##"(?m)^\s+ABCISemVer\s*=\s*"([^"]+)"\s+*$"##).unwrap(); + let re = Regex::new(r#"(?m)^\s+ABCISemVer\s*=\s*"([^"]+)"\s+*$"#).unwrap(); let captures = re .captures(&contents) .expect("cannot find ABCISemVer in version/version.go");