1use client::telemetry;
2use gpui::Task;
3use human_bytes::human_bytes;
4use release_channel::{AppCommitSha, AppVersion, ReleaseChannel};
5use serde::Serialize;
6use std::{env, fmt::Display};
7use sysinfo::{MemoryRefreshKind, RefreshKind, System};
8use ui::WindowContext;
9
10#[derive(Clone, Debug, Serialize)]
11pub struct SystemSpecs {
12 app_version: String,
13 release_channel: &'static str,
14 os_name: String,
15 os_version: String,
16 memory: u64,
17 architecture: &'static str,
18 commit_sha: Option<String>,
19 gpu_specs: Option<String>,
20}
21
22impl SystemSpecs {
23 pub fn new(cx: &WindowContext) -> Task<Self> {
24 let app_version = AppVersion::global(cx).to_string();
25 let release_channel = ReleaseChannel::global(cx);
26 let os_name = telemetry::os_name();
27 let system = System::new_with_specifics(
28 RefreshKind::new().with_memory(MemoryRefreshKind::everything()),
29 );
30 let memory = system.total_memory();
31 let architecture = env::consts::ARCH;
32 let commit_sha = match release_channel {
33 ReleaseChannel::Dev | ReleaseChannel::Nightly => {
34 AppCommitSha::try_global(cx).map(|sha| sha.0.clone())
35 }
36 _ => None,
37 };
38
39 let gpu_specs = if let Some(specs) = cx.gpu_specs() {
40 Some(format!(
41 "{} || {} || {}",
42 specs.device_name, specs.driver_name, specs.driver_info
43 ))
44 } else {
45 None
46 };
47
48 cx.background_executor().spawn(async move {
49 let os_version = telemetry::os_version();
50 SystemSpecs {
51 app_version,
52 release_channel: release_channel.display_name(),
53 os_name,
54 os_version,
55 memory,
56 architecture,
57 commit_sha,
58 gpu_specs,
59 }
60 })
61 }
62}
63
64impl Display for SystemSpecs {
65 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
66 let os_information = format!("OS: {} {}", self.os_name, self.os_version);
67 let app_version_information = format!(
68 "Zed: v{} ({})",
69 self.app_version,
70 match &self.commit_sha {
71 Some(commit_sha) => format!("{} {}", self.release_channel, commit_sha),
72 None => self.release_channel.to_string(),
73 }
74 );
75 let system_specs = [
76 app_version_information,
77 os_information,
78 format!("Memory: {}", human_bytes(self.memory as f64)),
79 format!("Architecture: {}", self.architecture),
80 ]
81 .into_iter()
82 .chain(
83 self.gpu_specs
84 .as_ref()
85 .map(|specs| format!("GPU: {}", specs)),
86 )
87 .collect::<Vec<String>>()
88 .join("\n");
89
90 write!(f, "{system_specs}")
91 }
92}