Skip to main content

kcl_lib/coredump/
mod.rs

1//! Core dump related structures and functions.
2#![allow(dead_code)]
3
4#[cfg(not(target_arch = "wasm32"))]
5pub mod local;
6#[cfg(target_arch = "wasm32")]
7pub mod wasm;
8
9use anyhow::Result;
10use serde::Deserialize;
11use serde::Serialize;
12/// "Value" would be OK. This is imported as "JValue" throughout the rest of this crate.
13use serde_json::Value as JValue;
14use uuid::Uuid;
15
16#[async_trait::async_trait(?Send)]
17pub trait CoreDump: Clone {
18    fn version(&self) -> Result<String>;
19
20    fn kcl_code(&self) -> Result<String>;
21
22    fn os(&self) -> Result<OsInfo>;
23
24    fn is_desktop(&self) -> Result<bool>;
25
26    async fn get_webrtc_stats(&self) -> Result<WebrtcStats>;
27
28    async fn get_client_state(&self) -> Result<JValue>;
29
30    /// Dump the app info.
31    async fn dump(&self) -> Result<CoreDumpInfo> {
32        let coredump_id = uuid::Uuid::new_v4();
33        let client_state = self.get_client_state().await?;
34        let webrtc_stats = self.get_webrtc_stats().await?;
35        let os = self.os()?;
36
37        let core_dump_info = CoreDumpInfo {
38            id: coredump_id,
39            version: self.version()?,
40            git_rev: git_rev::try_revision_string!().map_or_else(|| "unknown".to_string(), |s| s.to_string()),
41            timestamp: chrono::Utc::now(),
42            desktop: self.is_desktop()?,
43            kcl_code: self.kcl_code()?,
44            os,
45            webrtc_stats,
46            client_state,
47        };
48
49        // pretty-printed JSON byte vector of the coredump.
50        Ok(core_dump_info)
51    }
52}
53
54/// The app info structure.
55/// The Core Dump Info structure.
56#[derive(Debug, Clone, Deserialize, Serialize, PartialEq, ts_rs::TS)]
57#[ts(export)]
58#[serde(rename_all = "snake_case")]
59pub struct CoreDumpInfo {
60    /// The unique id for the core dump - this helps correlate uploaded files with coredump data.
61    pub id: Uuid,
62    /// The version of the app.
63    pub version: String,
64    /// The git revision of the app.
65    pub git_rev: String,
66    /// A timestamp of the core dump.
67    #[ts(type = "string")]
68    pub timestamp: chrono::DateTime<chrono::Utc>,
69    /// If the app is running in desktop or the browser.
70    pub desktop: bool,
71    /// The os info.
72    pub os: OsInfo,
73    /// The webrtc stats.
74    pub webrtc_stats: WebrtcStats,
75    /// The kcl code the user is using.
76    pub kcl_code: String,
77    /// The client state (singletons and xstate).
78    pub client_state: JValue,
79}
80
81/// The os info structure.
82#[derive(Debug, Clone, Deserialize, Serialize, PartialEq, ts_rs::TS)]
83#[ts(export)]
84#[serde(rename_all = "snake_case")]
85pub struct OsInfo {
86    /// The platform the app is running on.
87    #[serde(skip_serializing_if = "Option::is_none")]
88    pub platform: Option<String>,
89    /// The architecture the app is running on.
90    #[serde(skip_serializing_if = "Option::is_none")]
91    pub arch: Option<String>,
92    /// The kernel version.
93    #[serde(skip_serializing_if = "Option::is_none")]
94    pub version: Option<String>,
95    /// Information about the browser.
96    #[serde(skip_serializing_if = "Option::is_none")]
97    pub browser: Option<String>,
98}
99
100/// The webrtc stats structure.
101#[derive(Default, Debug, Clone, Deserialize, Serialize, PartialEq, ts_rs::TS)]
102#[ts(export)]
103#[serde(rename_all = "snake_case")]
104pub struct WebrtcStats {
105    /// The packets lost.
106    #[serde(default, skip_serializing_if = "Option::is_none")]
107    pub packets_lost: Option<u32>,
108    /// The frames received.
109    #[serde(default, skip_serializing_if = "Option::is_none")]
110    pub frames_received: Option<u32>,
111    /// The frame width.
112    #[serde(default, skip_serializing_if = "Option::is_none")]
113    pub frame_width: Option<f32>,
114    /// The frame height.
115    #[serde(default, skip_serializing_if = "Option::is_none")]
116    pub frame_height: Option<f32>,
117    /// The frame rate.
118    #[serde(default, skip_serializing_if = "Option::is_none")]
119    pub frame_rate: Option<f32>,
120    /// The number of key frames decoded.
121    #[serde(default, skip_serializing_if = "Option::is_none")]
122    pub key_frames_decoded: Option<u32>,
123    /// The number of frames dropped.
124    #[serde(default, skip_serializing_if = "Option::is_none")]
125    pub frames_dropped: Option<u32>,
126    /// The pause count.
127    #[serde(default, skip_serializing_if = "Option::is_none")]
128    pub pause_count: Option<u32>,
129    /// The total pauses duration.
130    #[serde(default, skip_serializing_if = "Option::is_none")]
131    pub total_pauses_duration: Option<f32>,
132    /// The freeze count.
133    #[serde(default, skip_serializing_if = "Option::is_none")]
134    pub freeze_count: Option<u32>,
135    /// The total freezes duration.
136    #[serde(default, skip_serializing_if = "Option::is_none")]
137    pub total_freezes_duration: Option<f32>,
138    /// The pli count.
139    #[serde(default, skip_serializing_if = "Option::is_none")]
140    pub pli_count: Option<u32>,
141    /// Packet jitter for this synchronizing source, measured in seconds.
142    #[serde(default, skip_serializing_if = "Option::is_none")]
143    pub jitter: Option<f32>,
144}