1use gpui::AppContext;
2use human_bytes::human_bytes;
3use release_channel::{AppVersion, ReleaseChannel};
4use serde::Serialize;
5use std::{env, fmt::Display};
6use sysinfo::{RefreshKind, System, SystemExt};
7
8#[derive(Clone, Debug, Serialize)]
9pub struct SystemSpecs {
10 app_version: String,
11 release_channel: &'static str,
12 os_name: &'static str,
13 os_version: Option<String>,
14 memory: u64,
15 architecture: &'static str,
16}
17
18impl SystemSpecs {
19 pub fn new(cx: &AppContext) -> Self {
20 let app_version = AppVersion::global(cx).to_string();
21 let release_channel = ReleaseChannel::global(cx).display_name();
22 let os_name = cx.app_metadata().os_name;
23 let system = System::new_with_specifics(RefreshKind::new().with_memory());
24 let memory = system.total_memory();
25 let architecture = env::consts::ARCH;
26 let os_version = cx
27 .app_metadata()
28 .os_version
29 .map(|os_version| os_version.to_string());
30
31 SystemSpecs {
32 app_version,
33 release_channel,
34 os_name,
35 os_version,
36 memory,
37 architecture,
38 }
39 }
40}
41
42impl Display for SystemSpecs {
43 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
44 let os_information = match &self.os_version {
45 Some(os_version) => format!("OS: {} {}", self.os_name, os_version),
46 None => format!("OS: {}", self.os_name),
47 };
48 let app_version_information =
49 format!("Zed: v{} ({})", self.app_version, self.release_channel);
50 let system_specs = [
51 app_version_information,
52 os_information,
53 format!("Memory: {}", human_bytes(self.memory as f64)),
54 format!("Architecture: {}", self.architecture),
55 ]
56 .into_iter()
57 .collect::<Vec<String>>()
58 .join("\n");
59
60 write!(f, "{system_specs}")
61 }
62}