perf_event_data/
visitor.rs

1use std::borrow::Cow;
2
3use perf_event_open_sys::bindings;
4
5use crate::parse::Parser;
6use crate::*;
7
8used_in_docs!(Parser);
9
10/// Extra record data emitted by the kernel that is common to all records.
11#[derive(Clone, Debug)]
12pub struct RecordMetadata {
13    ty: u32,
14    misc: u16,
15    sample_id: SampleId,
16}
17
18impl RecordMetadata {
19    #[inline]
20    pub(crate) fn new(header: bindings::perf_event_header, sample_id: SampleId) -> Self {
21        Self {
22            ty: header.type_,
23            misc: header.misc,
24            sample_id,
25        }
26    }
27
28    /// The type of this record, as emitted by the kernel.
29    #[inline]
30    pub fn ty(&self) -> u32 {
31        self.ty
32    }
33
34    /// Miscellaneous flags set by the kernel.
35    #[inline]
36    pub fn misc(&self) -> u16 {
37        self.misc
38    }
39
40    /// If `sample_id_all` was set when configuring the record then this will
41    /// contain a subset of the fields configured to be sampled.
42    ///
43    /// Note that, even if `sample_id_all` is set, MMAP and SAMPLE records will
44    /// always have an empty `SampleId`. If you want the `SampleId` fields
45    /// to be set then configure the kernel to generate MMAP2 records
46    /// instead.
47    #[inline]
48    pub fn sample_id(&self) -> &SampleId {
49        &self.sample_id
50    }
51}
52
53/// A visitor for visiting parsed records.
54///
55/// This is used in combination with [`Parser::parse_record`] to parse the
56/// record types that you are interested in.
57///
58/// # Implementing a Visitor
59/// To implement a visitor define your output type and implement
60/// `visit_unimplemented`, then, implement whichever `visit_*` method that is
61/// for the event you are interested in:
62///
63/// ```
64/// # use perf_event_data::{Visitor, RecordMetadata};
65/// struct MyVisitor;
66///
67/// impl Visitor<'_> for MyVisitor {
68///     type Output = ();
69///
70///     fn visit_unimplemented(self, metadata: RecordMetadata) -> Self::Output {
71///         println!("got a record with type {}", metadata.ty());
72///     }
73/// }
74/// ```
75#[allow(unused_variables)]
76pub trait Visitor<'a>: Sized {
77    /// The output type for this visitor.
78    type Output;
79
80    /// Called by the other `visit_*` methods if they are not implemented.
81    ///
82    /// When implementing a visitor this is this one method that it is required
83    /// to implement.
84    fn visit_unimplemented(self, metadata: RecordMetadata) -> Self::Output;
85
86    /// Visit a [`Mmap`] record.
87    ///
88    /// By default, [`visit_mmap2`](Visitor::visit_mmap2) forwards to this
89    /// method.
90    fn visit_mmap(self, record: Mmap<'a>, metadata: RecordMetadata) -> Self::Output {
91        self.visit_unimplemented(metadata)
92    }
93
94    /// Visit a [`Lost`] record.
95    fn visit_lost(self, record: Lost, metadata: RecordMetadata) -> Self::Output {
96        self.visit_unimplemented(metadata)
97    }
98
99    /// Visit a [`Comm`] record.
100    fn visit_comm(self, record: Comm<'a>, metadata: RecordMetadata) -> Self::Output {
101        self.visit_unimplemented(metadata)
102    }
103
104    /// Visit an [`Exit`] record.
105    fn visit_exit(self, record: Exit, metadata: RecordMetadata) -> Self::Output {
106        self.visit_unimplemented(metadata)
107    }
108
109    /// Visit a THROTTLE record.
110    fn visit_throttle(self, record: Throttle, metadata: RecordMetadata) -> Self::Output {
111        self.visit_unimplemented(metadata)
112    }
113
114    /// Visit an UNTHROTTLE record.
115    fn visit_unthrottle(self, record: Throttle, metadata: RecordMetadata) -> Self::Output {
116        self.visit_unimplemented(metadata)
117    }
118
119    /// Visit a [`Fork`] record.
120    fn visit_fork(self, record: Fork, metadata: RecordMetadata) -> Self::Output {
121        self.visit_unimplemented(metadata)
122    }
123
124    /// Visit a [`Read`] record.
125    fn visit_read(self, record: Read, metadata: RecordMetadata) -> Self::Output {
126        self.visit_unimplemented(metadata)
127    }
128
129    /// Visit a [`Sample`] record.
130    fn visit_sample(self, record: Sample<'a>, metadata: RecordMetadata) -> Self::Output {
131        self.visit_unimplemented(metadata)
132    }
133
134    /// Visit a [`Mmap2`] record.
135    ///
136    /// If not implemented, this forwards to
137    /// [`visit_mmap`](Visitor::visit_mmap).
138    fn visit_mmap2(self, record: Mmap2<'a>, metadata: RecordMetadata) -> Self::Output {
139        self.visit_mmap(record.into_mmap(), metadata)
140    }
141
142    /// Visit an [`Aux`] record.
143    fn visit_aux(self, record: Aux, metadata: RecordMetadata) -> Self::Output {
144        self.visit_unimplemented(metadata)
145    }
146
147    /// Visit an [`ITraceStart`] record.
148    fn visit_itrace_start(self, record: ITraceStart, metadata: RecordMetadata) -> Self::Output {
149        self.visit_unimplemented(metadata)
150    }
151
152    /// Visit a [`LostSamples`] record.
153    fn visit_lost_samples(self, record: LostSamples, metadata: RecordMetadata) -> Self::Output {
154        self.visit_unimplemented(metadata)
155    }
156
157    /// Visit a SWITCH record.
158    fn visit_switch(self, metadata: RecordMetadata) -> Self::Output {
159        self.visit_unimplemented(metadata)
160    }
161
162    /// Visit a [`SwitchCpuWide`] record.
163    fn visit_switch_cpu_wide(
164        self,
165        record: SwitchCpuWide,
166        metadata: RecordMetadata,
167    ) -> Self::Output {
168        self.visit_unimplemented(metadata)
169    }
170
171    /// Visit a [`Namespaces`] record.
172    fn visit_namespaces(self, record: Namespaces<'a>, metadata: RecordMetadata) -> Self::Output {
173        self.visit_unimplemented(metadata)
174    }
175
176    /// Visit a [`KSymbol`] record.
177    fn visit_ksymbol(self, record: KSymbol<'a>, metadata: RecordMetadata) -> Self::Output {
178        self.visit_unimplemented(metadata)
179    }
180
181    /// Visit a [`BpfEvent`] record.
182    fn visit_bpf_event(self, record: BpfEvent, metadata: RecordMetadata) -> Self::Output {
183        self.visit_unimplemented(metadata)
184    }
185
186    /// Visit a [`CGroup`] record.
187    fn visit_cgroup(self, record: CGroup<'a>, metadata: RecordMetadata) -> Self::Output {
188        self.visit_unimplemented(metadata)
189    }
190
191    /// Visit a [`TextPoke`] record.
192    fn visit_text_poke(self, record: TextPoke<'a>, metadata: RecordMetadata) -> Self::Output {
193        self.visit_unimplemented(metadata)
194    }
195
196    /// Visit a [`AuxOutputHwId`] record.
197    fn visit_aux_output_hw_id(
198        self,
199        record: AuxOutputHwId,
200        metadata: RecordMetadata,
201    ) -> Self::Output {
202        self.visit_unimplemented(metadata)
203    }
204
205    /// Visit a record not supported by this library.
206    ///
207    /// Note that support for new record types may be added in new minor
208    /// versions of `perf-event-data`. This visitor method is provided as a
209    /// backstop so that users can still choose to handle these should they need
210    /// it.
211    ///
212    /// If you find yourself using this for a record type emitted by
213    /// `perf_event_open` please create an issue or submit a PR to add the
214    /// record to `perf-event-data` itself.
215    fn visit_unknown(self, data: Cow<'a, [u8]>, metadata: RecordMetadata) -> Self::Output {
216        self.visit_unimplemented(metadata)
217    }
218}