2020import sys
2121import threading
2222import time
23- from typing import Optional , Dict , Any
23+ from typing import Any
2424from urllib .parse import urlparse
2525import uuid
2626
@@ -55,6 +55,7 @@ class RecordType(str, Enum):
5555 USAGE = "usage"
5656 LATENCY = "latency"
5757 FAILURE = "failure"
58+ RESOURCE_RETRIEVAL = "resource_retrieval"
5859 TOOL_EXECUTION = "tool_execution"
5960 UNITY_CONNECTION = "unity_connection"
6061 CLIENT_CONNECTION = "client_connection"
@@ -78,8 +79,8 @@ class TelemetryRecord:
7879 timestamp : float
7980 customer_uuid : str
8081 session_id : str
81- data : Dict [str , Any ]
82- milestone : Optional [ MilestoneType ] = None
82+ data : dict [str , Any ]
83+ milestone : MilestoneType | None = None
8384
8485
8586class TelemetryConfig :
@@ -208,8 +209,8 @@ class TelemetryCollector:
208209
209210 def __init__ (self ):
210211 self .config = TelemetryConfig ()
211- self ._customer_uuid : Optional [ str ] = None
212- self ._milestones : Dict [str , Dict [str , Any ]] = {}
212+ self ._customer_uuid : str | None = None
213+ self ._milestones : dict [str , dict [str , Any ]] = {}
213214 self ._lock : threading .Lock = threading .Lock ()
214215 # Bounded queue with single background worker (records only; no context propagation)
215216 self ._queue : "queue.Queue[TelemetryRecord]" = queue .Queue (maxsize = 1000 )
@@ -262,7 +263,7 @@ def _save_milestones(self):
262263 except OSError as e :
263264 logger .warning (f"Failed to save milestones: { e } " , exc_info = True )
264265
265- def record_milestone (self , milestone : MilestoneType , data : Optional [ Dict [ str , Any ]] = None ) -> bool :
266+ def record_milestone (self , milestone : MilestoneType , data : dict [ str , Any ] | None = None ) -> bool :
266267 """Record a milestone event, returns True if this is the first occurrence"""
267268 if not self .config .enabled :
268269 return False
@@ -288,8 +289,8 @@ def record_milestone(self, milestone: MilestoneType, data: Optional[Dict[str, An
288289
289290 def record (self ,
290291 record_type : RecordType ,
291- data : Dict [str , Any ],
292- milestone : Optional [ MilestoneType ] = None ):
292+ data : dict [str , Any ],
293+ milestone : MilestoneType | None = None ):
293294 """Record a telemetry event (async, non-blocking)"""
294295 if not self .config .enabled :
295296 return
@@ -393,7 +394,7 @@ def _send_telemetry(self, record: TelemetryRecord):
393394
394395
395396# Global telemetry instance
396- _telemetry_collector : Optional [ TelemetryCollector ] = None
397+ _telemetry_collector : TelemetryCollector | None = None
397398
398399
399400def get_telemetry () -> TelemetryCollector :
@@ -405,18 +406,18 @@ def get_telemetry() -> TelemetryCollector:
405406
406407
407408def record_telemetry (record_type : RecordType ,
408- data : Dict [str , Any ],
409- milestone : Optional [ MilestoneType ] = None ):
409+ data : dict [str , Any ],
410+ milestone : MilestoneType | None = None ):
410411 """Convenience function to record telemetry"""
411412 get_telemetry ().record (record_type , data , milestone )
412413
413414
414- def record_milestone (milestone : MilestoneType , data : Optional [ Dict [ str , Any ]] = None ) -> bool :
415+ def record_milestone (milestone : MilestoneType , data : dict [ str , Any ] | None = None ) -> bool :
415416 """Convenience function to record a milestone"""
416417 return get_telemetry ().record_milestone (milestone , data )
417418
418419
419- def record_tool_usage (tool_name : str , success : bool , duration_ms : float , error : Optional [ str ] = None , sub_action : Optional [ str ] = None ):
420+ def record_tool_usage (tool_name : str , success : bool , duration_ms : float , error : str | None = None , sub_action : str | None = None ):
420421 """Record tool usage telemetry
421422
422423 Args:
@@ -445,7 +446,28 @@ def record_tool_usage(tool_name: str, success: bool, duration_ms: float, error:
445446 record_telemetry (RecordType .TOOL_EXECUTION , data )
446447
447448
448- def record_latency (operation : str , duration_ms : float , metadata : Optional [Dict [str , Any ]] = None ):
449+ def record_resource_usage (resource_name : str , success : bool , duration_ms : float , error : str | None = None ):
450+ """Record resource usage telemetry
451+
452+ Args:
453+ resource_name: Name of the resource invoked (e.g., 'get_tests').
454+ success: Whether the resource completed successfully.
455+ duration_ms: Execution duration in milliseconds.
456+ error: Optional error message (truncated if present).
457+ """
458+ data = {
459+ "resource_name" : resource_name ,
460+ "success" : success ,
461+ "duration_ms" : round (duration_ms , 2 )
462+ }
463+
464+ if error :
465+ data ["error" ] = str (error )[:200 ] # Limit error message length
466+
467+ record_telemetry (RecordType .RESOURCE_RETRIEVAL , data )
468+
469+
470+ def record_latency (operation : str , duration_ms : float , metadata : dict [str , Any ] | None = None ):
449471 """Record latency telemetry"""
450472 data = {
451473 "operation" : operation ,
@@ -458,7 +480,7 @@ def record_latency(operation: str, duration_ms: float, metadata: Optional[Dict[s
458480 record_telemetry (RecordType .LATENCY , data )
459481
460482
461- def record_failure (component : str , error : str , metadata : Optional [ Dict [ str , Any ]] = None ):
483+ def record_failure (component : str , error : str , metadata : dict [ str , Any ] | None = None ):
462484 """Record failure telemetry"""
463485 data = {
464486 "component" : component ,
0 commit comments