1use gpui::AppContext;
2use human_bytes::human_bytes;
3use release_channel::{AppVersion, ReleaseChannel};
4use serde::Serialize;
5use std::{env, fmt::Display};
6use sysinfo::{MemoryRefreshKind, RefreshKind, System};
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(
24 RefreshKind::new().with_memory(MemoryRefreshKind::everything()),
25 );
26 let memory = system.total_memory();
27 let architecture = env::consts::ARCH;
28 let os_version = cx
29 .app_metadata()
30 .os_version
31 .map(|os_version| os_version.to_string());
32
33 SystemSpecs {
34 app_version,
35 release_channel,
36 os_name,
37 os_version,
38 memory,
39 architecture,
40 }
41 }
42}
43
44impl Display for SystemSpecs {
45 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
46 let os_information = match &self.os_version {
47 Some(os_version) => format!("OS: {} {}", self.os_name, os_version),
48 None => format!("OS: {}", self.os_name),
49 };
50 let app_version_information =
51 format!("Zed: v{} ({})", self.app_version, self.release_channel);
52 let system_specs = [
53 app_version_information,
54 os_information,
55 format!("Memory: {}", human_bytes(self.memory as f64)),
56 format!("Architecture: {}", self.architecture),
57 ]
58 .into_iter()
59 .collect::<Vec<String>>()
60 .join("\n");
61
62 write!(f, "{system_specs}")
63 }
64}