acp: Add telemetry

This commit is contained in:
Bennet Bo Fenner 2025-08-25 19:46:57 +02:00
parent 5c346a4ccf
commit ded77d07c9
9 changed files with 92 additions and 22 deletions

View file

@ -22,6 +22,10 @@ impl NativeAgentServer {
}
impl AgentServer for NativeAgentServer {
fn telemetry_id(&self) -> &'static str {
"zed"
}
fn name(&self) -> SharedString {
"Zed Agent".into()
}

View file

@ -36,6 +36,7 @@ pub trait AgentServer: Send {
fn name(&self) -> SharedString;
fn empty_state_headline(&self) -> SharedString;
fn empty_state_message(&self) -> SharedString;
fn telemetry_id(&self) -> &'static str;
fn connect(
&self,

View file

@ -43,6 +43,10 @@ use acp_thread::{AcpThread, AgentConnection, AuthRequired, LoadError, MentionUri
pub struct ClaudeCode;
impl AgentServer for ClaudeCode {
fn telemetry_id(&self) -> &'static str {
"claude-code"
}
fn name(&self) -> SharedString {
"Claude Code".into()
}

View file

@ -22,6 +22,10 @@ impl CustomAgentServer {
}
impl crate::AgentServer for CustomAgentServer {
fn telemetry_id(&self) -> &'static str {
"custom"
}
fn name(&self) -> SharedString {
self.name.clone()
}

View file

@ -17,6 +17,10 @@ pub struct Gemini;
const ACP_ARG: &str = "--experimental-acp";
impl AgentServer for Gemini {
fn telemetry_id(&self) -> &'static str {
"gemini-cli"
}
fn name(&self) -> SharedString {
"Gemini CLI".into()
}

View file

@ -892,6 +892,8 @@ impl AcpThreadView {
window: &mut Window,
cx: &mut Context<Self>,
) {
let agent_telemetry_id = self.agent.telemetry_id();
self.thread_error.take();
self.editing_message.take();
self.thread_feedback.clear();
@ -936,6 +938,9 @@ impl AcpThreadView {
}
});
drop(guard);
telemetry::event!("Agent Message Sent", agent = agent_telemetry_id);
thread.send(contents, cx)
})?;
send.await
@ -1242,12 +1247,26 @@ impl AcpThreadView {
pending_auth_method.replace(method.clone());
let authenticate = connection.authenticate(method, cx);
cx.notify();
self.auth_task = Some(cx.spawn_in(window, {
self.auth_task =
Some(cx.spawn_in(window, {
let project = self.project.clone();
let agent = self.agent.clone();
async move |this, cx| {
let result = authenticate.await;
match &result {
Ok(_) => telemetry::event!(
"Authenticate Agent Succeeded",
agent = agent.telemetry_id()
),
Err(_) => {
telemetry::event!(
"Authenticate Agent Failed",
agent = agent.telemetry_id(),
)
}
}
this.update_in(cx, |this, window, cx| {
if let Err(err) = result {
this.handle_thread_error(err, cx);
@ -2772,6 +2791,12 @@ impl AcpThreadView {
.on_click({
let method_id = method.id.clone();
cx.listener(move |this, _, window, cx| {
telemetry::event!(
"Authenticate Agent Started",
agent = this.agent.telemetry_id(),
method = method_id
);
this.authenticate(method_id.clone(), window, cx)
})
})
@ -2800,6 +2825,8 @@ impl AcpThreadView {
.icon_color(Color::Muted)
.icon_position(IconPosition::Start)
.on_click(cx.listener(move |this, _, window, cx| {
telemetry::event!("Agent Install CLI", agent = this.agent.telemetry_id());
let task = this
.workspace
.update(cx, |workspace, cx| {
@ -2857,6 +2884,8 @@ impl AcpThreadView {
.icon_color(Color::Muted)
.icon_position(IconPosition::Start)
.on_click(cx.listener(move |this, _, window, cx| {
telemetry::event!("Agent Upgrade CLI", agent = this.agent.telemetry_id());
let task = this
.workspace
.update(cx, |workspace, cx| {
@ -3704,6 +3733,8 @@ impl AcpThreadView {
}
})
.ok();
telemetry::event!("Follow Agent Selected", following = !following);
}
fn render_follow_toggle(&self, cx: &mut Context<Self>) -> impl IntoElement {
@ -5319,6 +5350,10 @@ pub(crate) mod tests {
where
C: 'static + AgentConnection + Send + Clone,
{
fn telemetry_id(&self) -> &'static str {
"test"
}
fn logo(&self) -> ui::IconName {
ui::IconName::Ai
}

View file

@ -1025,6 +1025,8 @@ impl AgentPanel {
}
fn new_prompt_editor(&mut self, window: &mut Window, cx: &mut Context<Self>) {
telemetry::event!("Agent Thread Started", agent = "zed-text");
let context = self
.context_store
.update(cx, |context_store, cx| context_store.create(cx));
@ -1117,6 +1119,8 @@ impl AgentPanel {
}
};
telemetry::event!("Agent Thread Started", agent = ext_agent.name());
let server = ext_agent.server(fs, history);
this.update_in(cx, |this, window, cx| {
@ -2325,6 +2329,8 @@ impl AgentPanel {
.menu({
let menu = self.assistant_navigation_menu.clone();
move |window, cx| {
telemetry::event!("View Thread History Clicked");
if let Some(menu) = menu.as_ref() {
menu.update(cx, |_, cx| {
cx.defer_in(window, |menu, window, cx| {
@ -2503,6 +2509,8 @@ impl AgentPanel {
let workspace = self.workspace.clone();
move |window, cx| {
telemetry::event!("New Thread Clicked");
let active_thread = active_thread.clone();
Some(ContextMenu::build(window, cx, |mut menu, _window, cx| {
menu = menu

View file

@ -174,6 +174,15 @@ enum ExternalAgent {
}
impl ExternalAgent {
fn name(&self) -> &'static str {
match self {
Self::NativeAgent => "zed",
Self::Gemini => "gemini-cli",
Self::ClaudeCode => "claude-code",
Self::Custom { .. } => "custom",
}
}
pub fn server(
&self,
fs: Arc<dyn fs::Fs>,

View file

@ -361,6 +361,7 @@ impl TextThreadEditor {
if self.sending_disabled(cx) {
return;
}
telemetry::event!("Agent Message Sent", agent = "zed-text");
self.send_to_model(window, cx);
}