1 use super::{OnItem, JAVA_ARGUMENT_REGISTER_OFFSET}; 2 use anyhow::{anyhow, Result}; 3 use log::debug; 4 use protobuf::MessageField; 5 use statssocket::AStatsEvent; 6 use uprobestats_bpf_bindgen::{CallResult, CallTimestamp}; 7 use uprobestats_proto::config::uprobestats_config::Task; 8 9 // SAFETY: `CallTimestamp` is a struct defined in the given `MAP_PATH`, and is guaranteed to match the 10 // layout of the corresponding C struct. 11 unsafe impl OnItem for CallTimestamp { 12 const MAP_PATH: &'static str = 13 "/sys/fs/bpf/uprobestats/map_GenericInstrumentation_call_timestamp_buf"; on_item(&self, task: &Task) -> Result<()>14 fn on_item(&self, task: &Task) -> Result<()> { 15 debug!("CallTimestamp - event: {}, timestamp_ns: {}", self.event, self.timestampNs,); 16 17 let MessageField(Some(ref statsd_logging_config)) = task.statsd_logging_config else { 18 return Ok(()); 19 }; 20 21 debug!("has logging config"); 22 let atom_id = statsd_logging_config 23 .atom_id 24 .ok_or(anyhow!("atom_id required if statsd_logging_config provided"))?; 25 26 debug!("attempting to write atom id: {}", atom_id); 27 let mut event = AStatsEvent::new(atom_id.try_into()?); 28 event.write_int32(self.event.try_into()?); 29 event.write_int64(self.timestampNs.try_into()?); 30 event.write(); 31 debug!("successfully wrote atom id: {}", atom_id); 32 Ok(()) 33 } 34 } 35 36 // SAFETY: `CallResult` is a struct defined in the given `MAP_PATH`, and is guaranteed to match the 37 // layout of the corresponding C struct. 38 unsafe impl OnItem for CallResult { 39 const MAP_PATH: &'static str = 40 "/sys/fs/bpf/uprobestats/map_GenericInstrumentation_call_detail_buf"; on_item(&self, task: &Task) -> Result<()>41 fn on_item(&self, task: &Task) -> Result<()> { 42 debug!("CallResult - register: pc = {}", self.pc,); 43 for i in 0..10 { 44 debug!("CallResult - register: {} = {}", i, self.regs[i],); 45 } 46 47 let MessageField(Some(ref statsd_logging_config)) = task.statsd_logging_config else { 48 return Ok(()); 49 }; 50 51 debug!("has logging config"); 52 let atom_id = statsd_logging_config 53 .atom_id 54 .ok_or(anyhow!("atom_id required if statsd_logging_config provided"))?; 55 56 debug!("attempting to write atom id: {}", atom_id); 57 let mut event = AStatsEvent::new(atom_id.try_into()?); 58 59 for primitive_argument_position in &statsd_logging_config.primitive_argument_positions { 60 let register_index: usize = 61 (JAVA_ARGUMENT_REGISTER_OFFSET + primitive_argument_position).try_into()?; 62 let primitive_argument: i32 = self.regs[register_index].try_into()?; 63 debug!( 64 "writing primitive_argument: {} from position: {}", 65 primitive_argument, primitive_argument_position 66 ); 67 event.write_int32(primitive_argument); 68 } 69 70 event.write(); 71 debug!("successfully wrote atom id: {}", atom_id); 72 73 Ok(()) 74 } 75 } 76