Skip to main content

vtcode_core/tools/registry/
telemetry.rs

1//! Telemetry events for tool operations
2//!
3//! This module defines telemetry events emitted by the tool registry to track
4//! operational metrics, fallback sequences, and potential issues during tool
5//! execution.
6
7use std::time::Duration;
8
9/// Telemetry events emitted during tool execution
10#[derive(Debug, Clone, PartialEq, Eq)]
11pub enum ToolTelemetryEvent {
12    /// A tool execution was attempted
13    ToolExecutionStarted { tool_name: String, has_args: bool },
14
15    /// A tool execution completed successfully
16    ToolExecutionCompleted {
17        tool_name: String,
18        duration: Duration,
19        output_size_bytes: usize,
20    },
21
22    /// A tool execution failed
23    ToolExecutionFailed {
24        tool_name: String,
25        error_type: String,
26        duration: Duration,
27    },
28
29    /// A tool fell back to a different implementation or strategy
30    ///
31    /// This is particularly important for detecting cascading delete/recreate
32    /// sequences as identified in the Codex issue review.
33    ToolFallbackDetected {
34        /// The original tool that was attempted
35        from_tool: String,
36        /// The fallback tool or strategy used
37        to_tool: String,
38        /// Reason for the fallback
39        reason: String,
40        /// Optional file path affected by the fallback
41        affected_file: Option<String>,
42    },
43
44    /// A tool operation was blocked by policy
45    ToolBlocked { tool_name: String, policy_reason: String },
46
47    /// A tool operation exceeded its timeout threshold
48    ToolTimeoutWarning {
49        tool_name: String,
50        elapsed: Duration,
51        ceiling: Duration,
52        percentage: u8,
53    },
54
55    /// A destructive operation is about to be performed
56    DestructiveOperationWarning {
57        tool_name: String,
58        operation_type: String,
59        affected_files: Vec<String>,
60        has_backup: bool,
61    },
62}
63
64impl ToolTelemetryEvent {
65    /// Create a tool fallback event for edit_file -> apply_patch transition
66    pub fn edit_to_patch_fallback(file_path: impl Into<String>, reason: impl Into<String>) -> Self {
67        Self::ToolFallbackDetected {
68            from_tool: "edit_file".to_string(),
69            to_tool: "apply_patch".to_string(),
70            reason: reason.into(),
71            affected_file: Some(file_path.into()),
72        }
73    }
74
75    /// Create a destructive operation warning for delete-and-recreate patterns
76    pub fn delete_and_recreate_warning(tool_name: impl Into<String>, files: Vec<String>, has_backup: bool) -> Self {
77        Self::DestructiveOperationWarning {
78            tool_name: tool_name.into(),
79            operation_type: "delete_and_recreate".to_string(),
80            affected_files: files,
81            has_backup,
82        }
83    }
84}
85
86#[cfg(test)]
87mod tests {
88    use super::*;
89
90    #[test]
91    fn test_create_fallback_event() {
92        let event = ToolTelemetryEvent::edit_to_patch_fallback("test.rs", "pattern_not_found");
93
94        match event {
95            ToolTelemetryEvent::ToolFallbackDetected { from_tool, to_tool, reason, affected_file } => {
96                assert_eq!(from_tool, "edit_file");
97                assert_eq!(to_tool, "apply_patch");
98                assert_eq!(reason, "pattern_not_found");
99                assert_eq!(affected_file, Some("test.rs".to_string()));
100            }
101            _ => panic!("Expected ToolFallbackDetected event"),
102        }
103    }
104
105    #[test]
106    fn test_create_destructive_warning() {
107        let event = ToolTelemetryEvent::delete_and_recreate_warning(
108            "apply_patch",
109            vec!["file1.rs".to_string(), "file2.rs".to_string()],
110            false,
111        );
112
113        match event {
114            ToolTelemetryEvent::DestructiveOperationWarning {
115                tool_name,
116                operation_type,
117                affected_files,
118                has_backup,
119            } => {
120                assert_eq!(tool_name, "apply_patch");
121                assert_eq!(operation_type, "delete_and_recreate");
122                assert_eq!(affected_files.len(), 2);
123                assert!(!has_backup);
124            }
125            _ => panic!("Expected DestructiveOperationWarning event"),
126        }
127    }
128}