1#![cfg_attr(not(feature = "std"), no_std)]
2
3#[repr(u8)]
5#[derive(Clone, Copy, Debug, PartialEq, Eq)]
6pub enum EventType {
7 SchedSwitch = 0,
8 ProcessFork = 1,
9 ProcessExit = 2,
10 PageFault = 3,
11 SyscallReadEnter = 4,
12 SyscallReadExit = 5,
13 SyscallWriteEnter = 6,
14 SyscallWriteExit = 7,
15 SyscallMmapEnter = 8,
16 SyscallMmapExit = 9,
17 SyscallMunmapEnter = 10,
18 SyscallMunmapExit = 11,
19 SyscallBrkEnter = 12,
20 SyscallBrkExit = 13,
21 SyscallIoUringSetupEnter = 14,
22 SyscallIoUringSetupExit = 15,
23 SyscallIoUringEnterEnter = 16,
24 SyscallIoUringEnterExit = 17,
25 SyscallIoUringRegisterEnter = 18,
26 SyscallIoUringRegisterExit = 19,
27 CpuSample = 20,
28}
29
30impl TryFrom<u8> for EventType {
31 type Error = u8;
32
33 fn try_from(value: u8) -> Result<Self, Self::Error> {
34 match value {
35 0 => Ok(EventType::SchedSwitch),
36 1 => Ok(EventType::ProcessFork),
37 2 => Ok(EventType::ProcessExit),
38 3 => Ok(EventType::PageFault),
39 4 => Ok(EventType::SyscallReadEnter),
40 5 => Ok(EventType::SyscallReadExit),
41 6 => Ok(EventType::SyscallWriteEnter),
42 7 => Ok(EventType::SyscallWriteExit),
43 8 => Ok(EventType::SyscallMmapEnter),
44 9 => Ok(EventType::SyscallMmapExit),
45 10 => Ok(EventType::SyscallMunmapEnter),
46 11 => Ok(EventType::SyscallMunmapExit),
47 12 => Ok(EventType::SyscallBrkEnter),
48 13 => Ok(EventType::SyscallBrkExit),
49 14 => Ok(EventType::SyscallIoUringSetupEnter),
50 15 => Ok(EventType::SyscallIoUringSetupExit),
51 16 => Ok(EventType::SyscallIoUringEnterEnter),
52 17 => Ok(EventType::SyscallIoUringEnterExit),
53 18 => Ok(EventType::SyscallIoUringRegisterEnter),
54 19 => Ok(EventType::SyscallIoUringRegisterExit),
55 20 => Ok(EventType::CpuSample),
56 v => Err(v),
57 }
58 }
59}
60
61#[repr(C)]
63#[derive(Clone, Copy, Debug)]
64pub struct EventHeader {
65 pub timestamp_ns: u64,
66 pub pid: u32,
67 pub tgid: u32,
68 pub stack_id: i32,
70 pub kernel_stack_id: i32,
72 pub stack_kind: u8,
73 pub event_type: u8,
74 pub cpu: u8,
75 pub _padding: [u8; 5],
76}
77
78pub const STACK_KIND_NONE: u8 = 0;
79pub const STACK_KIND_USER: u8 = 1;
80pub const STACK_KIND_KERNEL: u8 = 2;
81pub const STACK_KIND_BOTH: u8 = STACK_KIND_USER | STACK_KIND_KERNEL;
82
83pub const MAX_CPU_SAMPLE_FRAMES: usize = 127;
85
86pub const CPU_SAMPLE_STATS_LEN: usize = 7;
88pub const CPU_SAMPLE_STAT_CALLBACK_TOTAL: usize = 0;
89pub const CPU_SAMPLE_STAT_FILTERED_NOT_TRACED: usize = 1;
90pub const CPU_SAMPLE_STAT_EMITTED: usize = 2;
91pub const CPU_SAMPLE_STAT_RINGBUF_DROPPED: usize = 3;
92pub const CPU_SAMPLE_STAT_USER_STACK: usize = 4;
93pub const CPU_SAMPLE_STAT_KERNEL_STACK: usize = 5;
94pub const CPU_SAMPLE_STAT_NO_STACK: usize = 6;
95
96#[repr(C)]
98#[derive(Clone, Copy, Debug)]
99pub struct CpuSampleEvent {
100 pub header: EventHeader,
101 pub frame_count: u16,
102 pub _padding: [u8; 6],
103 pub frames: [u64; MAX_CPU_SAMPLE_FRAMES],
104}
105
106#[repr(C)]
108#[derive(Clone, Copy, Debug)]
109pub struct SchedSwitchEvent {
110 pub header: EventHeader,
111 pub prev_pid: u32,
112 pub prev_tgid: u32,
113 pub next_pid: u32,
114 pub next_tgid: u32,
115 pub prev_state: i64,
116}
117
118#[repr(C)]
120#[derive(Clone, Copy, Debug)]
121pub struct ProcessForkEvent {
122 pub header: EventHeader,
123 pub parent_pid: u32,
124 pub child_pid: u32,
125}
126
127#[repr(C)]
129#[derive(Clone, Copy, Debug)]
130pub struct ProcessExitEvent {
131 pub header: EventHeader,
132 pub exit_code: i32,
133 pub _padding: u32,
134}
135
136#[repr(C)]
138#[derive(Clone, Copy, Debug)]
139pub struct PageFaultEvent {
140 pub header: EventHeader,
141 pub address: u64,
142 pub error_code: u64,
143}
144
145#[repr(C)]
147#[derive(Clone, Copy, Debug)]
148pub struct SyscallEnterEvent {
149 pub header: EventHeader,
150 pub fd: i64,
151 pub count: u64,
152}
153
154#[repr(C)]
156#[derive(Clone, Copy, Debug)]
157pub struct SyscallExitEvent {
158 pub header: EventHeader,
159 pub ret: i64,
160}
161
162pub const SCHED_SWITCH_EVENT_SIZE: usize = core::mem::size_of::<SchedSwitchEvent>();
164pub const PROCESS_FORK_EVENT_SIZE: usize = core::mem::size_of::<ProcessForkEvent>();
165pub const PROCESS_EXIT_EVENT_SIZE: usize = core::mem::size_of::<ProcessExitEvent>();
166pub const PAGE_FAULT_EVENT_SIZE: usize = core::mem::size_of::<PageFaultEvent>();
167pub const SYSCALL_ENTER_EVENT_SIZE: usize = core::mem::size_of::<SyscallEnterEvent>();
168pub const SYSCALL_EXIT_EVENT_SIZE: usize = core::mem::size_of::<SyscallExitEvent>();
169pub const CPU_SAMPLE_EVENT_SIZE: usize = core::mem::size_of::<CpuSampleEvent>();
170
171pub const RING_BUF_SIZE: u32 = 64 * 1024 * 1024;
173
174pub const MAX_TRACKED_PIDS: u32 = 8192;
176
177#[cfg(feature = "viewer-api")]
178pub mod viewer_api {
179 use serde::{Deserialize, Serialize};
180 use std::collections::HashMap;
181
182 #[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
183 pub struct HistogramBucket {
184 pub bucket_start_ns: u64,
185 pub bucket_end_ns: u64,
186 pub count: usize,
187 pub counts_by_type: HashMap<String, usize>,
188 }
189
190 #[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
191 pub struct HistogramResponse {
192 pub buckets: Vec<HistogramBucket>,
193 pub total_in_range: usize,
194 }
195
196 #[derive(Debug, Clone, Serialize, Deserialize, Default, PartialEq)]
197 pub struct EventTypeCounts {
198 pub counts: HashMap<String, usize>,
199 }
200
201 #[derive(Debug, Clone, Serialize, Deserialize, Default, PartialEq)]
202 pub struct LatencySummary {
203 pub count: usize,
204 pub avg_ns: u64,
205 pub p50_ns: u64,
206 pub p95_ns: u64,
207 pub max_ns: u64,
208 }
209
210 #[derive(Debug, Clone, Serialize, Deserialize, Default, PartialEq)]
211 pub struct SyscallLatencyStats {
212 pub read: LatencySummary,
213 pub write: LatencySummary,
214 pub mmap_alloc_bytes: u64,
215 pub munmap_free_bytes: u64,
216 }
217
218 #[derive(Debug, Clone, Serialize, Deserialize, Default, PartialEq)]
219 pub struct TraceSummary {
220 pub total_events: usize,
221 pub event_types: Vec<String>,
222 pub unique_pids: Vec<u32>,
223 pub min_ts_ns: u64,
224 pub max_ts_ns: u64,
225 pub cpu_sample_frequency_hz: u64,
226 }
227
228 #[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
229 pub struct ProcessLifetime {
230 pub pid: u32,
231 pub process_name: Option<String>,
232 pub parent_pid: Option<u32>,
233 pub start_ns: u64,
234 pub end_ns: Option<u64>,
235 pub exit_code: Option<i32>,
236 pub was_forked: bool,
237 pub did_exit: bool,
238 }
239
240 #[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
241 pub struct ProcessLifetimesResponse {
242 pub processes: Vec<ProcessLifetime>,
243 }
244
245 #[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
246 pub struct EventMarker {
247 pub ts_ns: u64,
248 pub event_type: String,
249 }
250
251 #[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
252 pub struct ProcessEventsResponse {
253 pub events_by_pid: HashMap<u32, Vec<EventMarker>>,
254 pub cpu_sample_counts_by_pid: HashMap<u32, Vec<u16>>,
255 pub cpu_sample_bucket_count: usize,
256 }
257
258 #[derive(Debug, Clone, Serialize, Deserialize, Default, PartialEq)]
259 pub struct EventFlamegraphResponse {
260 pub event_type: String,
261 pub total_samples: usize,
262 pub svg: Option<String>,
263 }
264}