• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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