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 {
46        tool_name: String,
47        policy_reason: String,
48    },
49
50    /// A tool operation exceeded its timeout threshold
51    ToolTimeoutWarning {
52        tool_name: String,
53        elapsed: Duration,
54        ceiling: Duration,
55        percentage: u8,
56    },
57
58    /// A destructive operation is about to be performed
59    DestructiveOperationWarning {
60        tool_name: String,
61        operation_type: String,
62        affected_files: Vec<String>,
63        has_backup: bool,
64    },
65}
66
67impl ToolTelemetryEvent {
68    /// Create a tool fallback event for edit_file -> apply_patch transition
69    pub fn edit_to_patch_fallback(file_path: impl Into<String>, reason: impl Into<String>) -> Self {
70        Self::ToolFallbackDetected {
71            from_tool: "edit_file".to_string(),
72            to_tool: "apply_patch".to_string(),
73            reason: reason.into(),
74            affected_file: Some(file_path.into()),
75        }
76    }
77
78    /// Create a destructive operation warning for delete-and-recreate patterns
79    pub fn delete_and_recreate_warning(
80        tool_name: impl Into<String>,
81        files: Vec<String>,
82        has_backup: bool,
83    ) -> Self {
84        Self::DestructiveOperationWarning {
85            tool_name: tool_name.into(),
86            operation_type: "delete_and_recreate".to_string(),
87            affected_files: files,
88            has_backup,
89        }
90    }
91}
92
93#[cfg(test)]
94mod tests {
95    use super::*;
96
97    #[test]
98    fn test_create_fallback_event() {
99        let event = ToolTelemetryEvent::edit_to_patch_fallback("test.rs", "pattern_not_found");
100
101        match event {
102            ToolTelemetryEvent::ToolFallbackDetected {
103                from_tool,
104                to_tool,
105                reason,
106                affected_file,
107            } => {
108                assert_eq!(from_tool, "edit_file");
109                assert_eq!(to_tool, "apply_patch");
110                assert_eq!(reason, "pattern_not_found");
111                assert_eq!(affected_file, Some("test.rs".to_string()));
112            }
113            _ => panic!("Expected ToolFallbackDetected event"),
114        }
115    }
116
117    #[test]
118    fn test_create_destructive_warning() {
119        let event = ToolTelemetryEvent::delete_and_recreate_warning(
120            "apply_patch",
121            vec!["file1.rs".to_string(), "file2.rs".to_string()],
122            false,
123        );
124
125        match event {
126            ToolTelemetryEvent::DestructiveOperationWarning {
127                tool_name,
128                operation_type,
129                affected_files,
130                has_backup,
131            } => {
132                assert_eq!(tool_name, "apply_patch");
133                assert_eq!(operation_type, "delete_and_recreate");
134                assert_eq!(affected_files.len(), 2);
135                assert!(!has_backup);
136            }
137            _ => panic!("Expected DestructiveOperationWarning event"),
138        }
139    }
140}