1#![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;
12use 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 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 Ok(core_dump_info)
51 }
52}
53
54#[derive(Debug, Clone, Deserialize, Serialize, PartialEq, ts_rs::TS)]
57#[ts(export)]
58#[serde(rename_all = "snake_case")]
59pub struct CoreDumpInfo {
60 pub id: Uuid,
62 pub version: String,
64 pub git_rev: String,
66 #[ts(type = "string")]
68 pub timestamp: chrono::DateTime<chrono::Utc>,
69 pub desktop: bool,
71 pub os: OsInfo,
73 pub webrtc_stats: WebrtcStats,
75 pub kcl_code: String,
77 pub client_state: JValue,
79}
80
81#[derive(Debug, Clone, Deserialize, Serialize, PartialEq, ts_rs::TS)]
83#[ts(export)]
84#[serde(rename_all = "snake_case")]
85pub struct OsInfo {
86 #[serde(skip_serializing_if = "Option::is_none")]
88 pub platform: Option<String>,
89 #[serde(skip_serializing_if = "Option::is_none")]
91 pub arch: Option<String>,
92 #[serde(skip_serializing_if = "Option::is_none")]
94 pub version: Option<String>,
95 #[serde(skip_serializing_if = "Option::is_none")]
97 pub browser: Option<String>,
98}
99
100#[derive(Default, Debug, Clone, Deserialize, Serialize, PartialEq, ts_rs::TS)]
102#[ts(export)]
103#[serde(rename_all = "snake_case")]
104pub struct WebrtcStats {
105 #[serde(default, skip_serializing_if = "Option::is_none")]
107 pub packets_lost: Option<u32>,
108 #[serde(default, skip_serializing_if = "Option::is_none")]
110 pub frames_received: Option<u32>,
111 #[serde(default, skip_serializing_if = "Option::is_none")]
113 pub frame_width: Option<f32>,
114 #[serde(default, skip_serializing_if = "Option::is_none")]
116 pub frame_height: Option<f32>,
117 #[serde(default, skip_serializing_if = "Option::is_none")]
119 pub frame_rate: Option<f32>,
120 #[serde(default, skip_serializing_if = "Option::is_none")]
122 pub key_frames_decoded: Option<u32>,
123 #[serde(default, skip_serializing_if = "Option::is_none")]
125 pub frames_dropped: Option<u32>,
126 #[serde(default, skip_serializing_if = "Option::is_none")]
128 pub pause_count: Option<u32>,
129 #[serde(default, skip_serializing_if = "Option::is_none")]
131 pub total_pauses_duration: Option<f32>,
132 #[serde(default, skip_serializing_if = "Option::is_none")]
134 pub freeze_count: Option<u32>,
135 #[serde(default, skip_serializing_if = "Option::is_none")]
137 pub total_freezes_duration: Option<f32>,
138 #[serde(default, skip_serializing_if = "Option::is_none")]
140 pub pli_count: Option<u32>,
141 #[serde(default, skip_serializing_if = "Option::is_none")]
143 pub jitter: Option<f32>,
144}