diff --git a/bottlecap/Cargo.lock b/bottlecap/Cargo.lock index c64786b3b..568bd6659 100644 --- a/bottlecap/Cargo.lock +++ b/bottlecap/Cargo.lock @@ -893,7 +893,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "39cab71617ae0d63f51a36d69f866391735b51691dbda63cf6f96d042b63efeb" dependencies = [ "libc", - "windows-sys 0.61.2", + "windows-sys 0.52.0", ] [[package]] @@ -1159,19 +1159,6 @@ dependencies = [ "wasm-bindgen", ] -[[package]] -name = "getrandom" -version = "0.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "139ef39800118c7683f2fd3c98c1b23c09ae076556b435f8e9064ae108aaeeec" -dependencies = [ - "cfg-if", - "libc", - "r-efi", - "wasip2", - "wasip3", -] - [[package]] name = "glob" version = "0.3.3" @@ -1597,12 +1584,6 @@ dependencies = [ "zerovec", ] -[[package]] -name = "id-arena" -version = "2.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3d3067d79b975e8844ca9eb072e16b31c3c1c36928edf9c6789548c524d0d954" - [[package]] name = "idna" version = "1.1.0" @@ -1642,8 +1623,6 @@ checksum = "7714e70437a7dc3ac8eb7e6f8df75fd8eb422675fc7678aff7364301092b1017" dependencies = [ "equivalent", "hashbrown 0.16.1", - "serde", - "serde_core", ] [[package]] @@ -1767,12 +1746,6 @@ version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" -[[package]] -name = "leb128fmt" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "09edd9e8b54e49e587e4f6295a7d29c3ea94d469cb40ab8ca70b288248a81db2" - [[package]] name = "levenshtein" version = "1.0.5" @@ -2916,7 +2889,7 @@ dependencies = [ "errno", "libc", "linux-raw-sys 0.11.0", - "windows-sys 0.61.2", + "windows-sys 0.52.0", ] [[package]] @@ -3069,12 +3042,6 @@ dependencies = [ "libc", ] -[[package]] -name = "semver" -version = "1.0.27" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d767eb0aabc880b29956c35734170f26ed551a859dbd361d140cdbeca61ab1e2" - [[package]] name = "serde" version = "1.0.228" @@ -3420,10 +3387,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0136791f7c95b1f6dd99f9cc786b91bb81c3800b639b3478e561ddb7be95e5f1" dependencies = [ "fastrand", - "getrandom 0.4.1", + "getrandom 0.3.4", "once_cell", "rustix 1.1.3", - "windows-sys 0.61.2", + "windows-sys 0.52.0", ] [[package]] @@ -3985,16 +3952,7 @@ version = "1.0.1+wasi-0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0562428422c63773dad2c345a1882263bbf4d65cf3f42e90921f787ef5ad58e7" dependencies = [ - "wit-bindgen 0.46.0", -] - -[[package]] -name = "wasip3" -version = "0.4.0+wasi-0.3.0-rc-2026-01-06" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5428f8bf88ea5ddc08faddef2ac4a67e390b88186c703ce6dbd955e1c145aca5" -dependencies = [ - "wit-bindgen 0.51.0", + "wit-bindgen", ] [[package]] @@ -4056,40 +4014,6 @@ dependencies = [ "unicode-ident", ] -[[package]] -name = "wasm-encoder" -version = "0.244.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "990065f2fe63003fe337b932cfb5e3b80e0b4d0f5ff650e6985b1048f62c8319" -dependencies = [ - "leb128fmt", - "wasmparser", -] - -[[package]] -name = "wasm-metadata" -version = "0.244.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bb0e353e6a2fbdc176932bbaab493762eb1255a7900fe0fea1a2f96c296cc909" -dependencies = [ - "anyhow", - "indexmap 2.13.0", - "wasm-encoder", - "wasmparser", -] - -[[package]] -name = "wasmparser" -version = "0.244.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "47b807c72e1bac69382b3a6fb3dbe8ea4c0ed87ff5629b8685ae6b9a611028fe" -dependencies = [ - "bitflags 2.10.0", - "hashbrown 0.15.5", - "indexmap 2.13.0", - "semver", -] - [[package]] name = "web-sys" version = "0.3.85" @@ -4162,7 +4086,7 @@ version = "0.1.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c2a7b1c03c876122aa43f3020e6c3c3ee5c05081c9a00739faf7503aeba10d22" dependencies = [ - "windows-sys 0.61.2", + "windows-sys 0.52.0", ] [[package]] @@ -4348,94 +4272,6 @@ version = "0.46.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f17a85883d4e6d00e8a97c586de764dabcc06133f7f1d55dce5cdc070ad7fe59" -[[package]] -name = "wit-bindgen" -version = "0.51.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d7249219f66ced02969388cf2bb044a09756a083d0fab1e566056b04d9fbcaa5" -dependencies = [ - "wit-bindgen-rust-macro", -] - -[[package]] -name = "wit-bindgen-core" -version = "0.51.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ea61de684c3ea68cb082b7a88508a8b27fcc8b797d738bfc99a82facf1d752dc" -dependencies = [ - "anyhow", - "heck", - "wit-parser", -] - -[[package]] -name = "wit-bindgen-rust" -version = "0.51.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b7c566e0f4b284dd6561c786d9cb0142da491f46a9fbed79ea69cdad5db17f21" -dependencies = [ - "anyhow", - "heck", - "indexmap 2.13.0", - "prettyplease", - "syn 2.0.115", - "wasm-metadata", - "wit-bindgen-core", - "wit-component", -] - -[[package]] -name = "wit-bindgen-rust-macro" -version = "0.51.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0c0f9bfd77e6a48eccf51359e3ae77140a7f50b1e2ebfe62422d8afdaffab17a" -dependencies = [ - "anyhow", - "prettyplease", - "proc-macro2", - "quote", - "syn 2.0.115", - "wit-bindgen-core", - "wit-bindgen-rust", -] - -[[package]] -name = "wit-component" -version = "0.244.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9d66ea20e9553b30172b5e831994e35fbde2d165325bec84fc43dbf6f4eb9cb2" -dependencies = [ - "anyhow", - "bitflags 2.10.0", - "indexmap 2.13.0", - "log", - "serde", - "serde_derive", - "serde_json", - "wasm-encoder", - "wasm-metadata", - "wasmparser", - "wit-parser", -] - -[[package]] -name = "wit-parser" -version = "0.244.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ecc8ac4bc1dc3381b7f59c34f00b67e18f910c2c0f50015669dde7def656a736" -dependencies = [ - "anyhow", - "id-arena", - "indexmap 2.13.0", - "log", - "semver", - "serde", - "serde_derive", - "serde_json", - "unicode-xid", - "wasmparser", -] - [[package]] name = "writeable" version = "0.6.2" diff --git a/bottlecap/LICENSE-3rdparty.csv b/bottlecap/LICENSE-3rdparty.csv index 383854dff..85e333834 100644 --- a/bottlecap/LICENSE-3rdparty.csv +++ b/bottlecap/LICENSE-3rdparty.csv @@ -66,7 +66,6 @@ h2,https://github.com/hyperium/h2,MIT,"Carl Lerche , Sean McA hashbrown,https://github.com/rust-lang/hashbrown,MIT OR Apache-2.0,Amanieu d'Antras headers,https://github.com/hyperium/headers,MIT,Sean McArthur headers-core,https://github.com/hyperium/headers,MIT,Sean McArthur -heck,https://github.com/withoutboats/heck,MIT OR Apache-2.0,The heck Authors hex,https://github.com/KokaKiwi/rust-hex,MIT OR Apache-2.0,KokaKiwi hmac,https://github.com/RustCrypto/MACs,MIT OR Apache-2.0,RustCrypto Developers http,https://github.com/hyperium/http,MIT OR Apache-2.0,"Alex Crichton , Carl Lerche , Sean McArthur " @@ -86,7 +85,6 @@ icu_normalizer_data,https://github.com/unicode-org/icu4x,Unicode-3.0,The ICU4X P icu_properties,https://github.com/unicode-org/icu4x,Unicode-3.0,The ICU4X Project Developers icu_properties_data,https://github.com/unicode-org/icu4x,Unicode-3.0,The ICU4X Project Developers icu_provider,https://github.com/unicode-org/icu4x,Unicode-3.0,The ICU4X Project Developers -id-arena,https://github.com/fitzgen/id-arena,MIT OR Apache-2.0,"Nick Fitzgerald , Aleksey Kladov " idna,https://github.com/servo/rust-url,MIT OR Apache-2.0,The rust-url developers idna_adapter,https://github.com/hsivonen/idna_adapter,Apache-2.0 OR MIT,The rust-url developers indexmap,https://github.com/bluss/indexmap,Apache-2.0 OR MIT,The indexmap Authors @@ -99,7 +97,6 @@ itoa,https://github.com/dtolnay/itoa,MIT OR Apache-2.0,David Tolnay js-sys,https://github.com/wasm-bindgen/wasm-bindgen/tree/master/crates/js-sys,MIT OR Apache-2.0,The wasm-bindgen Developers lazy_static,https://github.com/rust-lang-nursery/lazy-static.rs,MIT OR Apache-2.0,Marvin Löbel -leb128fmt,https://github.com/bluk/leb128fmt,MIT OR Apache-2.0,Bryant Luk libc,https://github.com/rust-lang/libc,MIT OR Apache-2.0,The Rust Project Developers libdd-common,https://github.com/DataDog/libdatadog/tree/main/datadog-common,Apache-2.0,The libdd-common Authors libdd-ddsketch,https://github.com/DataDog/libdatadog/tree/main/libdd-ddsketch,Apache-2.0,The libdd-ddsketch Authors @@ -147,7 +144,6 @@ pin-utils,https://github.com/rust-lang-nursery/pin-utils,MIT OR Apache-2.0,Josef potential_utf,https://github.com/unicode-org/icu4x,Unicode-3.0,The ICU4X Project Developers powerfmt,https://github.com/jhpratt/powerfmt,MIT OR Apache-2.0,Jacob Pratt ppv-lite86,https://github.com/cryptocorrosion/cryptocorrosion,MIT OR Apache-2.0,The CryptoCorrosion Contributors -prettyplease,https://github.com/dtolnay/prettyplease,MIT OR Apache-2.0,David Tolnay proc-macro2,https://github.com/dtolnay/proc-macro2,MIT OR Apache-2.0,"David Tolnay , Alex Crichton " proc-macro2-diagnostics,https://github.com/SergioBenitez/proc-macro2-diagnostics,MIT OR Apache-2.0,Sergio Benitez prost,https://github.com/tokio-rs/prost,Apache-2.0,"Dan Burkert , Lucio Franco , Casper Meijn , Tokio Contributors " @@ -186,7 +182,6 @@ schannel,https://github.com/steffengy/schannel-rs,MIT,"Steven Fackler , Kornel " security-framework-sys,https://github.com/kornelski/rust-security-framework,MIT OR Apache-2.0,"Steven Fackler , Kornel " -semver,https://github.com/dtolnay/semver,MIT OR Apache-2.0,David Tolnay serde,https://github.com/serde-rs/serde,MIT OR Apache-2.0,"Erick Tryzelaar , David Tolnay " serde-aux,https://github.com/iddm/serde-aux,MIT,Victor Polevoy serde-value,https://github.com/arcnmx/serde-value,MIT,arcnmx @@ -258,15 +253,11 @@ value-bag,https://github.com/sval-rs/value-bag,Apache-2.0 OR MIT,Ashley Mannix < want,https://github.com/seanmonstar/want,MIT,Sean McArthur wasi,https://github.com/bytecodealliance/wasi,Apache-2.0 WITH LLVM-exception OR Apache-2.0 OR MIT,The Cranelift Project Developers wasip2,https://github.com/bytecodealliance/wasi-rs,Apache-2.0 WITH LLVM-exception OR Apache-2.0 OR MIT,The wasip2 Authors -wasip3,https://github.com/bytecodealliance/wasi-rs,Apache-2.0 WITH LLVM-exception OR Apache-2.0 OR MIT,The wasip3 Authors wasm-bindgen,https://github.com/wasm-bindgen/wasm-bindgen,MIT OR Apache-2.0,The wasm-bindgen Developers wasm-bindgen-futures,https://github.com/wasm-bindgen/wasm-bindgen/tree/master/crates/futures,MIT OR Apache-2.0,The wasm-bindgen Developers wasm-bindgen-macro,https://github.com/wasm-bindgen/wasm-bindgen/tree/master/crates/macro,MIT OR Apache-2.0,The wasm-bindgen Developers wasm-bindgen-macro-support,https://github.com/wasm-bindgen/wasm-bindgen/tree/master/crates/macro-support,MIT OR Apache-2.0,The wasm-bindgen Developers wasm-bindgen-shared,https://github.com/wasm-bindgen/wasm-bindgen/tree/master/crates/shared,MIT OR Apache-2.0,The wasm-bindgen Developers -wasm-encoder,https://github.com/bytecodealliance/wasm-tools/tree/main/crates/wasm-encoder,Apache-2.0 WITH LLVM-exception OR Apache-2.0 OR MIT,Nick Fitzgerald -wasm-metadata,https://github.com/bytecodealliance/wasm-tools/tree/main/crates/wasm-metadata,Apache-2.0 WITH LLVM-exception OR Apache-2.0 OR MIT,The wasm-metadata Authors -wasmparser,https://github.com/bytecodealliance/wasm-tools/tree/main/crates/wasmparser,Apache-2.0 WITH LLVM-exception OR Apache-2.0 OR MIT,Yury Delendik web-sys,https://github.com/wasm-bindgen/wasm-bindgen/tree/master/crates/web-sys,MIT OR Apache-2.0,The wasm-bindgen Developers web-time,https://github.com/daxpedda/web-time,MIT OR Apache-2.0,The web-time Authors webpki-roots,https://github.com/rustls/webpki-roots,CDLA-Permissive-2.0,The webpki-roots Authors @@ -292,11 +283,6 @@ windows_x86_64_gnullvm,https://github.com/microsoft/windows-rs,MIT OR Apache-2.0 windows_x86_64_msvc,https://github.com/microsoft/windows-rs,MIT OR Apache-2.0,Microsoft windows_x86_64_msvc,https://github.com/microsoft/windows-rs,MIT OR Apache-2.0,The windows_x86_64_msvc Authors wit-bindgen,https://github.com/bytecodealliance/wit-bindgen,Apache-2.0 WITH LLVM-exception OR Apache-2.0 OR MIT,Alex Crichton -wit-bindgen-core,https://github.com/bytecodealliance/wit-bindgen,Apache-2.0 WITH LLVM-exception OR Apache-2.0 OR MIT,Alex Crichton -wit-bindgen-rust,https://github.com/bytecodealliance/wit-bindgen,Apache-2.0 WITH LLVM-exception OR Apache-2.0 OR MIT,Alex Crichton -wit-bindgen-rust-macro,https://github.com/bytecodealliance/wit-bindgen,Apache-2.0 WITH LLVM-exception OR Apache-2.0 OR MIT,Alex Crichton -wit-component,https://github.com/bytecodealliance/wasm-tools/tree/main/crates/wit-component,Apache-2.0 WITH LLVM-exception OR Apache-2.0 OR MIT,Peter Huene -wit-parser,https://github.com/bytecodealliance/wasm-tools/tree/main/crates/wit-parser,Apache-2.0 WITH LLVM-exception OR Apache-2.0 OR MIT,Alex Crichton writeable,https://github.com/unicode-org/icu4x,Unicode-3.0,The ICU4X Project Developers yansi,https://github.com/SergioBenitez/yansi,MIT OR Apache-2.0,Sergio Benitez yoke,https://github.com/unicode-org/icu4x,Unicode-3.0,Manish Goregaokar diff --git a/bottlecap/src/appsec/processor/context.rs b/bottlecap/src/appsec/processor/context.rs index 79ce3a002..9576a1582 100644 --- a/bottlecap/src/appsec/processor/context.rs +++ b/bottlecap/src/appsec/processor/context.rs @@ -202,7 +202,7 @@ impl Context { self.process_result(result); } Err(e) => log_waf_run_error(e), - }; + } } /// Obtain the information about the endpoint that was invoked, if available. diff --git a/bottlecap/src/appsec/processor/mod.rs b/bottlecap/src/appsec/processor/mod.rs index 2b5462367..f15844889 100644 --- a/bottlecap/src/appsec/processor/mod.rs +++ b/bottlecap/src/appsec/processor/mod.rs @@ -34,7 +34,7 @@ pub struct Processor { context_buffer: VecDeque, } impl Processor { - const CONTEXT_BUFFER_DEFAULT_CAPACITY: NonZero = unsafe { NonZero::new_unchecked(5) }; + const CONTEXT_BUFFER_DEFAULT_CAPACITY: NonZero = NonZero::new(5).unwrap(); /// Creates a new [`Processor`] instance using the provided [`Config`]. /// @@ -578,9 +578,9 @@ impl InvocationPayload for IdentifiedTrigger { .unwrap_or_default() .iter() .flat_map(parse_cookie) - .chunk_by(|(k, _)| (*k).to_string()) + .chunk_by(|(k, _)| (*k).clone()) .into_iter() - .map(|(k, v)| (k, v.into_iter().map(|(_, v)| v.to_string()).collect())) + .map(|(k, v)| (k, v.into_iter().map(|(_, v)| v.clone()).collect())) .collect(), Self::APIGatewayWebSocketEvent(t) => t .multi_value_headers @@ -589,9 +589,9 @@ impl InvocationPayload for IdentifiedTrigger { .unwrap_or_default() .iter() .flat_map(parse_cookie) - .chunk_by(|(k, _)| k.to_string()) + .chunk_by(|(k, _)| k.clone()) .into_iter() - .map(|(k, v)| (k, v.into_iter().map(|(_, v)| v.to_string()).collect())) + .map(|(k, v)| (k, v.into_iter().map(|(_, v)| v.clone()).collect())) .collect(), Self::ALBEvent(t) => t .multi_value_headers @@ -601,9 +601,9 @@ impl InvocationPayload for IdentifiedTrigger { .unwrap_or_default() .iter() .flat_map(parse_cookie) - .chunk_by(|(k, _)| (*k).to_string()) + .chunk_by(|(k, _)| (*k).clone()) .into_iter() - .map(|(k, v)| (k, v.into_iter().map(|(_, v)| v.to_string()).collect())) + .map(|(k, v)| (k, v.into_iter().map(|(_, v)| v.clone()).collect())) .collect(), Self::LambdaFunctionUrlEvent(t) => { t.cookies.as_ref().map(list_to_map).unwrap_or_default() diff --git a/bottlecap/src/appsec/processor/response.rs b/bottlecap/src/appsec/processor/response.rs index 17194b86d..b07fa5ea7 100644 --- a/bottlecap/src/appsec/processor/response.rs +++ b/bottlecap/src/appsec/processor/response.rs @@ -7,7 +7,7 @@ use crate::appsec::processor::InvocationPayload; use crate::lifecycle::invocation::triggers::body::Body; /// The expected payload of a response. This is different from trigger to trigger. -#[derive(Debug, Clone, Copy, PartialEq, Eq)] +#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)] pub enum ExpectedResponseFormat { /// API Gateway style integration responses (REST and HTTP) ApiGatewayResponse, @@ -16,6 +16,7 @@ pub enum ExpectedResponseFormat { Raw, /// Unknown or unsupported response format + #[default] Unknown, } impl ExpectedResponseFormat { @@ -39,11 +40,6 @@ impl ExpectedResponseFormat { } } } -impl Default for ExpectedResponseFormat { - fn default() -> Self { - Self::Unknown - } -} #[derive(Debug, Default, Deserialize)] #[serde(default)] diff --git a/bottlecap/src/bin/bottlecap/main.rs b/bottlecap/src/bin/bottlecap/main.rs index 9b9bdfe03..f8bcf5cec 100644 --- a/bottlecap/src/bin/bottlecap/main.rs +++ b/bottlecap/src/bin/bottlecap/main.rs @@ -113,13 +113,13 @@ async fn main() -> anyhow::Result<()> { debug!("Starting Datadog Extension v{version_without_next}"); // Debug: Wait for debugger to attach if DD_DEBUG_WAIT_FOR_ATTACH is set - if let Ok(wait_secs) = env::var("DD_DEBUG_WAIT_FOR_ATTACH") { - if let Ok(secs) = wait_secs.parse::() { - debug!("DD_DEBUG_WAIT_FOR_ATTACH: Waiting {secs} seconds for debugger to attach..."); - debug!("Connect your debugger to port 2345 now!"); - tokio::time::sleep(tokio::time::Duration::from_secs(secs)).await; - debug!("DD_DEBUG_WAIT_FOR_ATTACH: Continuing execution..."); - } + if let Ok(wait_secs) = env::var("DD_DEBUG_WAIT_FOR_ATTACH") + && let Ok(secs) = wait_secs.parse::() + { + debug!("DD_DEBUG_WAIT_FOR_ATTACH: Waiting {secs} seconds for debugger to attach..."); + debug!("Connect your debugger to port 2345 now!"); + tokio::time::sleep(tokio::time::Duration::from_secs(secs)).await; + debug!("DD_DEBUG_WAIT_FOR_ATTACH: Continuing execution..."); } prepare_client_provider()?; @@ -273,7 +273,7 @@ async fn extension_loop_idle( error!("Error getting next event: {e:?}"); return Err(e.into()); } - }; + } } } @@ -288,11 +288,7 @@ async fn extension_loop_active( ) -> anyhow::Result<()> { let (mut event_bus, event_bus_tx) = EventBus::run(); - let account_id = r - .account_id - .as_ref() - .unwrap_or(&"none".to_string()) - .to_string(); + let account_id = r.account_id.as_ref().unwrap_or(&"none".to_string()).clone(); let tags_provider = setup_tag_provider(&Arc::clone(&aws_config), config, &account_id); let (logs_agent_channel, logs_flusher, logs_agent_cancel_token, logs_aggregator_handle) = @@ -517,7 +513,6 @@ async fn extension_loop_active( "Transient network error waiting for shutdown event: {}. Retrying...", e ); - continue; } Err(e) => { error!( @@ -626,11 +621,10 @@ async fn extension_loop_active( tokio::select! { biased; Some(event) = event_bus.rx.recv() => { - if let Some(telemetry_event) = handle_event_bus_event(event, invocation_processor_handle.clone(), appsec_processor.clone(), tags_provider.clone(), trace_processor.clone(), trace_agent_channel.clone(), stats_concentrator.clone()).await { - if let TelemetryRecord::PlatformRuntimeDone{ .. } = telemetry_event.record { + if let Some(telemetry_event) = handle_event_bus_event(event, invocation_processor_handle.clone(), appsec_processor.clone(), tags_provider.clone(), trace_processor.clone(), trace_agent_channel.clone(), stats_concentrator.clone()).await + && let TelemetryRecord::PlatformRuntimeDone{ .. } = telemetry_event.record { break 'flush_end; } - } } _ = race_flush_interval.tick() => { flushing_service.flush_blocking().await; diff --git a/bottlecap/src/config/env.rs b/bottlecap/src/config/env.rs index 59f673571..9f66587a4 100644 --- a/bottlecap/src/config/env.rs +++ b/bottlecap/src/config/env.rs @@ -1012,7 +1012,7 @@ mod tests { otlp_config_traces_probabilistic_sampler_sampling_percentage: Some(50), otlp_config_logs_enabled: true, statsd_metric_namespace: None, - dogstatsd_so_rcvbuf: Some(1048576), + dogstatsd_so_rcvbuf: Some(1_048_576), dogstatsd_buffer_size: Some(65507), dogstatsd_queue_size: Some(2048), api_key_secret_arn: "arn:aws:secretsmanager:region:account:secret:datadog-api-key" @@ -1216,7 +1216,7 @@ mod tests { .load(&mut config) .expect("Failed to load config"); - assert_eq!(config.dogstatsd_so_rcvbuf, Some(1048576)); + assert_eq!(config.dogstatsd_so_rcvbuf, Some(1_048_576)); assert_eq!(config.dogstatsd_buffer_size, Some(65507)); assert_eq!(config.dogstatsd_queue_size, Some(2048)); Ok(()) diff --git a/bottlecap/src/config/mod.rs b/bottlecap/src/config/mod.rs index 7ef0d40bd..86e886a53 100644 --- a/bottlecap/src/config/mod.rs +++ b/bottlecap/src/config/mod.rs @@ -188,10 +188,10 @@ impl ConfigBuilder { // If `proxy_https` is not set, set it from `HTTPS_PROXY` environment variable // if it exists - if let Ok(https_proxy) = std::env::var("HTTPS_PROXY") { - if self.config.proxy_https.is_none() { - self.config.proxy_https = Some(https_proxy); - } + if let Ok(https_proxy) = std::env::var("HTTPS_PROXY") + && self.config.proxy_https.is_none() + { + self.config.proxy_https = Some(https_proxy); } // If `proxy_https` is set, check if the site is in `NO_PROXY` environment variable @@ -1008,7 +1008,7 @@ pub mod tests { TracePropagationStyle::TraceContext ], logs_config_logs_dd_url: "https://http-intake.logs.datadoghq.com".to_string(), - apm_dd_url: trace_intake_url("datadoghq.com").to_string(), + apm_dd_url: trace_intake_url("datadoghq.com").clone(), dd_url: String::new(), // We add the prefix in main.rs ..Config::default() } diff --git a/bottlecap/src/config/yaml.rs b/bottlecap/src/config/yaml.rs index 31278db89..406d73c33 100644 --- a/bottlecap/src/config/yaml.rs +++ b/bottlecap/src/config/yaml.rs @@ -1029,7 +1029,7 @@ api_security_sample_delay: 60 # Seconds apm_filter_tags_regex_require: None, apm_filter_tags_regex_reject: None, statsd_metric_namespace: None, - dogstatsd_so_rcvbuf: Some(1048576), + dogstatsd_so_rcvbuf: Some(1_048_576), dogstatsd_buffer_size: Some(65507), dogstatsd_queue_size: Some(2048), }; @@ -1047,11 +1047,11 @@ api_security_sample_delay: 60 # Seconds jail.clear_env(); jail.create_file( "datadog.yaml", - r#" + r" dogstatsd_so_rcvbuf: 524288 dogstatsd_buffer_size: 16384 dogstatsd_queue_size: 512 -"#, +", )?; let mut config = Config::default(); let yaml_config_source = YamlConfigSource { @@ -1061,7 +1061,7 @@ dogstatsd_queue_size: 512 .load(&mut config) .expect("Failed to load config"); - assert_eq!(config.dogstatsd_so_rcvbuf, Some(524288)); + assert_eq!(config.dogstatsd_so_rcvbuf, Some(524_288)); assert_eq!(config.dogstatsd_buffer_size, Some(16384)); assert_eq!(config.dogstatsd_queue_size, Some(512)); Ok(()) diff --git a/bottlecap/src/lifecycle/invocation/mod.rs b/bottlecap/src/lifecycle/invocation/mod.rs index f99974b6c..366883966 100644 --- a/bottlecap/src/lifecycle/invocation/mod.rs +++ b/bottlecap/src/lifecycle/invocation/mod.rs @@ -59,7 +59,7 @@ pub fn generate_span_id() -> u64 { } fn redact_value(key: &str, value: String) -> String { - let split_key = key.split('.').last().unwrap_or_default(); + let split_key = key.split('.').next_back().unwrap_or_default(); if REDACTABLE_KEYS.contains(&split_key) { String::from("redacted") } else { diff --git a/bottlecap/src/lifecycle/invocation/processor.rs b/bottlecap/src/lifecycle/invocation/processor.rs index 296eee3d4..a5282d99e 100644 --- a/bottlecap/src/lifecycle/invocation/processor.rs +++ b/bottlecap/src/lifecycle/invocation/processor.rs @@ -272,7 +272,7 @@ impl Processor { if let Some(runtime) = &self.runtime { self.dynamic_tags - .insert(String::from("runtime"), runtime.to_string()); + .insert(String::from("runtime"), runtime.clone()); self.enhanced_metrics.set_runtime_tag(runtime); } @@ -513,11 +513,12 @@ impl Processor { let context = self.enrich_ctx_at_platform_done(request_id, status); if self.tracer_detected { - if let Some(ctx) = context { - if ctx.invocation_span.trace_id != 0 && ctx.invocation_span.span_id != 0 { - self.send_ctx_spans(&tags_provider, &trace_sender, ctx) - .await; - } + if let Some(ctx) = context + && ctx.invocation_span.trace_id != 0 + && ctx.invocation_span.span_id != 0 + { + self.send_ctx_spans(&tags_provider, &trace_sender, ctx) + .await; } } else { self.send_cold_start_span(&tags_provider, &trace_sender) @@ -580,19 +581,19 @@ impl Processor { .complete_inferred_spans(&context.invocation_span); // Handle cold start span if present - if let Some(cold_start_span) = &mut context.cold_start_span { - if context.invocation_span.trace_id != 0 { - cold_start_span.trace_id = context.invocation_span.trace_id; - cold_start_span.parent_id = context.invocation_span.parent_id; - } + if let Some(cold_start_span) = &mut context.cold_start_span + && context.invocation_span.trace_id != 0 + { + cold_start_span.trace_id = context.invocation_span.trace_id; + cold_start_span.parent_id = context.invocation_span.parent_id; } // Handle snapstart restore span if present - if let Some(snapstart_restore_span) = &mut context.snapstart_restore_span { - if context.invocation_span.trace_id != 0 { - snapstart_restore_span.trace_id = context.invocation_span.trace_id; - snapstart_restore_span.parent_id = context.invocation_span.parent_id; - } + if let Some(snapstart_restore_span) = &mut context.snapstart_restore_span + && context.invocation_span.trace_id != 0 + { + snapstart_restore_span.trace_id = context.invocation_span.trace_id; + snapstart_restore_span.parent_id = context.invocation_span.parent_id; } Some(context.clone()) } @@ -640,14 +641,14 @@ impl Processor { /// For Node/Python: Updates the cold start span with the given trace ID. /// Returns the Span ID of the cold start span so we can reparent the `aws.lambda.load` span. pub fn set_cold_start_span_trace_id(&mut self, trace_id: u64) -> Option { - if let Some(cold_start_context) = self.context_buffer.get_context_with_cold_start() { - if let Some(cold_start_span) = &mut cold_start_context.cold_start_span { - if cold_start_span.trace_id == 0 { - cold_start_span.trace_id = trace_id; - } - - return Some(cold_start_span.span_id); + if let Some(cold_start_context) = self.context_buffer.get_context_with_cold_start() + && let Some(cold_start_span) = &mut cold_start_context.cold_start_span + { + if cold_start_span.trace_id == 0 { + cold_start_span.trace_id = trace_id; } + + return Some(cold_start_span.span_id); } None @@ -659,19 +660,19 @@ impl Processor { tags_provider: &Arc, trace_sender: &Arc, ) { - if let Some(cold_start_context) = self.context_buffer.get_context_with_cold_start() { - if let Some(cold_start_span) = &mut cold_start_context.cold_start_span { - if cold_start_span.trace_id == 0 { - debug!("Not sending cold start span because trace ID is unset."); - return; - } + if let Some(cold_start_context) = self.context_buffer.get_context_with_cold_start() + && let Some(cold_start_span) = &mut cold_start_context.cold_start_span + { + if cold_start_span.trace_id == 0 { + debug!("Not sending cold start span because trace ID is unset."); + return; + } - let traces = vec![cold_start_span.clone()]; - let body_size = size_of_val(cold_start_span); + let traces = vec![cold_start_span.clone()]; + let body_size = size_of_val(cold_start_span); - self.send_spans(traces, body_size, tags_provider, trace_sender) - .await; - } + self.send_spans(traces, body_size, tags_provider, trace_sender) + .await; } } @@ -756,13 +757,13 @@ impl Processor { } // Set Network and CPU time metrics - if let Some(context) = self.context_buffer.get(request_id) { - if let Some(offsets) = &context.enhanced_metric_data { - self.enhanced_metrics - .set_network_enhanced_metrics(offsets.network_offset); - self.enhanced_metrics - .set_cpu_time_enhanced_metrics(offsets.cpu_offset.clone()); - } + if let Some(context) = self.context_buffer.get(request_id) + && let Some(offsets) = &context.enhanced_metric_data + { + self.enhanced_metrics + .set_network_enhanced_metrics(offsets.network_offset); + self.enhanced_metrics + .set_cpu_time_enhanced_metrics(offsets.cpu_offset.clone()); } } @@ -845,24 +846,23 @@ impl Processor { // For provided.al runtimes, if the last invocation hit the memory limit, increment the OOM metric. // We do this for provided.al runtimes because we didn't find another way to detect this under provided.al. // We don't do this for other runtimes to avoid double counting. - if let Some(runtime) = &self.runtime { - if runtime.starts_with("provided.al") - && metrics.max_memory_used_mb == metrics.memory_size_mb - { - debug!( - "Invocation Processor | PlatformReport | Last invocation hit memory limit. Incrementing OOM metric." - ); - self.enhanced_metrics.increment_oom_metric(timestamp); - } + if let Some(runtime) = &self.runtime + && runtime.starts_with("provided.al") + && metrics.max_memory_used_mb == metrics.memory_size_mb + { + debug!( + "Invocation Processor | PlatformReport | Last invocation hit memory limit. Incrementing OOM metric." + ); + self.enhanced_metrics.increment_oom_metric(timestamp); } // Calculate and set post-runtime duration if context is available - if let Some(context) = self.context_buffer.get(request_id) { - if context.runtime_duration_ms != 0.0 { - let post_runtime_duration_ms = metrics.duration_ms - context.runtime_duration_ms; - self.enhanced_metrics - .set_post_runtime_duration_metric(post_runtime_duration_ms, timestamp); - } + if let Some(context) = self.context_buffer.get(request_id) + && context.runtime_duration_ms != 0.0 + { + let post_runtime_duration_ms = metrics.duration_ms - context.runtime_duration_ms; + self.enhanced_metrics + .set_post_runtime_duration_metric(post_runtime_duration_ms, timestamp); } } @@ -1085,11 +1085,11 @@ impl Processor { return Some(sc); } - if let Some(payload_headers) = payload_value.get("headers") { - if let Some(sc) = propagator.extract(payload_headers) { - debug!("Extracted trace context from event headers"); - return Some(sc); - } + if let Some(payload_headers) = payload_value.get("headers") + && let Some(sc) = propagator.extract(payload_headers) + { + debug!("Extracted trace context from event headers"); + return Some(sc); } if let Some(sc) = propagator.extract(headers) { @@ -1212,13 +1212,13 @@ impl Processor { parent_id = header.parse::().unwrap_or(0); } - if let Some(priority_str) = headers.get(DATADOG_SAMPLING_PRIORITY_KEY) { - if let Ok(priority) = priority_str.parse::() { - context - .invocation_span - .metrics - .insert(TAG_SAMPLING_PRIORITY.to_string(), priority); - } + if let Some(priority_str) = headers.get(DATADOG_SAMPLING_PRIORITY_KEY) + && let Ok(priority) = priority_str.parse::() + { + context + .invocation_span + .metrics + .insert(TAG_SAMPLING_PRIORITY.to_string(), priority); } // Extract tags from headers @@ -1288,7 +1288,7 @@ impl Processor { if let Some(m) = message { let decoded_message = base64_to_string(m).unwrap_or_else(|_| { debug!("Error message header may not be encoded, setting as is"); - m.to_string() + m.clone() }); error_tags.insert(String::from("error.msg"), decoded_message); @@ -1297,7 +1297,7 @@ impl Processor { if let Some(t) = r#type { let decoded_type = base64_to_string(t).unwrap_or_else(|_| { debug!("Error type header may not be encoded, setting as is"); - t.to_string() + t.clone() }); error_tags.insert(String::from("error.type"), decoded_type); @@ -1306,7 +1306,7 @@ impl Processor { if let Some(s) = stack { let decoded_stack = base64_to_string(s).unwrap_or_else(|e| { debug!("Failed to decode error stack: {e}"); - s.to_string() + s.clone() }); error_tags.insert(String::from("error.stack"), decoded_stack); diff --git a/bottlecap/src/lifecycle/invocation/processor_service.rs b/bottlecap/src/lifecycle/invocation/processor_service.rs index 2e3975e7c..25ca0bff4 100644 --- a/bottlecap/src/lifecycle/invocation/processor_service.rs +++ b/bottlecap/src/lifecycle/invocation/processor_service.rs @@ -6,7 +6,7 @@ use libdd_trace_protobuf::pb::Span; use serde_json::Value; use thiserror::Error; use tokio::sync::{mpsc, oneshot}; -use tracing::{debug, error}; +use tracing::debug; use crate::{ config::{self, aws::AwsConfig}, diff --git a/bottlecap/src/lifecycle/invocation/span_inferrer.rs b/bottlecap/src/lifecycle/invocation/span_inferrer.rs index 14cba1ab0..6c4eddd32 100644 --- a/bottlecap/src/lifecycle/invocation/span_inferrer.rs +++ b/bottlecap/src/lifecycle/invocation/span_inferrer.rs @@ -137,29 +137,28 @@ impl SpanInferrer { None } IdentifiedTrigger::SnsRecord(t) => { - if let Some(message) = &t.sns.message { - if let Ok(event_bridge_wrapper_message) = + if let Some(message) = &t.sns.message + && let Ok(event_bridge_wrapper_message) = serde_json::from_str::(message) - { - let mut wrapped_inferred_span = Span { - span_id: generate_span_id(), - ..Default::default() - }; - - event_bridge_wrapper_message.enrich_span( - &mut wrapped_inferred_span, - &config.service_mapping, - config.trace_aws_service_representation_enabled, - ); - inferred_span - .meta - .extend(event_bridge_wrapper_message.get_tags()); - - wrapped_inferred_span.duration = - inferred_span.start - wrapped_inferred_span.start; - - return Some(wrapped_inferred_span); - } + { + let mut wrapped_inferred_span = Span { + span_id: generate_span_id(), + ..Default::default() + }; + + event_bridge_wrapper_message.enrich_span( + &mut wrapped_inferred_span, + &config.service_mapping, + config.trace_aws_service_representation_enabled, + ); + inferred_span + .meta + .extend(event_bridge_wrapper_message.get_tags()); + + wrapped_inferred_span.duration = + inferred_span.start - wrapped_inferred_span.start; + + return Some(wrapped_inferred_span); } None diff --git a/bottlecap/src/lifecycle/invocation/triggers/api_gateway_http_event.rs b/bottlecap/src/lifecycle/invocation/triggers/api_gateway_http_event.rs index 0078cec4d..3eedb7a7b 100644 --- a/bottlecap/src/lifecycle/invocation/triggers/api_gateway_http_event.rs +++ b/bottlecap/src/lifecycle/invocation/triggers/api_gateway_http_event.rs @@ -178,11 +178,11 @@ impl Trigger for APIGatewayHttpEvent { } if let Some(referer) = self.headers.get("referer") { - tags.insert("http.referer".to_string(), referer.to_string()); + tags.insert("http.referer".to_string(), referer.clone()); } if let Some(user_agent) = self.headers.get("user-agent") { - tags.insert("http.user_agent".to_string(), user_agent.to_string()); + tags.insert("http.user_agent".to_string(), user_agent.clone()); } tags diff --git a/bottlecap/src/lifecycle/invocation/triggers/api_gateway_rest_event.rs b/bottlecap/src/lifecycle/invocation/triggers/api_gateway_rest_event.rs index b52d8aad3..fdf829733 100644 --- a/bottlecap/src/lifecycle/invocation/triggers/api_gateway_rest_event.rs +++ b/bottlecap/src/lifecycle/invocation/triggers/api_gateway_rest_event.rs @@ -160,7 +160,7 @@ impl Trigger for APIGatewayRestEvent { ), ( "http.user_agent".to_string(), - self.request_context.identity.user_agent.to_string(), + self.request_context.identity.user_agent.clone(), ), ( FUNCTION_TRIGGER_EVENT_SOURCE_TAG.to_string(), @@ -169,7 +169,7 @@ impl Trigger for APIGatewayRestEvent { ]); if let Some(referer) = self.headers.get("referer") { - tags.insert("http.referer".to_string(), referer.to_string()); + tags.insert("http.referer".to_string(), referer.clone()); } tags diff --git a/bottlecap/src/lifecycle/invocation/triggers/api_gateway_websocket_event.rs b/bottlecap/src/lifecycle/invocation/triggers/api_gateway_websocket_event.rs index 02aaf820a..7e54d5c4f 100644 --- a/bottlecap/src/lifecycle/invocation/triggers/api_gateway_websocket_event.rs +++ b/bottlecap/src/lifecycle/invocation/triggers/api_gateway_websocket_event.rs @@ -153,7 +153,7 @@ impl Trigger for APIGatewayWebSocketEvent { ]); if let Some(referer) = self.headers.get("referer") { - tags.insert("http.referer".to_string(), referer.to_string()); + tags.insert("http.referer".to_string(), referer.clone()); } tags diff --git a/bottlecap/src/lifecycle/invocation/triggers/dynamodb_event.rs b/bottlecap/src/lifecycle/invocation/triggers/dynamodb_event.rs index 4b9fd1ce2..be64ed6e5 100644 --- a/bottlecap/src/lifecycle/invocation/triggers/dynamodb_event.rs +++ b/bottlecap/src/lifecycle/invocation/triggers/dynamodb_event.rs @@ -120,7 +120,7 @@ impl Trigger for DynamoDbRecord { ); span.name = String::from("aws.dynamodb"); - span.service = service_name.to_string(); + span.service.clone_from(&service_name); span.resource = resource; span.r#type = String::from("web"); span.start = start_time; @@ -141,7 +141,7 @@ impl Trigger for DynamoDbRecord { "stream_view_type".to_string(), self.dynamodb.stream_view_type.clone(), ), - ("table_name".to_string(), table_name.to_string()), + ("table_name".to_string(), table_name.clone()), ])); } diff --git a/bottlecap/src/lifecycle/invocation/triggers/event_bridge_event.rs b/bottlecap/src/lifecycle/invocation/triggers/event_bridge_event.rs index f4b15b7ed..322c82738 100644 --- a/bottlecap/src/lifecycle/invocation/triggers/event_bridge_event.rs +++ b/bottlecap/src/lifecycle/invocation/triggers/event_bridge_event.rs @@ -78,7 +78,7 @@ impl Trigger for EventBridgeEvent { ); span.name = String::from("aws.eventbridge"); - span.service = service_name.to_string(); + span.service.clone_from(&service_name); span.resource = resource_name; span.r#type = String::from("web"); span.start = start_time; @@ -100,10 +100,10 @@ impl Trigger for EventBridgeEvent { } fn get_carrier(&self) -> HashMap { - if let Ok(detail) = serde_json::from_value::>(self.detail.clone()) { - if let Some(carrier) = detail.get(DATADOG_CARRIER_KEY) { - return serde_json::from_value(carrier.clone()).unwrap_or_default(); - } + if let Ok(detail) = serde_json::from_value::>(self.detail.clone()) + && let Some(carrier) = detail.get(DATADOG_CARRIER_KEY) + { + return serde_json::from_value(carrier.clone()).unwrap_or_default(); } HashMap::new() } @@ -119,7 +119,7 @@ impl ServiceNameResolver for EventBridgeEvent { carrier .get(DATADOG_RESOURCE_NAME_KEY) .unwrap_or(&self.source) - .to_string() + .clone() } fn get_generic_identifier(&self) -> &'static str { diff --git a/bottlecap/src/lifecycle/invocation/triggers/kinesis_event.rs b/bottlecap/src/lifecycle/invocation/triggers/kinesis_event.rs index 64a4fe3c3..7883dfda4 100644 --- a/bottlecap/src/lifecycle/invocation/triggers/kinesis_event.rs +++ b/bottlecap/src/lifecycle/invocation/triggers/kinesis_event.rs @@ -92,18 +92,18 @@ impl Trigger for KinesisRecord { span.r#type = "web".to_string(); span.meta = HashMap::from([ ("operation_name".to_string(), "aws.kinesis".to_string()), - ("stream_name".to_string(), stream_name.to_string()), + ("stream_name".to_string(), stream_name.clone()), ("shard_id".to_string(), shard_id.to_string()), ( "event_source_arn".to_string(), - self.event_source_arn.to_string(), + self.event_source_arn.clone(), ), - ("event_id".to_string(), self.event_id.to_string()), - ("event_name".to_string(), self.event_name.to_string()), - ("event_version".to_string(), self.event_version.to_string()), + ("event_id".to_string(), self.event_id.clone()), + ("event_name".to_string(), self.event_name.clone()), + ("event_version".to_string(), self.event_version.clone()), ( "partition_key".to_string(), - self.kinesis.partition_key.to_string(), + self.kinesis.partition_key.clone(), ), ]); } @@ -120,13 +120,12 @@ impl Trigger for KinesisRecord { } fn get_carrier(&self) -> HashMap { - if let Ok(decoded_base64) = general_purpose::STANDARD.decode(&self.kinesis.data) { - if let Ok(as_json_map) = from_slice::>(&decoded_base64) { - if let Some(carrier) = as_json_map.get(DATADOG_CARRIER_KEY) { - return serde_json::from_value(carrier.clone()).unwrap_or_default(); - } - } - }; + if let Ok(decoded_base64) = general_purpose::STANDARD.decode(&self.kinesis.data) + && let Ok(as_json_map) = from_slice::>(&decoded_base64) + && let Some(carrier) = as_json_map.get(DATADOG_CARRIER_KEY) + { + return serde_json::from_value(carrier.clone()).unwrap_or_default(); + } HashMap::new() } @@ -139,7 +138,7 @@ impl ServiceNameResolver for KinesisRecord { fn get_specific_identifier(&self) -> String { self.event_source_arn .split('/') - .last() + .next_back() .unwrap_or_default() .to_string() } diff --git a/bottlecap/src/lifecycle/invocation/triggers/mod.rs b/bottlecap/src/lifecycle/invocation/triggers/mod.rs index 04f73c498..8e89b2a4c 100644 --- a/bottlecap/src/lifecycle/invocation/triggers/mod.rs +++ b/bottlecap/src/lifecycle/invocation/triggers/mod.rs @@ -1,6 +1,6 @@ use std::collections::HashMap; +use std::sync::LazyLock; -use lazy_static::lazy_static; use libdd_trace_protobuf::pb::Span; use regex::Regex; use serde::{Deserialize, Deserializer}; @@ -26,8 +26,8 @@ pub mod step_function_event; pub const DATADOG_CARRIER_KEY: &str = "_datadog"; pub const FUNCTION_TRIGGER_EVENT_SOURCE_TAG: &str = "function_trigger.event_source"; pub const FUNCTION_TRIGGER_EVENT_SOURCE_ARN_TAG: &str = "function_trigger.event_source_arn"; -lazy_static! { - static ref ULID_UUID_GUID: Regex = Regex::new( +static ULID_UUID_GUID: LazyLock = LazyLock::new(|| { + Regex::new( r"(?x) ( [0-9a-fA-F]{8}- # UUID/GUID segment 1 @@ -40,10 +40,10 @@ lazy_static! { ( [0123456789ABCDEFGHJKMNPQRSTVWXYZ]{26} # ULID ) - " + ", ) - .expect("failed to create regex"); -} + .expect("failed to create regex") +}); /// Resolves the service name for a given trigger depending on /// service mapping configuration. diff --git a/bottlecap/src/lifecycle/invocation/triggers/msk_event.rs b/bottlecap/src/lifecycle/invocation/triggers/msk_event.rs index 2673f1446..91bd85d17 100644 --- a/bottlecap/src/lifecycle/invocation/triggers/msk_event.rs +++ b/bottlecap/src/lifecycle/invocation/triggers/msk_event.rs @@ -82,7 +82,7 @@ impl Trigger for MSKEvent { span.start = (first_value.timestamp * MS_TO_NS) as i64; span.meta.extend([ ("operation_name".to_string(), String::from("aws.msk")), - ("topic".to_string(), first_value.topic.to_string()), + ("topic".to_string(), first_value.topic.clone()), ("partition".to_string(), first_value.partition.to_string()), ("event_source".to_string(), self.event_source.clone()), ( @@ -101,7 +101,7 @@ impl Trigger for MSKEvent { } fn get_arn(&self, _region: &str) -> String { - self.event_source_arn.to_string() + self.event_source_arn.clone() } fn get_carrier(&self) -> HashMap { diff --git a/bottlecap/src/lifecycle/invocation/triggers/sns_event.rs b/bottlecap/src/lifecycle/invocation/triggers/sns_event.rs index 73e53d2ac..96cbc152d 100644 --- a/bottlecap/src/lifecycle/invocation/triggers/sns_event.rs +++ b/bottlecap/src/lifecycle/invocation/triggers/sns_event.rs @@ -105,7 +105,7 @@ impl Trigger for SnsRecord { ); span.name = "aws.sns".to_string(); - span.service = service_name.to_string(); + span.service.clone_from(&service_name); span.resource.clone_from(&resource_name); span.r#type = "web".to_string(); span.start = start_time; @@ -153,10 +153,10 @@ impl Trigger for SnsRecord { debug!("Unsupported type in SNS message attribute"); } } - } else if let Some(event_bridge_message) = &self.sns.message { - if let Ok(event) = serde_json::from_str::(event_bridge_message) { - return event.get_carrier(); - } + } else if let Some(event_bridge_message) = &self.sns.message + && let Ok(event) = serde_json::from_str::(event_bridge_message) + { + return event.get_carrier(); } HashMap::new() @@ -172,7 +172,7 @@ impl ServiceNameResolver for SnsRecord { self.sns .topic_arn .split(':') - .last() + .next_back() .unwrap_or_default() .to_string() } diff --git a/bottlecap/src/lifecycle/invocation/triggers/sqs_event.rs b/bottlecap/src/lifecycle/invocation/triggers/sqs_event.rs index fab3549b6..607174ad6 100644 --- a/bottlecap/src/lifecycle/invocation/triggers/sqs_event.rs +++ b/bottlecap/src/lifecycle/invocation/triggers/sqs_event.rs @@ -122,7 +122,7 @@ impl Trigger for SqsRecord { ); span.name = "aws.sqs".to_string(); - span.service = service_name.to_string(); + span.service.clone_from(&service_name); span.resource = resource; span.r#type = "web".to_string(); span.start = start_time; @@ -177,10 +177,10 @@ impl Trigger for SqsRecord { fn get_carrier(&self) -> HashMap { let carrier = HashMap::new(); - if let Some(ma) = self.message_attributes.get(DATADOG_CARRIER_KEY) { - if let Some(string_value) = &ma.string_value { - return serde_json::from_str(string_value).unwrap_or_default(); - } + if let Some(ma) = self.message_attributes.get(DATADOG_CARRIER_KEY) + && let Some(string_value) = &ma.string_value + { + return serde_json::from_str(string_value).unwrap_or_default(); } // Check for SNS event sent through SQS @@ -208,7 +208,7 @@ impl ServiceNameResolver for SqsRecord { fn get_specific_identifier(&self) -> String { self.event_source_arn .split(':') - .last() + .next_back() .unwrap_or_default() .to_string() } @@ -606,7 +606,7 @@ mod tests { assert_eq!( extract_trace_context_from_aws_trace_header(Some( - event.attributes.aws_trace_header.unwrap().to_string() + event.attributes.aws_trace_header.unwrap().clone() )) .unwrap(), SpanContext { diff --git a/bottlecap/src/lifecycle/invocation/triggers/step_function_event.rs b/bottlecap/src/lifecycle/invocation/triggers/step_function_event.rs index 628388e6c..259b06e4e 100644 --- a/bottlecap/src/lifecycle/invocation/triggers/step_function_event.rs +++ b/bottlecap/src/lifecycle/invocation/triggers/step_function_event.rs @@ -1,4 +1,5 @@ use std::collections::HashMap; +use std::fmt::Write; use serde::{Deserialize, Serialize}; use serde_json::Value; @@ -156,7 +157,7 @@ impl StepFunctionEvent { let tags = DatadogHeaderPropagator::extract_tags(&HashMap::from([( DATADOG_TAGS_KEY.to_string(), - trace_tags.to_string(), + trace_tags.clone(), )])); (lo_tid, tags) @@ -210,7 +211,7 @@ impl StepFunctionEvent { let mut unique_string = format!("{execution_id}#{state_name}#{state_entered_time}"); if retry_count != 0 || redrive_count != 0 { - unique_string.push_str(&format!("#{retry_count}#{redrive_count}")); + let _ = write!(unique_string, "#{retry_count}#{redrive_count}"); } let hash = Sha256::digest(unique_string.as_bytes()); diff --git a/bottlecap/src/logs/flusher.rs b/bottlecap/src/logs/flusher.rs index 36b78623b..c1fee28f8 100644 --- a/bottlecap/src/logs/flusher.rs +++ b/bottlecap/src/logs/flusher.rs @@ -113,10 +113,7 @@ impl Flusher { let time = Instant::now(); attempts += 1; let Some(cloned_req) = req.try_clone() else { - return Err(Box::new(std::io::Error::new( - std::io::ErrorKind::Other, - "can't clone", - ))); + return Err(Box::new(std::io::Error::other("can't clone"))); }; let resp = cloned_req.send().await; let elapsed = time.elapsed(); @@ -248,17 +245,16 @@ impl LogsFlusher { // If retry_request is provided, only process that request if let Some(req) = retry_request { - if let Some(req_clone) = req.try_clone() { - if let Err(e) = Flusher::send(req_clone).await { - if let Some(failed_req_err) = e.downcast_ref::() { - failed_requests.push( - failed_req_err - .request - .try_clone() - .expect("should be able to clone request"), - ); - } - } + if let Some(req_clone) = req.try_clone() + && let Err(e) = Flusher::send(req_clone).await + && let Some(failed_req_err) = e.downcast_ref::() + { + failed_requests.push( + failed_req_err + .request + .try_clone() + .expect("should be able to clone request"), + ); } } else { let logs_batches = Arc::new({ diff --git a/bottlecap/src/logs/lambda/processor.rs b/bottlecap/src/logs/lambda/processor.rs index 8af820512..5aeb5970f 100644 --- a/bottlecap/src/logs/lambda/processor.rs +++ b/bottlecap/src/logs/lambda/processor.rs @@ -1,4 +1,5 @@ use std::error::Error; +use std::fmt::Write; use std::sync::Arc; use tokio::sync::mpsc::Sender; @@ -215,10 +216,10 @@ impl LambdaProcessor { if let Some(metrics) = metrics { self.invocation_context.runtime_duration_ms = metrics.duration_ms; if status == Status::Timeout { - message.push_str(&format!(" Task timed out after {:.2} seconds", metrics.duration_ms / 1000.0)); + let _ = write!(message, " Task timed out after {:.2} seconds", metrics.duration_ms / 1000.0); result_status = "error".to_string(); } else if status == Status::Error { - message.push_str(&format!(" Task failed: {:?}", error_type.unwrap_or_default())); + let _ = write!(message, " Task failed: {:?}", error_type.unwrap_or_default()); result_status = "error".to_string(); } } @@ -415,15 +416,15 @@ impl LambdaProcessor { } // Check for nested ddtags inside a "message" field - if let Some(inner_message) = json_obj.get_mut("message") { - if let Some(serde_json::Value::String(message_tags)) = inner_message.get("ddtags") { - tags.push(','); - tags.push_str(message_tags); - if let Some(inner_obj) = inner_message.as_object_mut() { - inner_obj.remove("ddtags"); - } - return inner_message.to_string(); + if let Some(inner_message) = json_obj.get_mut("message") + && let Some(serde_json::Value::String(message_tags)) = inner_message.get("ddtags") + { + tags.push(','); + tags.push_str(message_tags); + if let Some(inner_obj) = inner_message.as_object_mut() { + inner_obj.remove("ddtags"); } + return inner_message.to_string(); } // No ddtags found, use original message @@ -442,13 +443,11 @@ impl LambdaProcessor { fn process_and_queue_log(&mut self, mut log: IntakeLog) { let should_send_log = self.logs_enabled && LambdaProcessor::apply_rules(&self.rules, &mut log.message.message); - if should_send_log { - if let Ok(serialized_log) = serde_json::to_string(&log) { - // explicitly drop log so we don't accidentally re-use it and push - // duplicate logs to the aggregator - drop(log); - self.ready_logs.push(serialized_log); - } + if should_send_log && let Ok(serialized_log) = serde_json::to_string(&log) { + // explicitly drop log so we don't accidentally re-use it and push + // duplicate logs to the aggregator + drop(log); + self.ready_logs.push(serialized_log); } } @@ -465,10 +464,10 @@ impl LambdaProcessor { } } - if !self.ready_logs.is_empty() { - if let Err(e) = aggregator_handle.insert_batch(std::mem::take(&mut self.ready_logs)) { - debug!("Failed to send logs to aggregator: {}", e); - } + if !self.ready_logs.is_empty() + && let Err(e) = aggregator_handle.insert_batch(std::mem::take(&mut self.ready_logs)) + { + debug!("Failed to send logs to aggregator: {}", e); } } } diff --git a/bottlecap/src/lwa/mod.rs b/bottlecap/src/lwa/mod.rs index 89776ce88..06f01dd53 100644 --- a/bottlecap/src/lwa/mod.rs +++ b/bottlecap/src/lwa/mod.rs @@ -114,7 +114,7 @@ pub async fn process_invocation_next( if let Some(request_id) = request_id { let _ = invocation_processor_handle - .add_reparenting(request_id.to_string(), generate_span_id(), parent_id) + .add_reparenting(request_id.clone(), generate_span_id(), parent_id) .await; } } @@ -156,11 +156,10 @@ pub async fn process_invocation_response( } fn inner_header(inner_payload: &Value) -> HashMap { - let headers = if let Some(body) = inner_payload.get("headers") { + if let Some(body) = inner_payload.get("headers") { serde_json::from_value::>(body.clone()) .unwrap_or_else(|_| HashMap::new()) } else { HashMap::new() - }; - headers + } } diff --git a/bottlecap/src/metrics/enhanced/statfs.rs b/bottlecap/src/metrics/enhanced/statfs.rs index 96284fe72..707c607e7 100644 --- a/bottlecap/src/metrics/enhanced/statfs.rs +++ b/bottlecap/src/metrics/enhanced/statfs.rs @@ -10,7 +10,7 @@ use std::path::Path; /// Returns the block size, total number of blocks, and number of blocks available for the specified directory path. /// pub fn statfs_info(path: &str) -> Result<(f64, f64, f64), io::Error> { - let stat = statfs(Path::new(path)).map_err(|e| io::Error::new(io::ErrorKind::Other, e))?; + let stat = statfs(Path::new(path)).map_err(io::Error::other)?; Ok(( stat.block_size() as f64, stat.blocks() as f64, diff --git a/bottlecap/src/metrics/enhanced/usage_metrics.rs b/bottlecap/src/metrics/enhanced/usage_metrics.rs index 2a7190f72..322e432cc 100644 --- a/bottlecap/src/metrics/enhanced/usage_metrics.rs +++ b/bottlecap/src/metrics/enhanced/usage_metrics.rs @@ -19,20 +19,20 @@ impl UsageMetrics { } pub fn update(&mut self, tmp_used: Option, fd_use: Option, threads_use: Option) { - if let Some(tmp_used) = tmp_used { - if tmp_used > self.tmp_used { - self.tmp_used = tmp_used; - } + if let Some(tmp_used) = tmp_used + && tmp_used > self.tmp_used + { + self.tmp_used = tmp_used; } - if let Some(fd_use) = fd_use { - if fd_use > self.fd_use { - self.fd_use = fd_use; - } + if let Some(fd_use) = fd_use + && fd_use > self.fd_use + { + self.fd_use = fd_use; } - if let Some(threads_use) = threads_use { - if threads_use > self.threads_use { - self.threads_use = threads_use; - } + if let Some(threads_use) = threads_use + && threads_use > self.threads_use + { + self.threads_use = threads_use; } } diff --git a/bottlecap/src/otlp/agent.rs b/bottlecap/src/otlp/agent.rs index 13022d053..94fbcee04 100644 --- a/bottlecap/src/otlp/agent.rs +++ b/bottlecap/src/otlp/agent.rs @@ -194,16 +194,16 @@ impl Agent { format!("Error sending traces to the trace aggregator: {err}"), ); } - }; + } // This needs to be after process_traces() because process_traces() // performs obfuscation, and we need to compute stats on the obfuscated traces. - if compute_trace_stats_on_extension { - if let Err(err) = stats_generator.send(&processed_traces) { - // Just log the error. We don't think trace stats are critical, so we don't want to - // return an error if only stats fail to send. - error!("OTLP | Error sending traces to the stats concentrator: {err}"); - } + if compute_trace_stats_on_extension + && let Err(err) = stats_generator.send(&processed_traces) + { + // Just log the error. We don't think trace stats are critical, so we don't want to + // return an error if only stats fail to send. + error!("OTLP | Error sending traces to the stats concentrator: {err}"); } Self::otlp_success_response() diff --git a/bottlecap/src/otlp/transform.rs b/bottlecap/src/otlp/transform.rs index 9fb11cfef..451647d8c 100644 --- a/bottlecap/src/otlp/transform.rs +++ b/bottlecap/src/otlp/transform.rs @@ -1,5 +1,4 @@ use hex; -use lazy_static::lazy_static; use libdd_trace_normalization::normalize_utils::{ normalize_name, normalize_service, normalize_tag, }; @@ -29,7 +28,7 @@ use opentelemetry_semantic_conventions::trace::{ use serde_json::json; use std::collections::HashMap; use std::str; -use std::sync::Arc; +use std::sync::{Arc, LazyLock}; use tracing::debug; use crate::config::Config; @@ -59,27 +58,32 @@ pub const KEY_DATADOG_STATS_COMPUTED: &str = "_dd.stats_computed"; // const SPAN_TYPE_GENERIC_DB: &str = "db"; -lazy_static! { - // TODO: add mappings - static ref DB_SYSTEM_MAP: HashMap = HashMap::new(); - static ref DD_SEMANTIC_KEYS_TO_META_KEYS: HashMap<&'static str, &'static str> = HashMap::from([ - (KEY_DATADOG_ENVIRONMENT, "env"), - (KEY_DATADOG_VERSION, "version"), - (KEY_DATADOG_HTTP_STATUS_CODE, "http.status_code"), - (KEY_DATADOG_ERROR_MSG, "error.msg"), - (KEY_DATADOG_ERROR_TYPE, "error.type"), - (KEY_DATADOG_ERROR_STACK, "error.stack"), - ]); - - static ref META_KEYS_TO_DD_SEMANTIC_KEYS: HashMap<&'static str, &'static str> = HashMap::from([ - ("env", KEY_DATADOG_ENVIRONMENT), - ("version", KEY_DATADOG_VERSION), - ("http.status_code", KEY_DATADOG_HTTP_STATUS_CODE), - ("error.msg", KEY_DATADOG_ERROR_MSG), - ("error.type", KEY_DATADOG_ERROR_TYPE), - ("error.stack", KEY_DATADOG_ERROR_STACK), - ]); -} +// TODO: add mappings +#[allow(dead_code)] +static DB_SYSTEM_MAP: LazyLock> = LazyLock::new(HashMap::new); +static DD_SEMANTIC_KEYS_TO_META_KEYS: LazyLock> = + LazyLock::new(|| { + HashMap::from([ + (KEY_DATADOG_ENVIRONMENT, "env"), + (KEY_DATADOG_VERSION, "version"), + (KEY_DATADOG_HTTP_STATUS_CODE, "http.status_code"), + (KEY_DATADOG_ERROR_MSG, "error.msg"), + (KEY_DATADOG_ERROR_TYPE, "error.type"), + (KEY_DATADOG_ERROR_STACK, "error.stack"), + ]) + }); + +static META_KEYS_TO_DD_SEMANTIC_KEYS: LazyLock> = + LazyLock::new(|| { + HashMap::from([ + ("env", KEY_DATADOG_ENVIRONMENT), + ("version", KEY_DATADOG_VERSION), + ("http.status_code", KEY_DATADOG_HTTP_STATUS_CODE), + ("error.msg", KEY_DATADOG_ERROR_MSG), + ("error.type", KEY_DATADOG_ERROR_TYPE), + ("error.stack", KEY_DATADOG_ERROR_STACK), + ]) + }); fn get_otel_attribute_value(attributes: &Vec, key: &str) -> Option { for attribute in attributes { @@ -549,18 +553,18 @@ fn get_otel_status_code(otel_span: &OtelSpan) -> u32 { "http.response.status_code", false, ); - if !status_code.is_empty() { - if let Ok(status_code) = status_code.parse::() { - return status_code; - } + if !status_code.is_empty() + && let Ok(status_code) = status_code.parse::() + { + return status_code; } status_code = get_otel_attribute_value_as_string(&otel_span.attributes, HTTP_RESPONSE_STATUS_CODE, false); - if !status_code.is_empty() { - if let Ok(status_code) = status_code.parse::() { - return status_code; - } + if !status_code.is_empty() + && let Ok(status_code) = status_code.parse::() + { + return status_code; } 0 @@ -704,11 +708,11 @@ fn marshal_events(events: &[Event]) -> String { if !event.attributes.is_empty() { let mut attrs = json!({}); for kv in &event.attributes { - let key = kv.key.to_string(); - if let Some(v) = &kv.value { - if let Some(value) = &v.value { - attrs[key] = json!(otel_value_to_string(value)); - } + let key = kv.key.clone(); + if let Some(v) = &kv.value + && let Some(value) = &v.value + { + attrs[key] = json!(otel_value_to_string(value)); } } event_obj["attributes"] = attrs; @@ -740,11 +744,11 @@ fn marshal_links(links: &[Link]) -> String { if !link.attributes.is_empty() { let mut attrs = json!({}); for kv in &link.attributes { - let key = kv.key.to_string(); - if let Some(v) = &kv.value { - if let Some(value) = &v.value { - attrs[key] = json!(otel_value_to_string(value)); - } + let key = kv.key.clone(); + if let Some(v) = &kv.value + && let Some(value) = &v.value + { + attrs[key] = json!(otel_value_to_string(value)); } } link_obj["attributes"] = attrs; @@ -818,7 +822,7 @@ fn set_span_error_from_otel_span(dd_span: &mut DatadogSpan, otel_span: &OtelSpan if let Some(status_code) = dd_span.meta.get("http.response.status_code") { dd_span .meta - .insert("error.msg".to_string(), status_code.to_string()); + .insert("error.msg".to_string(), status_code.clone()); } } } @@ -1003,7 +1007,7 @@ pub fn otel_span_to_dd_span( if let Some(v) = value.as_ref().and_then(|v| v.value.as_ref()) { let value = otel_value_to_string(v); if !value.is_empty() { - dd_span.meta.insert(key.to_string(), value); + dd_span.meta.insert(key.clone(), value); } } } diff --git a/bottlecap/src/proxy/interceptor.rs b/bottlecap/src/proxy/interceptor.rs index 20fe0d6b6..4ed0fc951 100644 --- a/bottlecap/src/proxy/interceptor.rs +++ b/bottlecap/src/proxy/interceptor.rs @@ -179,20 +179,19 @@ async fn invocation_next_proxy( if let Ok(body) = intercepted_completion_receiver.await { debug!("PROXY | invocation_next_proxy | intercepted body completed"); - if let Some(appsec_processor) = appsec_processor { - if let Some(request_id) = intercepted_parts_clone + if let Some(appsec_processor) = appsec_processor + && let Some(request_id) = intercepted_parts_clone .headers .get("Lambda-Runtime-Aws-Request-Id") .and_then(|v| v.to_str().ok()) + { { - { - if let Ok(trigger) = IdentifiedTrigger::from_slice(&body) { - appsec_processor - .lock() - .await - .process_invocation_next(request_id, &trigger) - .await; - } + if let Ok(trigger) = IdentifiedTrigger::from_slice(&body) { + appsec_processor + .lock() + .await + .process_invocation_next(request_id, &trigger) + .await; } } } diff --git a/bottlecap/src/secrets/decrypt.rs b/bottlecap/src/secrets/decrypt.rs index 63914b922..673075919 100644 --- a/bottlecap/src/secrets/decrypt.rs +++ b/bottlecap/src/secrets/decrypt.rs @@ -115,7 +115,7 @@ pub async fn resolve_secrets(config: Arc, aws_config: Arc) -> fn clean_api_key(maybe_key: Option) -> Option { if let Some(key) = maybe_key { - let clean_key = key.trim_end_matches('\n').replace(' ', "").to_string(); + let clean_key = key.trim_end_matches('\n').replace(' ', "").clone(); if !clean_key.is_empty() { return Some(clean_key); } @@ -250,10 +250,10 @@ async fn decrypt_aws_ssm( ); let v = request(json_body, headers?, client).await?; - if let Some(parameter) = v["Parameter"].as_object() { - if let Some(value) = parameter["Value"].as_str() { - return Ok(value.to_string()); - } + if let Some(parameter) = v["Parameter"].as_object() + && let Some(value) = parameter["Value"].as_str() + { + return Ok(value.to_string()); } Err(Error::new(std::io::ErrorKind::InvalidData, v.to_string()).into()) } diff --git a/bottlecap/src/tags/lambda/tags.rs b/bottlecap/src/tags/lambda/tags.rs index 7915c085c..616c09405 100644 --- a/bottlecap/src/tags/lambda/tags.rs +++ b/bottlecap/src/tags/lambda/tags.rs @@ -78,14 +78,14 @@ fn tags_from_env( tags_map.insert(AWS_ACCOUNT_KEY.to_string(), parts[4].to_string()); tags_map.insert(FUNCTION_NAME_KEY.to_string(), parts[6].to_string()); tags_map.insert(RESOURCE_KEY.to_string(), parts[6].to_string()); - if let Ok(qualifier) = std::env::var(QUALIFIER_ENV_VAR) { - if qualifier != "$LATEST" { - tags_map.insert( - RESOURCE_KEY.to_string(), - format!("{}:{}", parts[6], qualifier), - ); - tags_map.insert(EXECUTED_VERSION_KEY.to_string(), qualifier); - } + if let Ok(qualifier) = std::env::var(QUALIFIER_ENV_VAR) + && qualifier != "$LATEST" + { + tags_map.insert( + RESOURCE_KEY.to_string(), + format!("{}:{}", parts[6], qualifier), + ); + tags_map.insert(EXECUTED_VERSION_KEY.to_string(), qualifier); } } tags_map.insert( @@ -94,10 +94,10 @@ fn tags_from_env( ); } if let Some(version) = &config.version { - tags_map.insert(VERSION_KEY.to_string(), version.to_string()); + tags_map.insert(VERSION_KEY.to_string(), version.clone()); } if let Some(env) = &config.env { - tags_map.insert(ENV_KEY.to_string(), env.to_string()); + tags_map.insert(ENV_KEY.to_string(), env.clone()); } if let Some(service) = &config.service { tags_map.insert(SERVICE_KEY.to_string(), service.to_lowercase()); @@ -109,10 +109,10 @@ fn tags_from_env( tags_map.insert(MEMORY_SIZE_KEY.to_string(), memory_size); } if let Ok(runtime) = std::env::var(RUNTIME_VAR) { - if config.serverless_appsec_enabled { - if let Some(runtime_family) = identify_runtime_family(&runtime) { - tags_map.insert(RUNTIME_FAMILY_KEY.to_string(), runtime_family.to_string()); - } + if config.serverless_appsec_enabled + && let Some(runtime_family) = identify_runtime_family(&runtime) + { + tags_map.insert(RUNTIME_FAMILY_KEY.to_string(), runtime_family.to_string()); } tags_map.insert(RUNTIME_KEY.to_string(), runtime); } @@ -164,7 +164,7 @@ pub fn resolve_runtime_from_proc(proc_path: &str, fallback_provided_al_path: &st .find(|line| line.contains(RUNTIME_VAR)) .and_then(|runtime_var_line| { // AWS_EXECUTION_ENV=AWS_Lambda_java8 - runtime_var_line.split('_').last().map(String::from) + runtime_var_line.split('_').next_back().map(String::from) }) }); @@ -172,7 +172,7 @@ pub fn resolve_runtime_from_proc(proc_path: &str, fallback_provided_al_path: &st if let Some(runtime_from_environ) = search_environ_runtime { debug!("Proc runtime search successful in {search_time}us: {runtime_from_environ}"); return runtime_from_environ.replace('\"', ""); - }; + } debug!("Proc runtime search unsuccessful after {search_time}us"); } Err(e) => { diff --git a/bottlecap/src/traces/propagation/mod.rs b/bottlecap/src/traces/propagation/mod.rs index 097f94292..828e210b1 100644 --- a/bottlecap/src/traces/propagation/mod.rs +++ b/bottlecap/src/traces/propagation/mod.rs @@ -200,10 +200,9 @@ impl DatadogCompositePropagator { #[cfg(test)] pub mod tests { + use std::sync::LazyLock; use std::vec; - use lazy_static::lazy_static; - use crate::traces::context::Sampling; use super::*; @@ -212,131 +211,152 @@ pub mod tests { (value & 0xFFFF_FFFF_FFFF_FFFF) as u64 } - lazy_static! { - static ref TRACE_ID: u128 = 171_395_628_812_617_415_352_188_477_958_425_669_623; - static ref TRACE_ID_LOWER_ORDER_BITS: u64 = lower_64_bits(*TRACE_ID); - static ref TRACE_ID_HEX: String = String::from("80f198ee56343ba864fe8b2a57d3eff7"); + static TRACE_ID: LazyLock = + LazyLock::new(|| 171_395_628_812_617_415_352_188_477_958_425_669_623); + static TRACE_ID_LOWER_ORDER_BITS: LazyLock = LazyLock::new(|| lower_64_bits(*TRACE_ID)); + static TRACE_ID_HEX: LazyLock = + LazyLock::new(|| String::from("80f198ee56343ba864fe8b2a57d3eff7")); - // TraceContext Headers - static ref VALID_TRACECONTEXT_HEADERS_BASIC: HashMap = HashMap::from([ - ( - "traceparent".to_string(), - format!("00-{}-00f067aa0ba902b7-01", *TRACE_ID_HEX) - ), - ( - "tracestate".to_string(), - "dd=p:00f067aa0ba902b7;s:2;o:rum".to_string() - ), - ]); - static ref VALID_TRACECONTEXT_HEADERS_RUM_NO_SAMPLING_DECISION: HashMap = + // TraceContext Headers + static VALID_TRACECONTEXT_HEADERS_BASIC: LazyLock> = + LazyLock::new(|| { HashMap::from([ ( "traceparent".to_string(), - format!("00-{}-00f067aa0ba902b7-00", *TRACE_ID_HEX) + format!("00-{}-00f067aa0ba902b7-01", *TRACE_ID_HEX), ), ( "tracestate".to_string(), - "dd=o:rum".to_string() + "dd=p:00f067aa0ba902b7;s:2;o:rum".to_string(), + ), + ]) + }); + static VALID_TRACECONTEXT_HEADERS_RUM_NO_SAMPLING_DECISION: LazyLock> = + LazyLock::new(|| { + HashMap::from([ + ( + "traceparent".to_string(), + format!("00-{}-00f067aa0ba902b7-00", *TRACE_ID_HEX), ), - ]); - static ref VALID_TRACECONTEXT_HEADERS: HashMap = HashMap::from([ + ("tracestate".to_string(), "dd=o:rum".to_string()), + ]) + }); + static VALID_TRACECONTEXT_HEADERS: LazyLock> = LazyLock::new(|| { + HashMap::from([ ( "traceparent".to_string(), - format!("00-{}-00f067aa0ba902b7-01", *TRACE_ID_HEX) + format!("00-{}-00f067aa0ba902b7-01", *TRACE_ID_HEX), ), ( "tracestate".to_string(), - "dd=s:2;o:rum;t.dm:-4;t.usr.id:baz64,congo=t61rcWkgMz".to_string() + "dd=s:2;o:rum;t.dm:-4;t.usr.id:baz64,congo=t61rcWkgMz".to_string(), ), - ]); - static ref VALID_TRACECONTEXT_HEADERS_VALID_64_BIT_TRACE_ID: HashMap = + ]) + }); + static VALID_TRACECONTEXT_HEADERS_VALID_64_BIT_TRACE_ID: LazyLock> = + LazyLock::new(|| { HashMap::from([ ( "traceparent".to_string(), - "00-000000000000000064fe8b2a57d3eff7-00f067aa0ba902b7-01".to_string() + "00-000000000000000064fe8b2a57d3eff7-00f067aa0ba902b7-01".to_string(), ), ( "tracestate".to_string(), - "dd=s:2;o:rum;t.dm:-4;t.usr.id:baz64,congo=t61rcWkgMzE".to_string() + "dd=s:2;o:rum;t.dm:-4;t.usr.id:baz64,congo=t61rcWkgMzE".to_string(), ), - ]); + ]) + }); - // Datadog Headers - static ref VALID_DATADOG_HEADERS: HashMap = HashMap::from([ + // Datadog Headers + static VALID_DATADOG_HEADERS: LazyLock> = LazyLock::new(|| { + HashMap::from([ ( "x-datadog-trace-id".to_string(), "13088165645273925489".to_string(), ), - ("x-datadog-parent-id".to_string(), "5678".to_string(),), + ("x-datadog-parent-id".to_string(), "5678".to_string()), ("x-datadog-sampling-priority".to_string(), "1".to_string()), ("x-datadog-origin".to_string(), "synthetics".to_string()), - ]); - static ref VALID_DATADOG_HEADERS_NO_PRIORITY: HashMap = HashMap::from([ - ( - "x-datadog-trace-id".to_string(), - "13088165645273925489".to_string(), - ), - ("x-datadog-parent-id".to_string(), "5678".to_string(),), - ("x-datadog-origin".to_string(), "synthetics".to_string()), - ]); - static ref VALID_DATADOG_HEADERS_MATCHING_TRACE_CONTEXT_VALID_TRACE_ID: HashMap = + ]) + }); + static VALID_DATADOG_HEADERS_NO_PRIORITY: LazyLock> = + LazyLock::new(|| { HashMap::from([ ( "x-datadog-trace-id".to_string(), - TRACE_ID_LOWER_ORDER_BITS.to_string() + "13088165645273925489".to_string(), ), ("x-datadog-parent-id".to_string(), "5678".to_string()), ("x-datadog-origin".to_string(), "synthetics".to_string()), - ("x-datadog-sampling-priority".to_string(), "1".to_string()), - ]); - static ref INVALID_DATADOG_HEADERS: HashMap = HashMap::from([ + ]) + }); + static VALID_DATADOG_HEADERS_MATCHING_TRACE_CONTEXT_VALID_TRACE_ID: LazyLock< + HashMap, + > = LazyLock::new(|| { + HashMap::from([ + ( + "x-datadog-trace-id".to_string(), + TRACE_ID_LOWER_ORDER_BITS.to_string(), + ), + ("x-datadog-parent-id".to_string(), "5678".to_string()), + ("x-datadog-origin".to_string(), "synthetics".to_string()), + ("x-datadog-sampling-priority".to_string(), "1".to_string()), + ]) + }); + static INVALID_DATADOG_HEADERS: LazyLock> = LazyLock::new(|| { + HashMap::from([ ( "x-datadog-trace-id".to_string(), "13088165645273925489".to_string(), ), - ("x-datadog-parent-id".to_string(), "parent_id".to_string(),), - ("x-datadog-sampling-priority".to_string(), "sample".to_string()), - ]); - - // Fixtures - // - static ref ALL_VALID_HEADERS: HashMap = { - let mut h = HashMap::new(); - h.extend(VALID_DATADOG_HEADERS.clone()); - h.extend(VALID_TRACECONTEXT_HEADERS.clone()); - // todo: add b3 - h - }; - static ref DATADOG_TRACECONTEXT_MATCHING_TRACE_ID_HEADERS: HashMap = { + ("x-datadog-parent-id".to_string(), "parent_id".to_string()), + ( + "x-datadog-sampling-priority".to_string(), + "sample".to_string(), + ), + ]) + }); + + // Fixtures + static ALL_VALID_HEADERS: LazyLock> = LazyLock::new(|| { + let mut h = HashMap::new(); + h.extend(VALID_DATADOG_HEADERS.clone()); + h.extend(VALID_TRACECONTEXT_HEADERS.clone()); + // todo: add b3 + h + }); + static DATADOG_TRACECONTEXT_MATCHING_TRACE_ID_HEADERS: LazyLock> = + LazyLock::new(|| { let mut h = HashMap::new(); h.extend(VALID_DATADOG_HEADERS_MATCHING_TRACE_CONTEXT_VALID_TRACE_ID.clone()); // We use 64-bit traceparent trace id value here so it can match for // both 128-bit enabled and disabled h.extend(VALID_TRACECONTEXT_HEADERS_VALID_64_BIT_TRACE_ID.clone()); h - }; - // Edge cases - static ref ALL_HEADERS_CHAOTIC_1: HashMap = { - let mut h = HashMap::new(); - h.extend(VALID_DATADOG_HEADERS_MATCHING_TRACE_CONTEXT_VALID_TRACE_ID.clone()); - h.extend(VALID_TRACECONTEXT_HEADERS_VALID_64_BIT_TRACE_ID.clone()); - // todo: add b3 - h - }; - static ref ALL_HEADERS_CHAOTIC_2: HashMap = { - let mut h = HashMap::new(); - h.extend(VALID_DATADOG_HEADERS.clone()); - h.extend(VALID_TRACECONTEXT_HEADERS_VALID_64_BIT_TRACE_ID.clone()); - // todo: add b3 - h - }; - static ref NO_TRACESTATE_SUPPORT_NOT_MATCHING_TRACE_ID: HashMap = { + }); + // Edge cases + #[allow(dead_code)] + static ALL_HEADERS_CHAOTIC_1: LazyLock> = LazyLock::new(|| { + let mut h = HashMap::new(); + h.extend(VALID_DATADOG_HEADERS_MATCHING_TRACE_CONTEXT_VALID_TRACE_ID.clone()); + h.extend(VALID_TRACECONTEXT_HEADERS_VALID_64_BIT_TRACE_ID.clone()); + // todo: add b3 + h + }); + static ALL_HEADERS_CHAOTIC_2: LazyLock> = LazyLock::new(|| { + let mut h = HashMap::new(); + h.extend(VALID_DATADOG_HEADERS.clone()); + h.extend(VALID_TRACECONTEXT_HEADERS_VALID_64_BIT_TRACE_ID.clone()); + // todo: add b3 + h + }); + static NO_TRACESTATE_SUPPORT_NOT_MATCHING_TRACE_ID: LazyLock> = + LazyLock::new(|| { let mut h = HashMap::new(); h.extend(VALID_DATADOG_HEADERS.clone()); h.extend(VALID_TRACECONTEXT_HEADERS_RUM_NO_SAMPLING_DECISION.clone()); h - }; - } + }); macro_rules! test_propagation_extract { ($($name:ident: $value:expr,)*) => { diff --git a/bottlecap/src/traces/propagation/text_map_propagator.rs b/bottlecap/src/traces/propagation/text_map_propagator.rs index 4f0e5b8c4..acd95ff18 100644 --- a/bottlecap/src/traces/propagation/text_map_propagator.rs +++ b/bottlecap/src/traces/propagation/text_map_propagator.rs @@ -1,6 +1,6 @@ use std::collections::HashMap; +use std::sync::LazyLock; -use lazy_static::lazy_static; use regex::Regex; use tracing::{debug, error, warn}; @@ -30,20 +30,23 @@ pub const TRACESTATE_KEY: &str = "tracestate"; pub const BAGGAGE_PREFIX: &str = "ot-baggage-"; -lazy_static! { - static ref TRACEPARENT_REGEX: Regex = - Regex::new(r"(?i)^([a-f0-9]{2})-([a-f0-9]{32})-([a-f0-9]{16})-([a-f0-9]{2})(-.*)?$") - .expect("failed creating regex"); - static ref INVALID_SEGMENT_REGEX: Regex = Regex::new(r"^0+$").expect("failed creating regex"); - static ref VALID_TAG_KEY_REGEX: Regex = - Regex::new(r"^_dd\.p\.[\x21-\x2b\x2d-\x7e]+$").expect("failed creating regex"); - static ref VALID_TAG_VALUE_REGEX: Regex = - Regex::new(r"^[\x20-\x2b\x2d-\x7e]*$").expect("failed creating regex"); - static ref INVALID_ASCII_CHARACTERS_REGEX: Regex = - Regex::new(r"[^\x20-\x7E]+").expect("failed creating regex"); - static ref VALID_SAMPLING_DECISION_REGEX: Regex = - Regex::new(r"^-([0-9])$").expect("failed creating regex"); -} +static TRACEPARENT_REGEX: LazyLock = LazyLock::new(|| { + Regex::new(r"(?i)^([a-f0-9]{2})-([a-f0-9]{32})-([a-f0-9]{16})-([a-f0-9]{2})(-.*)?$") + .expect("failed creating regex") +}); +static INVALID_SEGMENT_REGEX: LazyLock = + LazyLock::new(|| Regex::new(r"^0+$").expect("failed creating regex")); +#[allow(dead_code)] +static VALID_TAG_KEY_REGEX: LazyLock = LazyLock::new(|| { + Regex::new(r"^_dd\.p\.[\x21-\x2b\x2d-\x7e]+$").expect("failed creating regex") +}); +#[allow(dead_code)] +static VALID_TAG_VALUE_REGEX: LazyLock = + LazyLock::new(|| Regex::new(r"^[\x20-\x2b\x2d-\x7e]*$").expect("failed creating regex")); +static INVALID_ASCII_CHARACTERS_REGEX: LazyLock = + LazyLock::new(|| Regex::new(r"[^\x20-\x7E]+").expect("failed creating regex")); +static VALID_SAMPLING_DECISION_REGEX: LazyLock = + LazyLock::new(|| Regex::new(r"^-([0-9])$").expect("failed creating regex")); #[derive(Clone, Copy)] pub struct DatadogHeaderPropagator; @@ -168,21 +171,19 @@ impl DatadogHeaderPropagator { } // Handle 128bit trace ID - if !tags.is_empty() { - if let Some(trace_id_higher_order_bits) = + if !tags.is_empty() + && let Some(trace_id_higher_order_bits) = carrier.get(DATADOG_HIGHER_ORDER_TRACE_ID_BITS_KEY) - { - if !Self::higher_order_bits_valid(trace_id_higher_order_bits) { - warn!( - "Malformed Trace ID: {trace_id_higher_order_bits} Failed to decode trace ID from carrier." - ); - tags.insert( - DATADOG_PROPAGATION_ERROR_KEY.to_string(), - format!("malformed tid {trace_id_higher_order_bits}"), - ); - tags.remove(DATADOG_HIGHER_ORDER_TRACE_ID_BITS_KEY); - } - } + && !Self::higher_order_bits_valid(trace_id_higher_order_bits) + { + warn!( + "Malformed Trace ID: {trace_id_higher_order_bits} Failed to decode trace ID from carrier." + ); + tags.insert( + DATADOG_PROPAGATION_ERROR_KEY.to_string(), + format!("malformed tid {trace_id_higher_order_bits}"), + ); + tags.remove(DATADOG_HIGHER_ORDER_TRACE_ID_BITS_KEY); } if !tags.contains_key(DATADOG_SAMPLING_DECISION_KEY) { @@ -297,7 +298,7 @@ impl TraceContextPropagator { return None; } - tags.insert(TRACESTATE_KEY.to_string(), ts.to_string()); + tags.insert(TRACESTATE_KEY.to_string(), ts.clone()); let mut dd: Option> = None; for v in ts_v.clone() { @@ -321,10 +322,10 @@ impl TraceContextPropagator { lower_order_trace_id: None, }; - if let Some(ts_sp) = dd.get("s") { - if let Ok(p_sp) = ts_sp.parse::() { - tracestate.sampling_priority = Some(p_sp); - } + if let Some(ts_sp) = dd.get("s") + && let Ok(p_sp) = ts_sp.parse::() + { + tracestate.sampling_priority = Some(p_sp); } if let Some(o) = dd.get("o") { @@ -332,7 +333,7 @@ impl TraceContextPropagator { } if let Some(lo_tid) = dd.get("p") { - tracestate.lower_order_trace_id = Some(lo_tid.to_string()); + tracestate.lower_order_trace_id = Some(lo_tid.clone()); } // Convert from `t.` to `_dd.p.` @@ -357,12 +358,11 @@ impl TraceContextPropagator { traceparent_sampling_priority: i8, tracestate_sampling_priority: Option, ) -> i8 { - if let Some(ts_sp) = tracestate_sampling_priority { - if (traceparent_sampling_priority == 1 && ts_sp > 0) - || (traceparent_sampling_priority == 0 && ts_sp < 0) - { - return ts_sp; - } + if let Some(ts_sp) = tracestate_sampling_priority + && ((traceparent_sampling_priority == 1 && ts_sp > 0) + || (traceparent_sampling_priority == 0 && ts_sp < 0)) + { + return ts_sp; } traceparent_sampling_priority diff --git a/bottlecap/src/traces/proxy_flusher.rs b/bottlecap/src/traces/proxy_flusher.rs index a0de1d357..d41354697 100644 --- a/bottlecap/src/traces/proxy_flusher.rs +++ b/bottlecap/src/traces/proxy_flusher.rs @@ -144,10 +144,7 @@ impl Flusher { attempts += 1; let Some(cloned_request) = request.try_clone() else { - return Err(Box::new(std::io::Error::new( - std::io::ErrorKind::Other, - "can't clone proxy request", - ))); + return Err(Box::new(std::io::Error::other("can't clone proxy request"))); }; let time = std::time::Instant::now(); @@ -199,12 +196,11 @@ impl Flusher { let mut failed_requests: Vec = Vec::new(); for result in results { // There is no cleaner way to do this, so it's deeply nested. - if let Err(e) = result { - if let Some(fpre) = e.downcast_ref::() { - if let Some(request) = fpre.request.try_clone() { - failed_requests.push(request); - } - } + if let Err(e) = result + && let Some(fpre) = e.downcast_ref::() + && let Some(request) = fpre.request.try_clone() + { + failed_requests.push(request); } } diff --git a/bottlecap/src/traces/span_dedup.rs b/bottlecap/src/traces/span_dedup.rs index 9f937a415..89bdab705 100644 --- a/bottlecap/src/traces/span_dedup.rs +++ b/bottlecap/src/traces/span_dedup.rs @@ -87,10 +87,10 @@ impl Deduper { } // If we're at capacity, evict the oldest entry - if self.order.len() >= self.capacity { - if let Some(oldest) = self.order.pop_front() { - self.seen.remove(&oldest); - } + if self.order.len() >= self.capacity + && let Some(oldest) = self.order.pop_front() + { + self.seen.remove(&oldest); } // Add the new key diff --git a/bottlecap/src/traces/stats_flusher.rs b/bottlecap/src/traces/stats_flusher.rs index 222dddbd7..f860ff763 100644 --- a/bottlecap/src/traces/stats_flusher.rs +++ b/bottlecap/src/traces/stats_flusher.rs @@ -60,7 +60,7 @@ impl StatsFlusher { return None; }; - let api_key_clone = api_key.to_string(); + let api_key_clone = api_key.clone(); let endpoint = self .endpoint .get_or_init({ @@ -141,15 +141,15 @@ impl StatsFlusher { let mut all_failed: Vec = Vec::new(); // First, retry any previously failed stats - if let Some(retry_stats) = failed_stats { - if !retry_stats.is_empty() { - debug!( - "STATS | Retrying {} previously failed stats", - retry_stats.len() - ); - if let Some(still_failed) = self.send(retry_stats).await { - all_failed.extend(still_failed); - } + if let Some(retry_stats) = failed_stats + && !retry_stats.is_empty() + { + debug!( + "STATS | Retrying {} previously failed stats", + retry_stats.len() + ); + if let Some(still_failed) = self.send(retry_stats).await { + all_failed.extend(still_failed); } } diff --git a/bottlecap/src/traces/stats_processor.rs b/bottlecap/src/traces/stats_processor.rs index fd8c91260..86d3d81ff 100644 --- a/bottlecap/src/traces/stats_processor.rs +++ b/bottlecap/src/traces/stats_processor.rs @@ -51,18 +51,16 @@ impl StatsProcessor for ServerlessStatsProcessor { } }; - if let Some(content_length) = parts.headers.get("content-length") { - if let Ok(length_str) = content_length.to_str() { - if let Ok(length) = length_str.parse::() { - if length > MAX_CONTENT_LENGTH { - let error_msg = format!( - "Content-Length {length} exceeds maximum allowed size {MAX_CONTENT_LENGTH}" - ); - error!("{}", error_msg); - return Ok((StatusCode::PAYLOAD_TOO_LARGE, error_msg).into_response()); - } - } - } + if let Some(content_length) = parts.headers.get("content-length") + && let Ok(length_str) = content_length.to_str() + && let Ok(length) = length_str.parse::() + && length > MAX_CONTENT_LENGTH + { + let error_msg = format!( + "Content-Length {length} exceeds maximum allowed size {MAX_CONTENT_LENGTH}" + ); + error!("{}", error_msg); + return Ok((StatusCode::PAYLOAD_TOO_LARGE, error_msg).into_response()); } // deserialize trace stats from the request body, convert to protobuf structs (see diff --git a/bottlecap/src/traces/trace_agent.rs b/bottlecap/src/traces/trace_agent.rs index fd72ec251..96a16520e 100644 --- a/bottlecap/src/traces/trace_agent.rs +++ b/bottlecap/src/traces/trace_agent.rs @@ -584,13 +584,12 @@ impl TraceAgent { } } - if span.resource == INVOCATION_SPAN_RESOURCE { - if let Err(e) = invocation_processor_handle + if span.resource == INVOCATION_SPAN_RESOURCE + && let Err(e) = invocation_processor_handle .add_tracer_span(span.clone()) .await - { - error!("Failed to add tracer span to processor: {}", e); - } + { + error!("Failed to add tracer span to processor: {}", e); } handle_reparenting(&mut reparenting_info, &mut span); diff --git a/bottlecap/src/traces/trace_aggregator_service.rs b/bottlecap/src/traces/trace_aggregator_service.rs index 034bb050d..b8ffc4a30 100644 --- a/bottlecap/src/traces/trace_aggregator_service.rs +++ b/bottlecap/src/traces/trace_aggregator_service.rs @@ -7,7 +7,7 @@ use crate::traces::trace_aggregator::{ }; pub enum AggregatorCommand { - InsertPayload(SendDataBuilderInfo), + InsertPayload(Box), GetBatches(oneshot::Sender>>), Clear, Shutdown, @@ -23,7 +23,8 @@ impl AggregatorHandle { &self, payload_info: SendDataBuilderInfo, ) -> Result<(), mpsc::error::SendError> { - self.tx.send(AggregatorCommand::InsertPayload(payload_info)) + self.tx + .send(AggregatorCommand::InsertPayload(Box::new(payload_info))) } pub async fn get_batches(&self) -> Result>, String> { @@ -75,7 +76,7 @@ impl AggregatorService { while let Some(command) = self.rx.recv().await { match command { AggregatorCommand::InsertPayload(payload_info) => { - self.aggregator.add(payload_info); + self.aggregator.add(*payload_info); } AggregatorCommand::GetBatches(response_tx) => { let mut batches = Vec::new(); diff --git a/bottlecap/src/traces/trace_processor.rs b/bottlecap/src/traces/trace_processor.rs index 2a19e4566..8b3cc3e03 100644 --- a/bottlecap/src/traces/trace_processor.rs +++ b/bottlecap/src/traces/trace_processor.rs @@ -49,11 +49,11 @@ struct ChunkProcessor { impl TraceChunkProcessor for ChunkProcessor { fn process(&mut self, chunk: &mut pb::TraceChunk, root_span_index: usize) { - if let Some(root_span) = chunk.spans.get(root_span_index) { - if filter_span_by_tags(root_span, &self.config) { - chunk.spans.clear(); - return; - } + if let Some(root_span) = chunk.spans.get(root_span_index) + && filter_span_by_tags(root_span, &self.config) + { + chunk.spans.clear(); + return; } chunk @@ -62,10 +62,10 @@ impl TraceChunkProcessor for ChunkProcessor { for span in &mut chunk.spans { // Service name could be incorrectly set to 'aws.lambda' // in datadog lambda libraries - if span.service == "aws.lambda" { - if let Some(service) = self.tags_provider.get_tags_map().get("service") { - span.service.clone_from(service); - } + if span.service == "aws.lambda" + && let Some(service) = self.tags_provider.get_tags_map().get("service") + { + span.service.clone_from(service); } // Remove the _dd.base_service tag for unintentional service name override @@ -89,70 +89,70 @@ impl TraceChunkProcessor for ChunkProcessor { fn filter_span_by_tags(span: &Span, config: &config::Config) -> bool { // Handle required tags from DD_APM_FILTER_TAGS_REQUIRE (exact match) - if let Some(require_tags) = &config.apm_filter_tags_require { - if !require_tags.is_empty() { - let matches_require = require_tags - .iter() - .all(|filter| span_matches_tag_exact_filter(span, filter)); - if !matches_require { - debug!( - "TRACE_PROCESSOR | Filtering out span '{}' - doesn't match all required tags {}", - span.name, - require_tags.join(", ") - ); - return true; - } + if let Some(require_tags) = &config.apm_filter_tags_require + && !require_tags.is_empty() + { + let matches_require = require_tags + .iter() + .all(|filter| span_matches_tag_exact_filter(span, filter)); + if !matches_require { + debug!( + "TRACE_PROCESSOR | Filtering out span '{}' - doesn't match all required tags {}", + span.name, + require_tags.join(", ") + ); + return true; } } // Handle required regex tags from DD_APM_FILTER_TAGS_REGEX_REQUIRE (regex match) - if let Some(require_regex_tags) = &config.apm_filter_tags_regex_require { - if !require_regex_tags.is_empty() { - let matches_require_regex = require_regex_tags - .iter() - .all(|filter| span_matches_tag_regex_filter(span, filter)); - if !matches_require_regex { - debug!( - "TRACE_PROCESSOR | Filtering out span '{}' - doesn't match all required regex tags {}", - span.name, - require_regex_tags.join(", ") - ); - return true; - } + if let Some(require_regex_tags) = &config.apm_filter_tags_regex_require + && !require_regex_tags.is_empty() + { + let matches_require_regex = require_regex_tags + .iter() + .all(|filter| span_matches_tag_regex_filter(span, filter)); + if !matches_require_regex { + debug!( + "TRACE_PROCESSOR | Filtering out span '{}' - doesn't match all required regex tags {}", + span.name, + require_regex_tags.join(", ") + ); + return true; } } // Handle reject tags from DD_APM_FILTER_TAGS_REJECT (exact match) - if let Some(reject_tags) = &config.apm_filter_tags_reject { - if !reject_tags.is_empty() { - let matches_reject = reject_tags - .iter() - .any(|filter| span_matches_tag_exact_filter(span, filter)); - if matches_reject { - debug!( - "TRACE_PROCESSOR | Filtering out span '{}' - matches reject tags {}", - span.name, - reject_tags.join(", ") - ); - return true; - } + if let Some(reject_tags) = &config.apm_filter_tags_reject + && !reject_tags.is_empty() + { + let matches_reject = reject_tags + .iter() + .any(|filter| span_matches_tag_exact_filter(span, filter)); + if matches_reject { + debug!( + "TRACE_PROCESSOR | Filtering out span '{}' - matches reject tags {}", + span.name, + reject_tags.join(", ") + ); + return true; } } // Handle reject regex tags from DD_APM_FILTER_TAGS_REGEX_REJECT (regex match) - if let Some(reject_regex_tags) = &config.apm_filter_tags_regex_reject { - if !reject_regex_tags.is_empty() { - let matches_reject_regex = reject_regex_tags - .iter() - .any(|filter| span_matches_tag_regex_filter(span, filter)); - if matches_reject_regex { - debug!( - "TRACE_PROCESSOR | Filtering out span '{}' - matches reject regex tags {}", - span.name, - reject_regex_tags.join(", ") - ); - return true; - } + if let Some(reject_regex_tags) = &config.apm_filter_tags_regex_reject + && !reject_regex_tags.is_empty() + { + let matches_reject_regex = reject_regex_tags + .iter() + .any(|filter| span_matches_tag_regex_filter(span, filter)); + if matches_reject_regex { + debug!( + "TRACE_PROCESSOR | Filtering out span '{}' - matches reject regex tags {}", + span.name, + reject_regex_tags.join(", ") + ); + return true; } } @@ -190,10 +190,10 @@ fn span_matches_tag_regex_filter(span: &Span, filter: &str) -> bool { } fn span_matches_tag_exact(span: &Span, key: &str, value: &str) -> bool { - if let Some(span_value) = span.meta.get(key) { - if span_value == value { - return true; - } + if let Some(span_value) = span.meta.get(key) + && span_value == value + { + return true; } let span_property_value = match key { @@ -204,10 +204,10 @@ fn span_matches_tag_exact(span: &Span, key: &str, value: &str) -> bool { _ => None, }; - if let Some(prop_value) = span_property_value { - if prop_value == value { - return true; - } + if let Some(prop_value) = span_property_value + && prop_value == value + { + return true; } false @@ -222,10 +222,10 @@ fn span_matches_tag_regex(span: &Span, key: &str, value: &str) -> bool { return false; }; - if let Some(span_value) = span.meta.get(key) { - if regex.is_match(span_value) { - return true; - } + if let Some(span_value) = span.meta.get(key) + && regex.is_match(span_value) + { + return true; } let span_property_value = match key { @@ -235,10 +235,10 @@ fn span_matches_tag_regex(span: &Span, key: &str, value: &str) -> bool { "type" => Some(&span.r#type), _ => None, }; - if let Some(prop_value) = span_property_value { - if regex.is_match(prop_value) { - return true; - } + if let Some(prop_value) = span_property_value + && regex.is_match(prop_value) + { + return true; } false @@ -258,13 +258,12 @@ fn span_has_key(span: &Span, key: &str) -> bool { } fn filter_span_from_lambda_library_or_runtime(span: &Span) -> bool { - if let Some(url) = span.meta.get("http.url") { - if url.starts_with(LAMBDA_RUNTIME_URL_PREFIX) + if let Some(url) = span.meta.get("http.url") + && (url.starts_with(LAMBDA_RUNTIME_URL_PREFIX) || url.starts_with(LAMBDA_EXTENSION_URL_PREFIX) - || url.starts_with(LAMBDA_STATSD_URL_PREFIX) - { - return true; - } + || url.starts_with(LAMBDA_STATSD_URL_PREFIX)) + { + return true; } if let (Some(tcp_host), Some(tcp_port)) = ( @@ -282,13 +281,12 @@ fn filter_span_from_lambda_library_or_runtime(span: &Span) -> bool { } } - if let Some(dns_address) = span.meta.get("dns.address") { - if dns_address.starts_with(DNS_NON_ROUTABLE_ADDRESS_URL_PREFIX) + if let Some(dns_address) = span.meta.get("dns.address") + && (dns_address.starts_with(DNS_NON_ROUTABLE_ADDRESS_URL_PREFIX) || dns_address.starts_with(DNS_LOCAL_HOST_ADDRESS_URL_PREFIX) - || dns_address.starts_with(AWS_XRAY_DAEMON_ADDRESS_URL_PREFIX) - { - return true; - } + || dns_address.starts_with(AWS_XRAY_DAEMON_ADDRESS_URL_PREFIX)) + { + return true; } if span.resource == INVOCATION_SPAN_RESOURCE { return true; @@ -461,12 +459,12 @@ impl SendingTraceProcessor { // This needs to be after process_traces() because process_traces() // performs obfuscation, and we need to compute stats on the obfuscated traces. - if config.compute_trace_stats_on_extension { - if let Err(err) = self.stats_generator.send(&processed_traces) { - // Just log the error. We don't think trace stats are critical, so we don't want to - // return an error if only stats fail to send. - error!("TRACE_PROCESSOR | Error sending traces to the stats concentrator: {err}"); - } + if config.compute_trace_stats_on_extension + && let Err(err) = self.stats_generator.send(&processed_traces) + { + // Just log the error. We don't think trace stats are critical, so we don't want to + // return an error if only stats fail to send. + error!("TRACE_PROCESSOR | Error sending traces to the stats concentrator: {err}"); } Ok(()) } diff --git a/rust-toolchain.toml b/rust-toolchain.toml index 898a61f3f..585747e0c 100644 --- a/rust-toolchain.toml +++ b/rust-toolchain.toml @@ -1,4 +1,4 @@ [toolchain] -channel = "1.85.0" +channel = "1.93.1" components = [ "rustfmt", "clippy" ] profile = "minimal"