1use client::ZED_APP_VERSION;
2use gpui::{platform::AppVersion, AppContext};
3use human_bytes::human_bytes;
4use serde::Serialize;
5use std::{env, fmt::Display};
6use sysinfo::{System, SystemExt};
7use util::channel::ReleaseChannel;
8
9#[derive(Clone, Debug, Serialize)]
10pub struct SystemSpecs {
11 #[serde(serialize_with = "serialize_app_version")]
12 app_version: Option<AppVersion>,
13 release_channel: &'static str,
14 os_name: &'static str,
15 os_version: Option<String>,
16 memory: u64,
17 architecture: &'static str,
18}
19
20impl SystemSpecs {
21 pub fn new(cx: &AppContext) -> Self {
22 let platform = cx.platform();
23 let app_version = ZED_APP_VERSION.or_else(|| platform.app_version().ok());
24 let release_channel = cx.global::<ReleaseChannel>().dev_name();
25 let os_name = platform.os_name();
26 let system = System::new_all();
27 let memory = system.total_memory();
28 let architecture = env::consts::ARCH;
29 let os_version = platform
30 .os_version()
31 .ok()
32 .map(|os_version| os_version.to_string());
33
34 SystemSpecs {
35 app_version,
36 release_channel,
37 os_name,
38 os_version,
39 memory,
40 architecture,
41 }
42 }
43}
44
45impl Display for SystemSpecs {
46 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
47 let os_information = match &self.os_version {
48 Some(os_version) => format!("OS: {} {}", self.os_name, os_version),
49 None => format!("OS: {}", self.os_name),
50 };
51 let app_version_information = self
52 .app_version
53 .as_ref()
54 .map(|app_version| format!("Zed: v{} ({})", app_version, self.release_channel));
55 let system_specs = [
56 app_version_information,
57 Some(os_information),
58 Some(format!("Memory: {}", human_bytes(self.memory as f64))),
59 Some(format!("Architecture: {}", self.architecture)),
60 ]
61 .into_iter()
62 .flatten()
63 .collect::<Vec<String>>()
64 .join("\n");
65
66 write!(f, "{system_specs}")
67 }
68}
69
70fn serialize_app_version<S>(version: &Option<AppVersion>, serializer: S) -> Result<S::Ok, S::Error>
71where
72 S: serde::Serializer,
73{
74 version.map(|v| v.to_string()).serialize(serializer)
75}