buildToolUsageSummary aggregates tool usage across all runs Filters out invalid tool names that appear to be fragments or garbage
(processedRuns []ProcessedRun)
| 68 | // buildToolUsageSummary aggregates tool usage across all runs |
| 69 | // Filters out invalid tool names that appear to be fragments or garbage |
| 70 | func buildToolUsageSummary(processedRuns []ProcessedRun) []ToolUsageSummary { |
| 71 | reportLog.Printf("Building tool usage summary from %d processed runs", len(processedRuns)) |
| 72 | toolStats := make(map[string]*ToolUsageSummary) |
| 73 | |
| 74 | for _, pr := range processedRuns { |
| 75 | // Extract metrics from run's logs |
| 76 | metrics := ExtractLogMetricsFromRun(pr) |
| 77 | |
| 78 | // Track which runs use each tool |
| 79 | toolRunTracker := make(map[string]struct { |
| 80 | }) |
| 81 | |
| 82 | for _, toolCall := range metrics.ToolCalls { |
| 83 | displayKey := workflow.PrettifyToolName(toolCall.Name) |
| 84 | |
| 85 | // Filter out invalid tool names |
| 86 | if !isValidToolName(displayKey) { |
| 87 | continue |
| 88 | } |
| 89 | |
| 90 | toolRunTracker[displayKey] = struct { |
| 91 | }{} |
| 92 | |
| 93 | if existing, exists := toolStats[displayKey]; exists { |
| 94 | existing.TotalCalls += toolCall.CallCount |
| 95 | if toolCall.MaxOutputSize > existing.MaxOutputSize { |
| 96 | existing.MaxOutputSize = toolCall.MaxOutputSize |
| 97 | } |
| 98 | if toolCall.MaxDuration > 0 { |
| 99 | maxDur := timeutil.FormatDuration(toolCall.MaxDuration) |
| 100 | if existing.MaxDuration == "" || toolCall.MaxDuration > parseDurationString(existing.MaxDuration) { |
| 101 | existing.MaxDuration = maxDur |
| 102 | } |
| 103 | } |
| 104 | } else { |
| 105 | info := &ToolUsageSummary{ |
| 106 | Name: displayKey, |
| 107 | TotalCalls: toolCall.CallCount, |
| 108 | MaxOutputSize: toolCall.MaxOutputSize, |
| 109 | Runs: 0, // Will be incremented below |
| 110 | } |
| 111 | if toolCall.MaxDuration > 0 { |
| 112 | info.MaxDuration = timeutil.FormatDuration(toolCall.MaxDuration) |
| 113 | } |
| 114 | toolStats[displayKey] = info |
| 115 | } |
| 116 | } |
| 117 | |
| 118 | // Increment run count for tools used in this run |
| 119 | for toolName := range toolRunTracker { |
| 120 | if stat, exists := toolStats[toolName]; exists { |
| 121 | stat.Runs++ |
| 122 | } |
| 123 | } |
| 124 | } |
| 125 | |
| 126 | var result []ToolUsageSummary |
| 127 | for _, info := range toolStats { |