Skip to content

Commit e6542a7

Browse files
authored
chore: Add telemetry event for slash command execution (#2285)
* first pass * parse command name * add ssoRegion in telemetry definitions and fix format * update telemetry definitions with existing result and reason * add com & sub's name function * update command name
1 parent 661875a commit e6542a7

File tree

11 files changed

+228
-5
lines changed

11 files changed

+228
-5
lines changed

crates/chat-cli/src/cli/chat/cli/context.rs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -322,4 +322,14 @@ impl ContextSubcommand {
322322
skip_printing_tools: true,
323323
})
324324
}
325+
326+
pub fn name(&self) -> &'static str {
327+
match self {
328+
ContextSubcommand::Show { .. } => "show",
329+
ContextSubcommand::Add { .. } => "add",
330+
ContextSubcommand::Remove { .. } => "remove",
331+
ContextSubcommand::Clear => "clear",
332+
ContextSubcommand::Hooks => "hooks",
333+
}
334+
}
325335
}

crates/chat-cli/src/cli/chat/cli/hooks.rs

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -449,6 +449,10 @@ impl HooksArgs {
449449
skip_printing_tools: true,
450450
})
451451
}
452+
453+
pub fn subcommand_name(&self) -> Option<&'static str> {
454+
self.subcommand.as_ref().map(|s| s.name())
455+
}
452456
}
453457

454458
#[deny(missing_docs)]
@@ -634,6 +638,18 @@ impl HooksSubcommand {
634638
skip_printing_tools: true,
635639
})
636640
}
641+
642+
pub fn name(&self) -> &'static str {
643+
match self {
644+
HooksSubcommand::Add { .. } => "add",
645+
HooksSubcommand::Remove { .. } => "remove",
646+
HooksSubcommand::Enable { .. } => "enable",
647+
HooksSubcommand::Disable { .. } => "disable",
648+
HooksSubcommand::EnableAll => "enable-all",
649+
HooksSubcommand::DisableAll => "disable-all",
650+
HooksSubcommand::Show => "show",
651+
}
652+
}
637653
}
638654

639655
/// Prints hook configuration grouped by trigger: conversation session start or per user message

crates/chat-cli/src/cli/chat/cli/knowledge.rs

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -478,4 +478,16 @@ impl KnowledgeSubcommand {
478478
},
479479
}
480480
}
481+
482+
pub fn name(&self) -> &'static str {
483+
match self {
484+
KnowledgeSubcommand::Show => "show",
485+
KnowledgeSubcommand::Add { .. } => "add",
486+
KnowledgeSubcommand::Remove { .. } => "remove",
487+
KnowledgeSubcommand::Update { .. } => "update",
488+
KnowledgeSubcommand::Clear => "clear",
489+
KnowledgeSubcommand::Status => "status",
490+
KnowledgeSubcommand::Cancel { .. } => "cancel",
491+
}
492+
}
481493
}

crates/chat-cli/src/cli/chat/cli/mod.rs

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -122,4 +122,40 @@ impl SlashCommand {
122122
// },
123123
}
124124
}
125+
126+
pub fn command_name(&self) -> &'static str {
127+
match self {
128+
Self::Quit => "quit",
129+
Self::Clear(_) => "clear",
130+
Self::Agent(_) => "agent",
131+
Self::Context(_) => "context",
132+
Self::Knowledge(_) => "knowledge",
133+
Self::PromptEditor(_) => "editor",
134+
Self::Compact(_) => "compact",
135+
Self::Tools(_) => "tools",
136+
Self::Issue(_) => "issue",
137+
Self::Prompts(_) => "prompts",
138+
Self::Hooks(_) => "hooks",
139+
Self::Usage(_) => "usage",
140+
Self::Mcp(_) => "mcp",
141+
Self::Model(_) => "model",
142+
Self::Subscribe(_) => "subscribe",
143+
Self::Persist(sub) => match sub {
144+
PersistSubcommand::Save { .. } => "save",
145+
PersistSubcommand::Load { .. } => "load",
146+
},
147+
}
148+
}
149+
150+
pub fn subcommand_name(&self) -> Option<&'static str> {
151+
match self {
152+
SlashCommand::Agent(sub) => Some(sub.name()),
153+
SlashCommand::Context(sub) => Some(sub.name()),
154+
SlashCommand::Knowledge(sub) => Some(sub.name()),
155+
SlashCommand::Tools(arg) => arg.subcommand_name(),
156+
SlashCommand::Prompts(arg) => arg.subcommand_name(),
157+
SlashCommand::Hooks(arg) => arg.subcommand_name(),
158+
_ => None,
159+
}
160+
}
125161
}

crates/chat-cli/src/cli/chat/cli/profile.rs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -138,6 +138,16 @@ impl AgentSubcommand {
138138
skip_printing_tools: true,
139139
})
140140
}
141+
142+
pub fn name(&self) -> &'static str {
143+
match self {
144+
Self::List => "list",
145+
Self::Create { .. } => "create",
146+
Self::Delete { .. } => "delete",
147+
Self::Set { .. } => "set",
148+
Self::Rename { .. } => "rename",
149+
}
150+
}
141151
}
142152

143153
fn highlight_json(output: &mut impl Write, json_str: &str) -> eyre::Result<()> {

crates/chat-cli/src/cli/chat/cli/prompts.rs

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -200,6 +200,10 @@ impl PromptsArgs {
200200
skip_printing_tools: true,
201201
})
202202
}
203+
204+
pub fn subcommand_name(&self) -> Option<&'static str> {
205+
self.subcommand.as_ref().map(|s| s.name())
206+
}
203207
}
204208

205209
#[deny(missing_docs)]
@@ -305,4 +309,11 @@ impl PromptsSubcommand {
305309
skip_printing_tools: true,
306310
})
307311
}
312+
313+
pub fn name(&self) -> &'static str {
314+
match self {
315+
PromptsSubcommand::List { .. } => "list",
316+
PromptsSubcommand::Get { .. } => "get",
317+
}
318+
}
308319
}

crates/chat-cli/src/cli/chat/cli/tools.rs

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -166,6 +166,10 @@ impl ToolsArgs {
166166

167167
Ok(ChatState::default())
168168
}
169+
170+
pub fn subcommand_name(&self) -> Option<&'static str> {
171+
self.subcommand.as_ref().map(|s| s.name())
172+
}
169173
}
170174

171175
#[deny(missing_docs)]
@@ -383,4 +387,14 @@ impl ToolsSubcommand {
383387
skip_printing_tools: true,
384388
})
385389
}
390+
391+
pub fn name(&self) -> &'static str {
392+
match self {
393+
ToolsSubcommand::Schema => "schema",
394+
ToolsSubcommand::Trust { .. } => "trust",
395+
ToolsSubcommand::Untrust { .. } => "untrust",
396+
ToolsSubcommand::TrustAll => "trust-all",
397+
ToolsSubcommand::Reset => "reset",
398+
}
399+
}
386400
}

crates/chat-cli/src/cli/chat/mod.rs

Lines changed: 45 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1396,16 +1396,30 @@ impl ChatSession {
13961396

13971397
match SlashCommand::try_parse_from(args) {
13981398
Ok(command) => {
1399+
let command_name = command.command_name().to_string();
1400+
let subcommand_name = command.subcommand_name().map(|s| s.to_string());
1401+
13991402
match command.execute(os, self).await {
1400-
Ok(chat_state)
1403+
Ok(chat_state) => {
1404+
let _ = self
1405+
.send_slash_command_telemetry(
1406+
os,
1407+
command_name,
1408+
subcommand_name,
1409+
TelemetryResult::Succeeded,
1410+
None,
1411+
)
1412+
.await;
1413+
14011414
if matches!(chat_state, ChatState::Exit)
14021415
|| matches!(chat_state, ChatState::HandleInput { input: _ })
14031416
// TODO(bskiser): this is just a hotfix for handling state changes
14041417
// from manually running /compact, without impacting behavior of
14051418
// other slash commands.
1406-
|| matches!(chat_state, ChatState::CompactHistory { .. }) =>
1407-
{
1408-
return Ok(chat_state);
1419+
|| matches!(chat_state, ChatState::CompactHistory { .. })
1420+
{
1421+
return Ok(chat_state);
1422+
}
14091423
},
14101424
Err(err) => {
14111425
queue!(
@@ -1414,8 +1428,16 @@ impl ChatSession {
14141428
style::Print(format!("\nFailed to execute command: {}\n", err)),
14151429
style::SetForegroundColor(Color::Reset)
14161430
)?;
1431+
let _ = self
1432+
.send_slash_command_telemetry(
1433+
os,
1434+
command_name,
1435+
subcommand_name,
1436+
TelemetryResult::Failed,
1437+
Some(err.to_string()),
1438+
)
1439+
.await;
14171440
},
1418-
_ => {},
14191441
}
14201442

14211443
writeln!(self.stderr)?;
@@ -2323,6 +2345,24 @@ impl ChatSession {
23232345
.await
23242346
.ok();
23252347
}
2348+
2349+
pub async fn send_slash_command_telemetry(
2350+
&self,
2351+
os: &Os,
2352+
command: String,
2353+
subcommand: Option<String>,
2354+
result: TelemetryResult,
2355+
reason: Option<String>,
2356+
) {
2357+
let conversation_id = self.conversation.conversation_id().to_owned();
2358+
if let Err(e) = os
2359+
.telemetry
2360+
.send_chat_slash_command_executed(&os.database, conversation_id, command, subcommand, result, reason)
2361+
.await
2362+
{
2363+
tracing::warn!("Failed to send slash command telemetry: {}", e);
2364+
}
2365+
}
23262366
}
23272367

23282368
/// Replaces amzn_codewhisperer_client::types::SubscriptionStatus with a more descriptive type.

crates/chat-cli/src/telemetry/core.rs

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ use crate::telemetry::definitions::metrics::{
1515
AmazonqProfileState,
1616
AmazonqStartChat,
1717
CodewhispererterminalAddChatMessage,
18+
CodewhispererterminalChatSlashCommandExecuted,
1819
CodewhispererterminalCliSubcommandExecuted,
1920
CodewhispererterminalMcpServerInit,
2021
CodewhispererterminalRefreshCredentials,
@@ -103,6 +104,27 @@ impl Event {
103104
}
104105
.into_metric_datum(),
105106
),
107+
EventType::ChatSlashCommandExecuted {
108+
conversation_id,
109+
command,
110+
subcommand,
111+
result,
112+
reason,
113+
} => Some(
114+
CodewhispererterminalChatSlashCommandExecuted {
115+
create_time: self.created_time,
116+
value: None,
117+
credential_start_url: self.credential_start_url.map(Into::into),
118+
sso_region: self.sso_region.map(Into::into),
119+
amazonq_conversation_id: Some(conversation_id.into()),
120+
codewhispererterminal_chat_slash_command: Some(command.into()),
121+
codewhispererterminal_chat_slash_subcommand: subcommand.map(Into::into),
122+
result: Some(result.to_string().into()),
123+
reason: reason.map(Into::into),
124+
codewhispererterminal_in_cloudshell: None,
125+
}
126+
.into_metric_datum(),
127+
),
106128
EventType::ChatStart { conversation_id, model } => Some(
107129
AmazonqStartChat {
108130
create_time: self.created_time,
@@ -287,6 +309,13 @@ pub enum EventType {
287309
CliSubcommandExecuted {
288310
subcommand: String,
289311
},
312+
ChatSlashCommandExecuted {
313+
conversation_id: String,
314+
command: String,
315+
subcommand: Option<String>,
316+
result: TelemetryResult,
317+
reason: Option<String>,
318+
},
290319
ChatStart {
291320
conversation_id: String,
292321
model: Option<String>,

crates/chat-cli/src/telemetry/mod.rs

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -232,6 +232,26 @@ impl TelemetryThread {
232232
}))?)
233233
}
234234

235+
pub async fn send_chat_slash_command_executed(
236+
&self,
237+
database: &Database,
238+
conversation_id: String,
239+
command: String,
240+
subcommand: Option<String>,
241+
result: TelemetryResult,
242+
reason: Option<String>,
243+
) -> Result<(), TelemetryError> {
244+
let mut event = Event::new(EventType::ChatSlashCommandExecuted {
245+
conversation_id,
246+
command,
247+
subcommand,
248+
result,
249+
reason,
250+
});
251+
set_start_url_and_region(database, &mut event).await;
252+
Ok(self.tx.send(event)?)
253+
}
254+
235255
#[allow(clippy::too_many_arguments)] // TODO: Should make a parameters struct.
236256
pub async fn send_chat_added_message(
237257
&self,

0 commit comments

Comments
 (0)