| 38 | } |
| 39 | |
| 40 | func buildSafeOutputChainMetrics(logsPath string) SafeOutputChainMetrics { |
| 41 | items := extractCreatedItemsFromManifest(logsPath) |
| 42 | metrics := SafeOutputChainMetrics{ |
| 43 | ManifestEntryCount: len(items), |
| 44 | } |
| 45 | if logsPath == "" { |
| 46 | return metrics |
| 47 | } |
| 48 | if !safeOutputArtifactsPresent(logsPath) { |
| 49 | safeOutputChainsLog.Print("No safe output artifacts present, skipping chain metrics") |
| 50 | return metrics |
| 51 | } |
| 52 | |
| 53 | safeOutputChainsLog.Printf("Building safe output chain metrics: manifest_entries=%d", len(items)) |
| 54 | |
| 55 | resolvedTargets, tempIDMapStatus := loadResolvedTemporaryIDTargets(logsPath) |
| 56 | metrics.TemporaryIDMapStatus = tempIDMapStatus |
| 57 | metrics.TemporaryIDMappings = len(resolvedTargets) |
| 58 | safeOutputChainsLog.Printf("Temporary ID map status=%s, mappings=%d", tempIDMapStatus, len(resolvedTargets)) |
| 59 | if len(items) == 0 || len(resolvedTargets) == 0 { |
| 60 | return metrics |
| 61 | } |
| 62 | |
| 63 | itemCounts := make(map[string]int) |
| 64 | delegatedTargets := make(map[string]struct { |
| 65 | }) |
| 66 | closedTargets := make(map[string]struct { |
| 67 | }) |
| 68 | for _, item := range items { |
| 69 | if item.Repo == "" || item.Number <= 0 { |
| 70 | continue |
| 71 | } |
| 72 | key := safeOutputTargetKey(item.Repo, item.Number) |
| 73 | itemCounts[key]++ |
| 74 | switch item.Type { |
| 75 | case "assign_to_agent", "create_agent_session": |
| 76 | delegatedTargets[key] = struct { |
| 77 | }{} |
| 78 | case "close_issue", "close_pull_request", "close_discussion", "merge_pull_request": |
| 79 | closedTargets[key] = struct { |
| 80 | }{} |
| 81 | } |
| 82 | } |
| 83 | |
| 84 | for _, target := range resolvedTargets { |
| 85 | key := safeOutputTargetKey(target.Repo, target.Number) |
| 86 | count := itemCounts[key] |
| 87 | if count > 1 { |
| 88 | metrics.ChainedTargetCount++ |
| 89 | metrics.ChainedFollowupActionCount += count - 1 |
| 90 | } |
| 91 | if setutil.Contains(delegatedTargets, key) { |
| 92 | metrics.DelegatedTempTargetCount++ |
| 93 | } |
| 94 | if setutil.Contains(closedTargets, key) { |
| 95 | metrics.ClosedTempTargetCount++ |
| 96 | } |
| 97 | } |