Skip to main content

moire_types/
api.rs

1use crate::{ConnectionId, CutId, ProcessId, SessionId};
2use facet::Facet;
3use moire_trace_types::{BacktraceId, FrameId, RelPc};
4
5/// API response for connected processes.
6#[derive(Facet)]
7pub struct ConnectionsResponse {
8    pub connected_processes: usize,
9    pub processes: Vec<ConnectedProcessInfo>,
10}
11
12#[derive(Facet)]
13pub struct ConnectedProcessInfo {
14    pub conn_id: ConnectionId,
15    pub process_id: ProcessId,
16    pub process_name: String,
17    pub pid: u32,
18}
19
20#[derive(Facet)]
21pub struct TriggerCutResponse {
22    pub cut_id: CutId,
23    pub requested_at_ns: i64,
24    pub requested_connections: usize,
25}
26
27#[derive(Facet)]
28pub struct CutStatusResponse {
29    pub cut_id: CutId,
30    pub requested_at_ns: i64,
31    pub pending_connections: usize,
32    pub acked_connections: usize,
33    pub pending_conn_ids: Vec<ConnectionId>,
34}
35
36#[derive(Facet)]
37pub struct ApiError {
38    pub error: String,
39}
40
41#[derive(Facet)]
42pub struct SqlRequest {
43    pub sql: String,
44}
45
46#[derive(Facet)]
47pub struct QueryRequest {
48    pub name: String,
49    #[facet(skip_unless_truthy)]
50    pub limit: Option<u32>,
51}
52
53#[derive(Facet)]
54pub struct SqlResponse {
55    pub columns: Vec<String>,
56    pub rows: Vec<facet_value::Value>,
57    pub row_count: u32,
58}
59
60/// Top-level response for `/api/snapshot`.
61#[derive(Facet)]
62pub struct SnapshotCutResponse {
63    /// Monotonic server-side snapshot id for correlating stream updates.
64    pub snapshot_id: i64,
65    /// Wall-clock milliseconds (Unix epoch) when this cut was assembled server-side.
66    pub captured_at_unix_ms: i64,
67    /// Processes that replied within the timeout window.
68    pub processes: Vec<ProcessSnapshotView>,
69    /// Processes connected at request time but timed out before response.
70    pub timed_out_processes: Vec<TimedOutProcess>,
71    /// Backtraces referenced by entities/scopes/edges/events in this snapshot.
72    pub backtraces: Vec<SnapshotBacktrace>,
73    /// Deduplicated frame catalog keyed by frame_id.
74    pub frames: Vec<SnapshotFrameRecord>,
75}
76
77#[derive(Facet, Clone, Debug)]
78pub struct SnapshotBacktrace {
79    pub backtrace_id: BacktraceId,
80    pub frame_ids: Vec<FrameId>,
81}
82
83#[derive(Facet, Clone, Debug)]
84pub struct SnapshotFrameRecord {
85    pub frame_id: FrameId,
86    pub frame: SnapshotBacktraceFrame,
87}
88
89#[derive(Facet, Clone, Debug, PartialEq, Eq)]
90#[repr(u8)]
91#[facet(rename_all = "snake_case")]
92pub enum SnapshotBacktraceFrame {
93    Resolved(BacktraceFrameResolved),
94    Unresolved(BacktraceFrameUnresolved),
95}
96
97#[derive(Facet, Clone, Debug, PartialEq, Eq)]
98pub struct BacktraceFrameResolved {
99    pub module_path: String,
100    pub function_name: String,
101    pub source_file: String,
102    pub line: Option<u32>,
103}
104
105#[derive(Facet, Clone, Debug, PartialEq, Eq)]
106pub struct BacktraceFrameUnresolved {
107    pub module_path: String,
108    pub rel_pc: RelPc,
109    pub reason: String,
110}
111
112#[derive(Facet, Clone, Debug)]
113pub struct SnapshotSymbolicationUpdate {
114    pub snapshot_id: i64,
115    pub total_frames: u32,
116    pub completed_frames: u32,
117    pub done: bool,
118    pub updated_frames: Vec<SnapshotFrameRecord>,
119}
120
121/// Per-process envelope inside a snapshot cut.
122#[derive(Facet)]
123pub struct ProcessSnapshotView {
124    pub process_id: ProcessId,
125    pub process_name: String,
126    pub pid: u32,
127    pub ptime_now_ms: u64,
128    pub snapshot: crate::Snapshot,
129    #[facet(default)]
130    pub scope_entity_links: Vec<ScopeEntityLink>,
131}
132
133#[derive(Facet)]
134pub struct ScopeEntityLink {
135    pub scope_id: String,
136    pub entity_id: String,
137}
138
139#[derive(Facet)]
140pub struct TimedOutProcess {
141    pub process_id: ProcessId,
142    pub process_name: String,
143    pub pid: u32,
144}
145
146#[derive(Facet)]
147pub struct RecordStartRequest {
148    pub interval_ms: Option<u32>,
149    pub max_frames: Option<u32>,
150    pub max_memory_bytes: Option<u64>,
151}
152
153#[derive(Facet)]
154pub struct RecordCurrentResponse {
155    pub session: Option<RecordingSessionInfo>,
156}
157
158#[derive(Facet)]
159pub struct RecordingSessionInfo {
160    pub session_id: SessionId,
161    pub status: RecordingSessionStatus,
162    pub interval_ms: u32,
163    pub started_at_unix_ms: i64,
164    pub stopped_at_unix_ms: Option<i64>,
165    pub frame_count: u32,
166    pub max_frames: u32,
167    pub max_memory_bytes: u64,
168    pub overflowed: bool,
169    pub approx_memory_bytes: u64,
170    pub avg_capture_ms: f64,
171    pub max_capture_ms: f64,
172    pub total_capture_ms: f64,
173    pub frames: Vec<FrameSummary>,
174}
175
176#[derive(Facet, Clone, Copy, Debug, PartialEq, Eq)]
177#[repr(u8)]
178#[facet(rename_all = "snake_case")]
179pub enum RecordingSessionStatus {
180    Recording,
181    Stopped,
182}
183
184#[derive(Facet)]
185pub struct FrameSummary {
186    pub frame_index: u32,
187    pub captured_at_unix_ms: i64,
188    pub process_count: u32,
189    pub capture_duration_ms: f64,
190}
191
192#[derive(Facet)]
193pub struct RecordingImportFrame {
194    pub frame_index: u32,
195    pub snapshot: facet_value::Value,
196}
197
198/// A single entry in a syntax-highlighted source context excerpt.
199#[derive(Facet, Clone, Debug)]
200#[repr(u8)]
201#[facet(rename_all = "snake_case")]
202pub enum SourceContextLine {
203    /// A real source line with its original line number and highlighted HTML.
204    Line(ContextCodeLine),
205    /// A ⋯ separator representing one or more elided lines.
206    Separator(ContextSeparator),
207}
208
209#[derive(Facet, Clone, Debug)]
210pub struct ContextCodeLine {
211    pub line_num: u32,
212    pub html: String,
213}
214
215#[derive(Facet, Clone, Debug)]
216pub struct ContextSeparator {
217    pub indent_cols: u32,
218}
219
220/// Response for `GET /api/source/preview`.
221// r[impl api.source.preview]
222#[derive(Facet)]
223pub struct SourcePreviewResponse {
224    pub frame_id: FrameId,
225    pub source_file: String,
226    pub target_line: u32,
227    #[facet(skip_unless_truthy)]
228    pub target_col: Option<u32>,
229    pub total_lines: u32,
230    /// Full arborium-highlighted HTML for the entire file.
231    /// The frontend splits this into per-line strings using splitHighlightedHtml.
232    pub html: String,
233    /// Highlighted, collapsed context lines for the cut scope excerpt.
234    /// Separators replace elided regions; line numbers are original file line numbers.
235    #[facet(skip_unless_truthy)]
236    pub context_lines: Option<Vec<SourceContextLine>>,
237    /// Highlighted, collapsed context lines for the aggressively cut scope excerpt.
238    /// Intended for compact/collapsed displays.
239    #[facet(skip_unless_truthy)]
240    pub compact_context_lines: Option<Vec<SourceContextLine>>,
241    /// Highlighted HTML for a compact target-statement snippet.
242    ///
243    /// Preserves statement structure (may include newlines) and aggressively
244    /// elides long inner block bodies with a placeholder.
245    /// Used for compact collapsed-frame display.
246    #[facet(skip_unless_truthy)]
247    pub context_line: Option<String>,
248    /// Highlighted HTML for the frame header — the label identifying which
249    /// function or method this frame belongs to.
250    ///
251    /// Format: `fn name(params...)` for free functions,
252    /// `Type::fn name(params...)` for impl methods (module path included when present).
253    /// Visibility modifiers are omitted. Currently only populated for Rust.
254    #[facet(skip_unless_truthy)]
255    pub frame_header: Option<String>,
256}
257
258/// Request body for `POST /api/source/previews`.
259#[derive(Facet)]
260pub struct SourcePreviewBatchRequest {
261    pub frame_ids: Vec<FrameId>,
262}
263
264/// Response for `POST /api/source/previews`.
265#[derive(Facet)]
266pub struct SourcePreviewBatchResponse {
267    pub previews: Vec<SourcePreviewResponse>,
268    pub unavailable_frame_ids: Vec<FrameId>,
269}
270
271/// A 1-based inclusive line range within a source file.
272#[derive(Facet, Debug)]
273pub struct LineRange {
274    pub start: u32,
275    pub end: u32,
276}
277
278#[derive(Facet)]
279pub struct RecordingImportBody {
280    pub version: u32,
281    pub session: RecordingSessionInfo,
282    pub frames: Vec<RecordingImportFrame>,
283}