1use client::ZED_APP_VERSION;
2use gpui::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 app_version: Option<String>,
12 release_channel: &'static str,
13 os_name: &'static str,
14 os_version: Option<String>,
15 memory: u64,
16 architecture: &'static str,
17}
18
19impl SystemSpecs {
20 pub fn new(cx: &AppContext) -> Self {
21 let app_version = ZED_APP_VERSION
22 .or_else(|| cx.app_metadata().app_version)
23 .map(|v| v.to_string());
24 let release_channel = cx.global::<ReleaseChannel>().display_name();
25 let os_name = cx.app_metadata().os_name;
26 let system = System::new_all();
27 let memory = system.total_memory();
28 let architecture = env::consts::ARCH;
29 let os_version = cx
30 .app_metadata()
31 .os_version
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}