diff --git a/bottlecap/src/lifecycle/invocation/context.rs b/bottlecap/src/lifecycle/invocation/context.rs index 680a967ba..97e6bbf14 100644 --- a/bottlecap/src/lifecycle/invocation/context.rs +++ b/bottlecap/src/lifecycle/invocation/context.rs @@ -96,7 +96,7 @@ impl ContextBuffer { /// Creates a new `Context` and adds it to the buffer. /// pub fn create_context(&mut self, request_id: String) { - self.insert(Context::new(request_id, 0.0, 0.0, 0, None)); + self.insert(Context::new(request_id, 0f64, 0f64, 0, None)); } /// Adds the init duration to a `Context` in the buffer. @@ -188,20 +188,20 @@ mod tests { let mut buffer = ContextBuffer::with_capacity(2); let request_id = String::from("1"); - let context = Context::new(request_id.clone(), 0.0, 0.0, 0, None); + let context = Context::new(request_id.clone(), 0f64, 0f64, 0, None); buffer.insert(context.clone()); assert_eq!(buffer.size(), 1); assert_eq!(buffer.get(&request_id).unwrap(), &context); let request_id_2 = String::from("2"); - let context = Context::new(request_id_2.clone(), 0.0, 0.0, 0, None); + let context = Context::new(request_id_2.clone(), 0f64, 0f64, 0, None); buffer.insert(context.clone()); assert_eq!(buffer.size(), 2); assert_eq!(buffer.get(&request_id_2).unwrap(), &context); // This should replace the first context let request_id_3 = String::from("3"); - let context = Context::new(request_id_3.clone(), 0.0, 0.0, 0, None); + let context = Context::new(request_id_3.clone(), 0f64, 0f64, 0, None); buffer.insert(context.clone()); assert_eq!(buffer.size(), 2); assert_eq!(buffer.get(&request_id_3).unwrap(), &context); @@ -215,13 +215,13 @@ mod tests { let mut buffer = ContextBuffer::with_capacity(2); let request_id = String::from("1"); - let context = Context::new(request_id.clone(), 0.0, 0.0, 0, None); + let context = Context::new(request_id.clone(), 0f64, 0f64, 0, None); buffer.insert(context.clone()); assert_eq!(buffer.size(), 1); assert_eq!(buffer.get(&request_id).unwrap(), &context); let request_id_2 = String::from("2"); - let context = Context::new(request_id_2.clone(), 0.0, 0.0, 0, None); + let context = Context::new(request_id_2.clone(), 0f64, 0f64, 0, None); buffer.insert(context.clone()); assert_eq!(buffer.size(), 2); assert_eq!(buffer.get(&request_id_2).unwrap(), &context); @@ -242,13 +242,13 @@ mod tests { let mut buffer = ContextBuffer::with_capacity(2); let request_id = String::from("1"); - let context = Context::new(request_id.clone(), 0.0, 0.0, 0, None); + let context = Context::new(request_id.clone(), 0f64, 0f64, 0, None); buffer.insert(context.clone()); assert_eq!(buffer.size(), 1); assert_eq!(buffer.get(&request_id).unwrap(), &context); let request_id_2 = String::from("2"); - let context = Context::new(request_id_2.clone(), 0.0, 0.0, 0, None); + let context = Context::new(request_id_2.clone(), 0f64, 0f64, 0, None); buffer.insert(context.clone()); assert_eq!(buffer.size(), 2); assert_eq!(buffer.get(&request_id_2).unwrap(), &context); @@ -263,13 +263,13 @@ mod tests { let mut buffer = ContextBuffer::with_capacity(2); let request_id = String::from("1"); - let context = Context::new(request_id.clone(), 0.0, 0.0, 0, None); + let context = Context::new(request_id.clone(), 0f64, 0f64, 0, None); buffer.insert(context.clone()); assert_eq!(buffer.size(), 1); assert_eq!(buffer.get(&request_id).unwrap(), &context); - buffer.add_init_duration(&request_id, 100.0); - assert_eq!(buffer.get(&request_id).unwrap().init_duration_ms, 100.0); + buffer.add_init_duration(&request_id, 100f64); + assert!((buffer.get(&request_id).unwrap().init_duration_ms - 100f64).abs() < f64::EPSILON); } #[test] @@ -277,7 +277,7 @@ mod tests { let mut buffer = ContextBuffer::with_capacity(2); let request_id = String::from("1"); - let context = Context::new(request_id.clone(), 0.0, 0.0, 0, None); + let context = Context::new(request_id.clone(), 0f64, 0f64, 0, None); buffer.insert(context.clone()); assert_eq!(buffer.size(), 1); assert_eq!(buffer.get(&request_id).unwrap(), &context); @@ -291,13 +291,15 @@ mod tests { let mut buffer = ContextBuffer::with_capacity(2); let request_id = String::from("1"); - let context = Context::new(request_id.clone(), 0.0, 0.0, 0, None); + let context = Context::new(request_id.clone(), 0f64, 0f64, 0, None); buffer.insert(context.clone()); assert_eq!(buffer.size(), 1); assert_eq!(buffer.get(&request_id).unwrap(), &context); - buffer.add_runtime_duration(&request_id, 100.0); - assert_eq!(buffer.get(&request_id).unwrap().runtime_duration_ms, 100.0); + buffer.add_runtime_duration(&request_id, 100f64); + assert!( + (buffer.get(&request_id).unwrap().runtime_duration_ms - 100f64).abs() < f64::EPSILON + ); } #[test] @@ -305,27 +307,27 @@ mod tests { let mut buffer = ContextBuffer::with_capacity(2); let request_id = String::from("1"); - let context = Context::new(request_id.clone(), 0.0, 0.0, 0, None); + let context = Context::new(request_id.clone(), 0f64, 0f64, 0, None); buffer.insert(context.clone()); assert_eq!(buffer.size(), 1); assert_eq!(buffer.get(&request_id).unwrap(), &context); let network_offset = Some(NetworkData { - rx_bytes: 180.0, + rx_bytes: 180f64, tx_bytes: 254.0, }); let mut individual_cpu_idle_times = HashMap::new(); - individual_cpu_idle_times.insert("cpu0".to_string(), 10.0); - individual_cpu_idle_times.insert("cpu1".to_string(), 20.0); + individual_cpu_idle_times.insert("cpu0".to_string(), 10f64); + individual_cpu_idle_times.insert("cpu1".to_string(), 20f64); let cpu_offset = Some(CPUData { - total_user_time_ms: 100.0, + total_user_time_ms: 100f64, total_system_time_ms: 53.0, - total_idle_time_ms: 20.0, + total_idle_time_ms: 20f64, individual_cpu_idle_times, }); - let uptime_offset = Some(50.0); + let uptime_offset = Some(50f64); let (tmp_chan_tx, _) = watch::channel(()); let (process_chan_tx, _) = watch::channel(()); diff --git a/bottlecap/src/lifecycle/invocation/span_inferrer.rs b/bottlecap/src/lifecycle/invocation/span_inferrer.rs index 3391bc689..a916305f7 100644 --- a/bottlecap/src/lifecycle/invocation/span_inferrer.rs +++ b/bottlecap/src/lifecycle/invocation/span_inferrer.rs @@ -17,7 +17,7 @@ use crate::lifecycle::invocation::{ lambda_function_url_event::LambdaFunctionUrlEvent, s3_event::S3Record, sns_event::{SnsEntity, SnsRecord}, - sqs_event::SqsRecord, + sqs_event::{extract_trace_context_from_aws_trace_header, SqsRecord}, step_function_event::StepFunctionEvent, Trigger, FUNCTION_TRIGGER_EVENT_SOURCE_ARN_TAG, }, @@ -35,7 +35,7 @@ pub struct SpanInferrer { is_async_span: bool, // Carrier to extract the span context from carrier: Option>, - // Generated Span Context from Step Functions + // Generated Span Context from Step Functions or context taken from `AWSTraceHeader` when java->sqs->java generated_span_context: Option, // Tags generated from the trigger trigger_tags: Option>, @@ -74,6 +74,8 @@ impl SpanInferrer { ..Default::default() }; + let mut is_step_function = false; + if APIGatewayHttpEvent::is_match(payload_value) { if let Some(t) = APIGatewayHttpEvent::new(payload_value.clone()) { t.enrich_span(&mut inferred_span, &self.service_mapping); @@ -96,6 +98,10 @@ impl SpanInferrer { if let Some(t) = SqsRecord::new(payload_value.clone()) { t.enrich_span(&mut inferred_span, &self.service_mapping); + self.generated_span_context = extract_trace_context_from_aws_trace_header( + t.attributes.aws_trace_header.clone(), + ); + // Check for SNS event wrapped in the SQS body if let Ok(sns_entity) = serde_json::from_str::(&t.body) { debug!("Found an SNS event wrapped in the SQS body"); @@ -191,6 +197,7 @@ impl SpanInferrer { if let Some(t) = StepFunctionEvent::new(payload_value.clone()) { self.generated_span_context = Some(t.get_span_context()); trigger = Some(Box::new(t)); + is_step_function = true; } } else { debug!("Unable to infer span from payload: no matching trigger found"); @@ -209,7 +216,7 @@ impl SpanInferrer { self.is_async_span = t.is_async(); // For Step Functions, there is no inferred span - if self.generated_span_context.is_some() { + if is_step_function && self.generated_span_context.is_some() { self.inferred_span = None; } else { self.inferred_span = Some(inferred_span); @@ -295,8 +302,8 @@ impl SpanInferrer { /// pub fn get_span_context(&self, propagator: &impl Propagator) -> Option { // Step Functions `SpanContext` is deterministically generated - if let Some(sc) = &self.generated_span_context { - return Some(sc.clone()); + if self.generated_span_context.is_some() { + return self.generated_span_context.clone(); } if let Some(sc) = self.carrier.as_ref().and_then(|c| propagator.extract(c)) { diff --git a/bottlecap/src/lifecycle/invocation/triggers/lambda_function_url_event.rs b/bottlecap/src/lifecycle/invocation/triggers/lambda_function_url_event.rs index 14a2eaa32..18bdc734d 100644 --- a/bottlecap/src/lifecycle/invocation/triggers/lambda_function_url_event.rs +++ b/bottlecap/src/lifecycle/invocation/triggers/lambda_function_url_event.rs @@ -225,7 +225,7 @@ mod tests { ]), request_context: RequestContext { request_id: String::from("ec4d58f8-2b8b-4ceb-a1d5-2be7bff58505"), - time_epoch: 1637169449721, + time_epoch: 1_637_169_449_721, http: Http { method: String::from("GET"), path: String::from("/"), diff --git a/bottlecap/src/lifecycle/invocation/triggers/s3_event.rs b/bottlecap/src/lifecycle/invocation/triggers/s3_event.rs index d45dc1f50..43065cb0f 100644 --- a/bottlecap/src/lifecycle/invocation/triggers/s3_event.rs +++ b/bottlecap/src/lifecycle/invocation/triggers/s3_event.rs @@ -134,6 +134,7 @@ impl ServiceNameResolver for S3Record { } #[cfg(test)] +#[allow(clippy::unwrap_used)] mod tests { use super::*; use crate::lifecycle::invocation::triggers::test_utils::read_json_file; diff --git a/bottlecap/src/lifecycle/invocation/triggers/sns_event.rs b/bottlecap/src/lifecycle/invocation/triggers/sns_event.rs index 47091a9d6..091dcdf53 100644 --- a/bottlecap/src/lifecycle/invocation/triggers/sns_event.rs +++ b/bottlecap/src/lifecycle/invocation/triggers/sns_event.rs @@ -174,6 +174,7 @@ impl ServiceNameResolver for SnsRecord { } #[cfg(test)] +#[allow(clippy::unwrap_used)] mod tests { use datadog_trace_protobuf::pb::Span; diff --git a/bottlecap/src/lifecycle/invocation/triggers/sqs_event.rs b/bottlecap/src/lifecycle/invocation/triggers/sqs_event.rs index c9766a736..a4bf0e44f 100644 --- a/bottlecap/src/lifecycle/invocation/triggers/sqs_event.rs +++ b/bottlecap/src/lifecycle/invocation/triggers/sqs_event.rs @@ -13,6 +13,7 @@ use crate::lifecycle::invocation::{ ServiceNameResolver, Trigger, DATADOG_CARRIER_KEY, FUNCTION_TRIGGER_EVENT_SOURCE_TAG, }, }; +use crate::traces::context::{Sampling, SpanContext}; #[derive(Debug, Serialize, Deserialize, Clone, PartialEq)] pub struct SqsEvent { @@ -64,6 +65,8 @@ pub struct Attributes { pub sent_timestamp: String, #[serde(rename = "SenderId")] pub sender_id: String, + #[serde(rename = "AWSTraceHeader")] + pub aws_trace_header: Option, } impl Trigger for SqsRecord { @@ -163,12 +166,9 @@ impl Trigger for SqsRecord { } } - fn is_async(&self) -> bool { - true - } - 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(); @@ -190,6 +190,10 @@ impl Trigger for SqsRecord { // TODO: AWSTraceHeader carrier } + + fn is_async(&self) -> bool { + true + } } impl ServiceNameResolver for SqsRecord { @@ -206,7 +210,74 @@ impl ServiceNameResolver for SqsRecord { } } +// extractTraceContextfromAWSTraceHeader extracts trace context from the +// AWSTraceHeader directly. Unlike the other carriers in this file, it should +// not be passed to the tracer.Propagator, instead extracting context directly. +pub(crate) fn extract_trace_context_from_aws_trace_header( + headers_string: Option, +) -> Option { + let value = headers_string?; + if !value.starts_with("Root=") { + return None; + } + + let mut start_part = 0; + let mut trace_id = String::new(); + let mut parent_id = String::new(); + let mut sampled = String::new(); + + let length = value.len(); + while start_part < length { + let end_part = value[start_part..] + .find(';') + .map_or(length, |i| i + start_part); + let part = &value[start_part..end_part]; + + if part.starts_with("Root=") { + if trace_id.is_empty() { + trace_id = part[24..].to_string(); + } + } else if let Some(parent_part) = part.strip_prefix("Parent=") { + if parent_id.is_empty() { + parent_id = parent_part.to_string(); + } + } else if part.starts_with("Sampled=") && sampled.is_empty() { + sampled = part[8..].to_string(); + } + + if !trace_id.is_empty() && !parent_id.is_empty() && !sampled.is_empty() { + break; + } + start_part = end_part + 1; + } + + let trace_id = u64::from_str_radix(&trace_id, 16).ok()?; + let parent_id = u64::from_str_radix(&parent_id, 16).ok()?; + + if trace_id == 0 || parent_id == 0 { + debug!("awstrace_header contains empty trace or parent ID"); + return None; + } + + let sampling_priority = i8::from(sampled == "1"); + + Some(SpanContext { + // the context from AWS Header is used by Datadog only and does not contain the upper + // 64 bits like other 128 w3c compliant trace ids + trace_id, + span_id: parent_id, + sampling: Some(Sampling { + priority: Some(sampling_priority), + mechanism: None, + }), + origin: None, + tags: HashMap::new(), + links: Vec::new(), + }) +} + #[cfg(test)] +#[allow(clippy::unwrap_used)] mod tests { use super::*; use crate::lifecycle::invocation::triggers::test_utils::read_json_file; @@ -235,6 +306,7 @@ mod tests { approximate_receive_count: "1".to_string(), sent_timestamp: "1523232000000".to_string(), sender_id: "123456789012".to_string(), + aws_trace_header: None, }, message_attributes, md5_of_body: "{{{md5_of_body}}}".to_string(), @@ -425,4 +497,29 @@ mod tests { "generic-service" ); } + + #[test] + fn extract_java_sqs_header_context() { + let json = read_json_file("eventbridge_sqs_java_header_event.json"); + let payload = serde_json::from_str(&json).expect("Failed to deserialize into Value"); + let event = SqsRecord::new(payload).expect("Failed to deserialize EventBridgeEvent"); + + assert_eq!( + extract_trace_context_from_aws_trace_header(Some( + event.attributes.aws_trace_header.unwrap().to_string() + )) + .unwrap(), + SpanContext { + trace_id: 130_944_522_478_755_159, + span_id: 9_032_698_535_745_367_362, + sampling: Some(Sampling { + priority: Some("0".parse().unwrap()), + mechanism: None, + }), + origin: None, + tags: HashMap::new(), + links: Vec::new(), + } + ); + } } diff --git a/bottlecap/src/lifecycle/invocation/triggers/step_function_event.rs b/bottlecap/src/lifecycle/invocation/triggers/step_function_event.rs index ee77434bc..6169be7d3 100644 --- a/bottlecap/src/lifecycle/invocation/triggers/step_function_event.rs +++ b/bottlecap/src/lifecycle/invocation/triggers/step_function_event.rs @@ -322,8 +322,8 @@ mod tests { let span_context = event.get_span_context(); let expected = SpanContext { - trace_id: 5744042798732701615, - span_id: 2902498116043018663, + trace_id: 5_744_042_798_732_701_615, + span_id: 2_902_498_116_043_018_663, sampling: Some(Sampling { priority: Some(1), mechanism: None, @@ -347,7 +347,7 @@ mod tests { String::from("2022-12-08T21:08:19.224Z") ); - assert_eq!(parent_id, 4340734536022949921); + assert_eq!(parent_id, 4_340_734_536_022_949_921); let parent_id = StepFunctionEvent::generate_parent_id( String::from("arn:aws:states:sa-east-1:601427271234:express:DatadogStateMachine:acaf1a67-336a-e854-1599-2a627eb2dd8a:c8baf081-31f1-464d-971f-70cb17d01111"), @@ -355,7 +355,7 @@ mod tests { String::from("2022-12-08T21:08:19.224Y") ); - assert_eq!(parent_id, 981693280319792699); + assert_eq!(parent_id, 981_693_280_319_792_699); } #[test] @@ -363,20 +363,20 @@ mod tests { let (lo_tid, hi_tid) = StepFunctionEvent::generate_trace_id(String::from( "arn:aws:states:sa-east-1:425362996713:stateMachine:MyStateMachine-b276uka1j", )); - let hex_tid = format!("{:x}", hi_tid); + let hex_tid = format!("{hi_tid:x}"); - assert_eq!(lo_tid, 1680583253837593461); - assert_eq!(hi_tid, 6984552746569958392); + assert_eq!(lo_tid, 1_680_583_253_837_593_461); + assert_eq!(hi_tid, 6_984_552_746_569_958_392); assert_eq!(hex_tid, "60ee1db79e4803f8"); let (lo_tid, hi_tid) = StepFunctionEvent::generate_trace_id( String::from("arn:aws:states:us-east-1:425362996713:execution:agocsTestSF:bc9f281c-3daa-4e5a-9a60-471a3810bf44") ); - let hex_tid = format!("{:x}", hi_tid); + let hex_tid = format!("{hi_tid:x}"); - assert_eq!(lo_tid, 5744042798732701615); - assert_eq!(hi_tid, 1807349139850867390); + assert_eq!(lo_tid, 5_744_042_798_732_701_615); + assert_eq!(hi_tid, 1_807_349_139_850_867_390); assert_eq!(hex_tid, "1914fe7789eb32be"); } diff --git a/bottlecap/src/metrics/enhanced/lambda.rs b/bottlecap/src/metrics/enhanced/lambda.rs index af5996ff6..f307b979b 100644 --- a/bottlecap/src/metrics/enhanced/lambda.rs +++ b/bottlecap/src/metrics/enhanced/lambda.rs @@ -743,6 +743,7 @@ mod tests { } #[test] + #[allow(clippy::too_many_lines)] fn test_disabled() { let (metrics_aggr, no_config) = setup(); let my_config = Arc::new(config::Config { @@ -991,8 +992,8 @@ mod tests { let (metrics_aggr, my_config) = setup(); let lambda = Lambda::new(metrics_aggr.clone(), my_config); - let tmp_max = 550461440.0; - let tmp_used = 12165120.0; + let tmp_max = 550_461_440.0; + let tmp_used = 12_165_120.0; Lambda::generate_tmp_enhanced_metrics( tmp_max, @@ -1001,9 +1002,9 @@ mod tests { None, ); - assert_sketch(&metrics_aggr, constants::TMP_MAX_METRIC, 550461440.0); - assert_sketch(&metrics_aggr, constants::TMP_USED_METRIC, 12165120.0); - assert_sketch(&metrics_aggr, constants::TMP_FREE_METRIC, 538296320.0); + assert_sketch(&metrics_aggr, constants::TMP_MAX_METRIC, 550_461_440.0); + assert_sketch(&metrics_aggr, constants::TMP_USED_METRIC, 12_165_120.0); + assert_sketch(&metrics_aggr, constants::TMP_FREE_METRIC, 538_296_320.0); } #[test] diff --git a/bottlecap/src/proc/mod.rs b/bottlecap/src/proc/mod.rs index 2aaf17474..f6fa819c2 100644 --- a/bottlecap/src/proc/mod.rs +++ b/bottlecap/src/proc/mod.rs @@ -330,8 +330,6 @@ mod tests { use super::*; use std::path::PathBuf; - const PRECISION: f64 = 1e-6; - fn path_from_root(file: &str) -> String { let mut safe_path = PathBuf::from(env!("CARGO_MANIFEST_DIR")); safe_path.push(file); @@ -341,8 +339,8 @@ mod tests { #[test] fn test_get_pid_list() { let path = "./tests/proc"; - let mut pids = get_pid_list_from_path(path); - pids.sort(); + let mut pids = get_pid_list_from_path(path_from_root(path).as_str()); + pids.sort_unstable(); assert_eq!(pids.len(), 2); assert_eq!(pids[0], 13); assert_eq!(pids[1], 142); @@ -358,8 +356,8 @@ mod tests { let network_data_result = get_network_data_from_path(path_from_root(path).as_str()); assert!(network_data_result.is_ok()); let network_data = network_data_result.unwrap(); - assert!((network_data.rx_bytes - 180.0).abs() < PRECISION); - assert!((network_data.tx_bytes - 254.0).abs() < PRECISION); + assert!((network_data.rx_bytes - 180.0).abs() < f64::EPSILON); + assert!((network_data.tx_bytes - 254.0).abs() < f64::EPSILON); let path = "./tests/proc/net/invalid_dev_malformed"; let network_data_result = get_network_data_from_path(path); @@ -384,9 +382,9 @@ mod tests { let cpu_data_result = get_cpu_data_from_path(path_from_root(path).as_str()); assert!(cpu_data_result.is_ok()); let cpu_data = cpu_data_result.unwrap(); - assert!((cpu_data.total_user_time_ms - 23370.0).abs() < PRECISION); - assert!((cpu_data.total_system_time_ms - 1880.0).abs() < PRECISION); - assert!((cpu_data.total_idle_time_ms - 178_380.0).abs() < PRECISION); + assert!((cpu_data.total_user_time_ms - 23370.0).abs() < f64::EPSILON); + assert!((cpu_data.total_system_time_ms - 1880.0).abs() < f64::EPSILON); + assert!((cpu_data.total_idle_time_ms - 178_380.0).abs() < f64::EPSILON); assert_eq!(cpu_data.individual_cpu_idle_times.len(), 2); assert!( (*cpu_data @@ -395,7 +393,7 @@ mod tests { .expect("cpu0 not found") - 91880.0) .abs() - < PRECISION + < f64::EPSILON ); assert!( (*cpu_data @@ -404,7 +402,7 @@ mod tests { .expect("cpu1 not found") - 86490.0) .abs() - < PRECISION + < f64::EPSILON ); let path = "./tests/proc/stat/invalid_stat_non_numerical_value_1"; @@ -438,7 +436,7 @@ mod tests { let uptime_data_result = get_uptime_from_path(path_from_root(path).as_str()); assert!(uptime_data_result.is_ok()); let uptime_data = uptime_data_result.unwrap(); - assert!((uptime_data - 3_213_103_123_000.0).abs() < PRECISION); + assert!((uptime_data - 3_213_103_123_000.0).abs() < f64::EPSILON); let path = "./tests/proc/uptime/invalid_data_uptime"; let uptime_data_result = get_uptime_from_path(path); @@ -456,29 +454,29 @@ mod tests { #[test] fn test_get_fd_max_data() { let path = "./tests/proc/process/valid"; - let pids = get_pid_list_from_path(path); + let pids = get_pid_list_from_path(path_from_root(path).as_str()); let fd_max = get_fd_max_data_from_path(path, &pids); - assert!((fd_max - 900.0).abs() < PRECISION); + assert!((fd_max - 900.0).abs() < f64::EPSILON); let path = "./tests/proc/process/invalid_malformed"; let fd_max = get_fd_max_data_from_path(path, &pids); // assert that fd_max is equal to AWS Lambda limit - assert!((fd_max - constants::LAMBDA_FILE_DESCRIPTORS_DEFAULT_LIMIT).abs() < PRECISION); + assert!((fd_max - constants::LAMBDA_FILE_DESCRIPTORS_DEFAULT_LIMIT).abs() < f64::EPSILON); let path = "./tests/proc/process/invalid_missing"; let fd_max = get_fd_max_data_from_path(path, &pids); // assert that fd_max is equal to AWS Lambda limit - assert!((fd_max - constants::LAMBDA_FILE_DESCRIPTORS_DEFAULT_LIMIT).abs() < PRECISION); + assert!((fd_max - constants::LAMBDA_FILE_DESCRIPTORS_DEFAULT_LIMIT).abs() < f64::EPSILON); } #[test] fn test_get_fd_use_data() { let path = "./tests/proc/process/valid"; - let pids = get_pid_list_from_path(path); + let pids = get_pid_list_from_path(path_from_root(path).as_str()); let fd_use_result = get_fd_use_data_from_path(path, &pids); assert!(fd_use_result.is_ok()); let fd_use = fd_use_result.unwrap(); - assert!((fd_use - 5.0).abs() < PRECISION); + assert!((fd_use - 5.0).abs() < f64::EPSILON); let path = "./tests/proc/process/invalid_missing"; let fd_use_result = get_fd_use_data_from_path(path, &pids); @@ -488,33 +486,35 @@ mod tests { #[test] fn test_get_threads_max_data() { let path = "./tests/proc/process/valid"; - let pids = get_pid_list_from_path(path); + let pids = get_pid_list_from_path(path_from_root(path).as_str()); let threads_max = get_threads_max_data_from_path(path, &pids); - assert!((threads_max - 1024.0).abs() < PRECISION); + assert!((threads_max - 1024.0).abs() < f64::EPSILON); let path = "./tests/proc/process/invalid_malformed"; let threads_max = get_threads_max_data_from_path(path, &pids); // assert that threads_max is equal to AWS Lambda limit assert!( - (threads_max - constants::LAMBDA_EXECUTION_PROCESSES_DEFAULT_LIMIT).abs() < PRECISION + (threads_max - constants::LAMBDA_EXECUTION_PROCESSES_DEFAULT_LIMIT).abs() + < f64::EPSILON ); let path = "./tests/proc/process/invalid_missing"; let threads_max = get_threads_max_data_from_path(path, &pids); // assert that threads_max is equal to AWS Lambda limit assert!( - (threads_max - constants::LAMBDA_EXECUTION_PROCESSES_DEFAULT_LIMIT).abs() < PRECISION + (threads_max - constants::LAMBDA_EXECUTION_PROCESSES_DEFAULT_LIMIT).abs() + < f64::EPSILON ); } #[test] fn test_get_threads_use_data() { let path = "./tests/proc/process/valid"; - let pids = get_pid_list_from_path(path); + let pids = get_pid_list_from_path(path_from_root(path).as_str()); let threads_use_result = get_threads_use_data_from_path(path, &pids); assert!(threads_use_result.is_ok()); let threads_use = threads_use_result.unwrap(); - assert!((threads_use - 5.0).abs() < PRECISION); + assert!((threads_use - 5.0).abs() < f64::EPSILON); let path = "./tests/proc/process/invalid_missing"; let threads_use_result = get_threads_use_data_from_path(path, &pids); diff --git a/bottlecap/src/traces/propagation/mod.rs b/bottlecap/src/traces/propagation/mod.rs index 723666406..300e6eff9 100644 --- a/bottlecap/src/traces/propagation/mod.rs +++ b/bottlecap/src/traces/propagation/mod.rs @@ -211,9 +211,13 @@ pub mod tests { use super::*; + fn lower_64_bits(value: u128) -> u64 { + (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 = *TRACE_ID as u64; + static ref TRACE_ID_LOWER_ORDER_BITS: u64 = lower_64_bits(*TRACE_ID); static ref TRACE_ID_HEX: String = String::from("80f198ee56343ba864fe8b2a57d3eff7"); // TraceContext Headers @@ -771,13 +775,15 @@ pub mod tests { #[test] fn test_new_filter_propagators() { - let mut config = config::Config::default(); - config.trace_propagation_style_extract = vec![ - TracePropagationStyle::Datadog, - TracePropagationStyle::TraceContext, - TracePropagationStyle::B3, - TracePropagationStyle::B3Multi, - ]; + let config = config::Config { + trace_propagation_style_extract: vec![ + TracePropagationStyle::Datadog, + TracePropagationStyle::TraceContext, + TracePropagationStyle::B3, + TracePropagationStyle::B3Multi, + ], + ..Default::default() + }; let propagator = DatadogCompositePropagator::new(Arc::new(config)); @@ -786,8 +792,10 @@ pub mod tests { #[test] fn test_new_no_propagators() { - let mut config = config::Config::default(); - config.trace_propagation_style_extract = vec![TracePropagationStyle::None]; + let config = config::Config { + trace_propagation_style_extract: vec![TracePropagationStyle::None], + ..Default::default() + }; let propagator = DatadogCompositePropagator::new(Arc::new(config)); assert_eq!(propagator.propagators.len(), 0); @@ -795,11 +803,13 @@ pub mod tests { #[test] fn test_extract_available_contexts() { - let mut config = config::Config::default(); - config.trace_propagation_style_extract = vec![ - TracePropagationStyle::Datadog, - TracePropagationStyle::TraceContext, - ]; + let config = config::Config { + trace_propagation_style_extract: vec![ + TracePropagationStyle::Datadog, + TracePropagationStyle::TraceContext, + ], + ..Default::default() + }; let propagator = DatadogCompositePropagator::new(Arc::new(config)); @@ -835,8 +845,10 @@ pub mod tests { #[test] fn test_extract_available_contexts_no_contexts() { - let mut config = config::Config::default(); - config.trace_propagation_style_extract = vec![TracePropagationStyle::Datadog]; + let config = config::Config { + trace_propagation_style_extract: vec![TracePropagationStyle::Datadog], + ..Default::default() + }; let propagator = DatadogCompositePropagator::new(Arc::new(config)); @@ -868,6 +880,6 @@ pub mod tests { DatadogCompositePropagator::attach_baggage(&mut context, &carrier); assert_eq!(context.tags.len(), 1); - assert_eq!(context.tags.get("key1").unwrap(), "value1"); + assert_eq!(context.tags.get("key1").expect("Missing tag"), "value1"); } } diff --git a/bottlecap/src/traces/propagation/text_map_propagator.rs b/bottlecap/src/traces/propagation/text_map_propagator.rs index f1c5cbcf4..520428630 100644 --- a/bottlecap/src/traces/propagation/text_map_propagator.rs +++ b/bottlecap/src/traces/propagation/text_map_propagator.rs @@ -456,6 +456,7 @@ impl TraceContextPropagator { } #[cfg(test)] +#[allow(clippy::unwrap_used)] mod test { use super::*; diff --git a/bottlecap/tests/payloads/eventbridge_sqs_event.json b/bottlecap/tests/payloads/eventbridge_sqs_event.json index 033740244..b3a392a50 100644 --- a/bottlecap/tests/payloads/eventbridge_sqs_event.json +++ b/bottlecap/tests/payloads/eventbridge_sqs_event.json @@ -6,7 +6,6 @@ "body": "{\"version\":\"0\",\"id\":\"af718b2a-b987-e8c0-7a2b-a188fad2661a\",\"detail-type\":\"my.Detail\",\"source\":\"my.Source\",\"account\":\"425362996713\",\"time\":\"2023-08-03T22:49:03Z\",\"region\":\"us-east-1\",\"resources\":[],\"detail\":{\"text\":\"Hello, world!\",\"_datadog\":{\"x-datadog-trace-id\":\"7379586022458917877\",\"x-datadog-parent-id\":\"2644033662113726488\",\"x-datadog-sampling-priority\":\"1\",\"x-datadog-tags\":\"_dd.p.dm=-0\",\"traceparent\":\"00-000000000000000066698e63821a03f5-24b17e9b6476c018-01\",\"tracestate\":\"dd=t.dm:-0;s:1\"}}}", "attributes": { "ApproximateReceiveCount": "1", - "AWSTraceHeader": "Root=1-64cc2edd-112fbf1701d1355973a11d57;Parent=7d5a9776024b2d42;Sampled=0", "SentTimestamp": "1691102943638", "SenderId": "AIDAJXNJGGKNS7OSV23OI", "ApproximateFirstReceiveTimestamp": "1691102943647" diff --git a/bottlecap/tests/payloads/eventbridge_sqs_java_header_event.json b/bottlecap/tests/payloads/eventbridge_sqs_java_header_event.json new file mode 100644 index 000000000..033740244 --- /dev/null +++ b/bottlecap/tests/payloads/eventbridge_sqs_java_header_event.json @@ -0,0 +1,21 @@ +{ + "Records": [ + { + "messageId": "e995e54f-1724-41fa-82c0-8b81821f854e", + "receiptHandle": "AQEB4mIfRcyqtzn1X5Ss+ConhTejVGc+qnAcmu3/Z9ZvbNkaPcpuDLX/bzvPD/ZkAXJUXZcemGSJmd7L3snZHKMP2Ck8runZiyl4mubiLb444pZvdiNPuGRJ6a3FvgS/GQPzho/9nNMyOi66m8Viwh70v4EUCPGO4JmD3TTDAUrrcAnqU4WSObjfC/NAp9bI6wH2CEyAYEfex6Nxplbl/jBf9ZUG0I3m3vQd0Q4l4gd4jIR4oxQUglU2Tldl4Kx5fMUAhTRLAENri6HsY81avBkKd9FAuxONlsITB5uj02kOkvLlRGEcalqsKyPJ7AFaDLrOLaL3U+yReroPEJ5R5nwhLOEbeN5HROlZRXeaAwZOIN8BjqdeooYTIOrtvMEVb7a6OPLMdH1XB+ddevtKAH8K9Tm2ZjpaA7dtBGh1zFVHzBk=", + "body": "{\"version\":\"0\",\"id\":\"af718b2a-b987-e8c0-7a2b-a188fad2661a\",\"detail-type\":\"my.Detail\",\"source\":\"my.Source\",\"account\":\"425362996713\",\"time\":\"2023-08-03T22:49:03Z\",\"region\":\"us-east-1\",\"resources\":[],\"detail\":{\"text\":\"Hello, world!\",\"_datadog\":{\"x-datadog-trace-id\":\"7379586022458917877\",\"x-datadog-parent-id\":\"2644033662113726488\",\"x-datadog-sampling-priority\":\"1\",\"x-datadog-tags\":\"_dd.p.dm=-0\",\"traceparent\":\"00-000000000000000066698e63821a03f5-24b17e9b6476c018-01\",\"tracestate\":\"dd=t.dm:-0;s:1\"}}}", + "attributes": { + "ApproximateReceiveCount": "1", + "AWSTraceHeader": "Root=1-64cc2edd-112fbf1701d1355973a11d57;Parent=7d5a9776024b2d42;Sampled=0", + "SentTimestamp": "1691102943638", + "SenderId": "AIDAJXNJGGKNS7OSV23OI", + "ApproximateFirstReceiveTimestamp": "1691102943647" + }, + "messageAttributes": {}, + "md5OfBody": "93d9f0cd8886d1e000a1a0b7007bffc4", + "eventSource": "aws:sqs", + "eventSourceARN": "arn:aws:sqs:us-east-1:425362996713:lambda-eb-sqs-lambda-dev-demo-queue", + "awsRegion": "us-east-1" + } + ] +}