1/// Please see: [Telemetry in Zed](https://zed.dev/docs/telemetry) for additional documentation.
2use semantic_version::SemanticVersion;
3use serde::{Deserialize, Serialize};
4use std::{fmt::Display, sync::Arc, time::Duration};
5
6#[derive(Serialize, Deserialize, Debug)]
7pub struct EventRequestBody {
8 /// Identifier unique to each system Zed is installed on
9 pub system_id: Option<String>,
10 /// Identifier unique to each Zed installation (differs for stable, preview, dev)
11 pub installation_id: Option<String>,
12 /// Identifier unique to each logged in Zed user (randomly generated on first sign in)
13 /// Identifier unique to each Zed session (differs for each time you open Zed)
14 pub session_id: Option<String>,
15 pub metrics_id: Option<String>,
16 /// True for Zed staff, otherwise false
17 pub is_staff: Option<bool>,
18 /// Zed version number
19 pub app_version: String,
20 pub os_name: String,
21 pub os_version: Option<String>,
22 pub architecture: String,
23 /// Zed release channel (stable, preview, dev)
24 pub release_channel: Option<String>,
25 pub events: Vec<EventWrapper>,
26}
27
28impl EventRequestBody {
29 pub fn semver(&self) -> Option<SemanticVersion> {
30 self.app_version.parse().ok()
31 }
32}
33
34#[derive(Serialize, Deserialize, Debug)]
35pub struct EventWrapper {
36 pub signed_in: bool,
37 /// Duration between this event's timestamp and the timestamp of the first event in the current batch
38 pub milliseconds_since_first_event: i64,
39 /// The event itself
40 #[serde(flatten)]
41 pub event: Event,
42}
43
44#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
45#[serde(rename_all = "snake_case")]
46pub enum AssistantKind {
47 Panel,
48 Inline,
49}
50impl Display for AssistantKind {
51 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
52 write!(
53 f,
54 "{}",
55 match self {
56 Self::Panel => "panel",
57 Self::Inline => "inline",
58 }
59 )
60 }
61}
62
63#[derive(Default, Clone, Debug, PartialEq, Serialize, Deserialize)]
64#[serde(rename_all = "snake_case")]
65pub enum AssistantPhase {
66 #[default]
67 Response,
68 Invoked,
69 Accepted,
70 Rejected,
71}
72
73impl Display for AssistantPhase {
74 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
75 write!(
76 f,
77 "{}",
78 match self {
79 Self::Response => "response",
80 Self::Invoked => "invoked",
81 Self::Accepted => "accepted",
82 Self::Rejected => "rejected",
83 }
84 )
85 }
86}
87
88#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
89#[serde(tag = "type")]
90pub enum Event {
91 Editor(EditorEvent),
92 Copilot(CopilotEvent), // Needed for clients sending old copilot_event types
93 InlineCompletion(InlineCompletionEvent),
94 Call(CallEvent),
95 Assistant(AssistantEvent),
96 Cpu(CpuEvent),
97 Memory(MemoryEvent),
98 App(AppEvent),
99 Setting(SettingEvent),
100 Extension(ExtensionEvent),
101 Edit(EditEvent),
102 Action(ActionEvent),
103 Repl(ReplEvent),
104}
105
106#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
107pub struct EditorEvent {
108 /// The editor operation performed (open, save)
109 pub operation: String,
110 /// The extension of the file that was opened or saved
111 pub file_extension: Option<String>,
112 /// Whether the user is in vim mode or not
113 pub vim_mode: bool,
114 /// Whether the user has copilot enabled or not
115 pub copilot_enabled: bool,
116 /// Whether the user has copilot enabled for the language of the file opened or saved
117 pub copilot_enabled_for_language: bool,
118}
119
120/// Deprecated since Zed v0.137.0 (2024-05-29). Replaced by InlineCompletionEvent.
121// Needed for clients sending old copilot_event types
122#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
123pub struct CopilotEvent {
124 pub suggestion_id: Option<String>,
125 pub suggestion_accepted: bool,
126 pub file_extension: Option<String>,
127}
128
129#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
130pub struct InlineCompletionEvent {
131 /// Provider of the completion suggestion (e.g. copilot, supermaven)
132 pub provider: String,
133 pub suggestion_accepted: bool,
134 pub file_extension: Option<String>,
135}
136
137#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
138pub struct CallEvent {
139 /// Operation performed: invite/join call; begin/end screenshare; share/unshare project; etc
140 pub operation: String,
141 pub room_id: Option<u64>,
142 pub channel_id: Option<u64>,
143}
144
145#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
146pub struct AssistantEvent {
147 /// Unique random identifier for each assistant tab (None for inline assist)
148 pub conversation_id: Option<String>,
149 /// The kind of assistant (Panel, Inline)
150 pub kind: AssistantKind,
151 #[serde(default)]
152 pub phase: AssistantPhase,
153 /// Name of the AI model used (gpt-4o, claude-3-5-sonnet, etc)
154 pub model: String,
155 pub response_latency: Option<Duration>,
156 pub error_message: Option<String>,
157}
158
159#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
160pub struct CpuEvent {
161 pub usage_as_percentage: f32,
162 pub core_count: u32,
163}
164
165#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
166pub struct MemoryEvent {
167 pub memory_in_bytes: u64,
168 pub virtual_memory_in_bytes: u64,
169}
170
171#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
172pub struct ActionEvent {
173 pub source: String,
174 pub action: String,
175}
176
177#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
178pub struct EditEvent {
179 pub duration: i64,
180 pub environment: String,
181}
182
183#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
184pub struct SettingEvent {
185 pub setting: String,
186 pub value: String,
187}
188
189#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
190pub struct ExtensionEvent {
191 pub extension_id: Arc<str>,
192 pub version: Arc<str>,
193}
194
195#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
196pub struct AppEvent {
197 pub operation: String,
198}
199
200#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
201pub struct ReplEvent {
202 pub kernel_language: String,
203 pub kernel_status: String,
204 pub repl_session_id: String,
205}
206
207#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
208pub struct BacktraceFrame {
209 pub ip: usize,
210 pub symbol_addr: usize,
211 pub base: Option<usize>,
212 pub symbols: Vec<String>,
213}
214
215#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
216pub struct HangReport {
217 pub backtrace: Vec<BacktraceFrame>,
218 pub app_version: Option<SemanticVersion>,
219 pub os_name: String,
220 pub os_version: Option<String>,
221 pub architecture: String,
222 /// Identifier unique to each Zed installation (differs for stable, preview, dev)
223 pub installation_id: Option<String>,
224}
225
226#[derive(Serialize, Deserialize)]
227pub struct LocationData {
228 pub file: String,
229 pub line: u32,
230}
231
232#[derive(Serialize, Deserialize)]
233pub struct Panic {
234 /// The name of the thread that panicked
235 pub thread: String,
236 /// The panic message
237 pub payload: String,
238 /// The location of the panic (file, line number)
239 #[serde(skip_serializing_if = "Option::is_none")]
240 pub location_data: Option<LocationData>,
241 pub backtrace: Vec<String>,
242 /// Zed version number
243 pub app_version: String,
244 /// Zed release channel (stable, preview, dev)
245 pub release_channel: String,
246 pub os_name: String,
247 pub os_version: Option<String>,
248 pub architecture: String,
249 /// The time the panic occurred (UNIX millisecond timestamp)
250 pub panicked_on: i64,
251 /// Identifier unique to each system Zed is installed on
252 #[serde(skip_serializing_if = "Option::is_none")]
253 pub system_id: Option<String>,
254 /// Identifier unique to each Zed installation (differs for stable, preview, dev)
255 #[serde(skip_serializing_if = "Option::is_none")]
256 pub installation_id: Option<String>,
257 /// Identifier unique to each Zed session (differs for each time you open Zed)
258 pub session_id: String,
259}
260
261#[derive(Serialize, Deserialize)]
262pub struct PanicRequest {
263 pub panic: Panic,
264}