Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/duplicate-code-detector.lock.yml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

80 changes: 53 additions & 27 deletions pkg/cli/logs.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,26 +23,27 @@ import (

// WorkflowRun represents a GitHub Actions workflow run with metrics
type WorkflowRun struct {
DatabaseID int64 `json:"databaseId"`
Number int `json:"number"`
URL string `json:"url"`
Status string `json:"status"`
Conclusion string `json:"conclusion"`
WorkflowName string `json:"workflowName"`
CreatedAt time.Time `json:"createdAt"`
StartedAt time.Time `json:"startedAt"`
UpdatedAt time.Time `json:"updatedAt"`
Event string `json:"event"`
HeadBranch string `json:"headBranch"`
HeadSha string `json:"headSha"`
DisplayTitle string `json:"displayTitle"`
Duration time.Duration
TokenUsage int
EstimatedCost float64
Turns int
ErrorCount int
WarningCount int
LogsPath string
DatabaseID int64 `json:"databaseId"`
Number int `json:"number"`
URL string `json:"url"`
Status string `json:"status"`
Conclusion string `json:"conclusion"`
WorkflowName string `json:"workflowName"`
CreatedAt time.Time `json:"createdAt"`
StartedAt time.Time `json:"startedAt"`
UpdatedAt time.Time `json:"updatedAt"`
Event string `json:"event"`
HeadBranch string `json:"headBranch"`
HeadSha string `json:"headSha"`
DisplayTitle string `json:"displayTitle"`
Duration time.Duration
TokenUsage int
EstimatedCost float64
Turns int
ErrorCount int
WarningCount int
MissingToolCount int
LogsPath string
}

// LogMetrics represents extracted metrics from log files
Expand Down Expand Up @@ -526,9 +527,11 @@ func DownloadWorkflowLogs(workflowName string, count int, startDate, endDate, ou
// Display overview table
workflowRuns := make([]WorkflowRun, len(processedRuns))
for i, pr := range processedRuns {
workflowRuns[i] = pr.Run
run := pr.Run
run.MissingToolCount = len(pr.MissingTools)
workflowRuns[i] = run
}
displayLogsOverview(workflowRuns)
displayLogsOverview(processedRuns, verbose)

// Display MCP failures analysis
displayMCPFailuresAnalysis(processedRuns, verbose)
Expand Down Expand Up @@ -1031,13 +1034,13 @@ func parseLogFileWithEngine(filePath string, detectedEngine workflow.CodingAgent
var extractJSONMetrics = workflow.ExtractJSONMetrics

// displayLogsOverview displays a summary table of workflow runs and metrics
func displayLogsOverview(runs []WorkflowRun) {
if len(runs) == 0 {
func displayLogsOverview(processedRuns []ProcessedRun, verbose bool) {
if len(processedRuns) == 0 {
return
}

// Prepare table data
headers := []string{"Run ID", "Workflow", "Status", "Duration", "Tokens", "Cost ($)", "Turns", "Errors", "Warnings", "Created", "Logs Path"}
headers := []string{"Run ID", "Workflow", "Status", "Duration", "Tokens", "Cost ($)", "Turns", "Errors", "Warnings", "Missing", "Created", "Logs Path"}
var rows [][]string

var totalTokens int
Expand All @@ -1046,8 +1049,10 @@ func displayLogsOverview(runs []WorkflowRun) {
var totalTurns int
var totalErrors int
var totalWarnings int
var totalMissingTools int

for _, run := range runs {
for _, pr := range processedRuns {
run := pr.Run
// Format duration
durationStr := ""
if run.Duration > 0 {
Expand Down Expand Up @@ -1084,6 +1089,25 @@ func displayLogsOverview(runs []WorkflowRun) {
warningsStr := fmt.Sprintf("%d", run.WarningCount)
totalWarnings += run.WarningCount

// Format missing tools
var missingToolsStr string
if verbose && len(pr.MissingTools) > 0 {
// In verbose mode, show actual tool names
toolNames := make([]string, len(pr.MissingTools))
for i, tool := range pr.MissingTools {
toolNames[i] = tool.Tool
}
missingToolsStr = strings.Join(toolNames, ", ")
// Truncate if too long
if len(missingToolsStr) > 30 {
missingToolsStr = missingToolsStr[:27] + "..."
}
} else {
// In normal mode, just show the count
missingToolsStr = fmt.Sprintf("%d", run.MissingToolCount)
}
totalMissingTools += run.MissingToolCount

// Truncate workflow name if too long
workflowName := run.WorkflowName
if len(workflowName) > 20 {
Expand All @@ -1109,6 +1133,7 @@ func displayLogsOverview(runs []WorkflowRun) {
turnsStr,
errorsStr,
warningsStr,
missingToolsStr,
run.CreatedAt.Format("2006-01-02"),
relPath,
}
Expand All @@ -1117,7 +1142,7 @@ func displayLogsOverview(runs []WorkflowRun) {

// Prepare total row
totalRow := []string{
fmt.Sprintf("TOTAL (%d runs)", len(runs)),
fmt.Sprintf("TOTAL (%d runs)", len(processedRuns)),
"",
"",
formatDuration(totalDuration),
Expand All @@ -1126,6 +1151,7 @@ func displayLogsOverview(runs []WorkflowRun) {
fmt.Sprintf("%d", totalTurns),
fmt.Sprintf("%d", totalErrors),
fmt.Sprintf("%d", totalWarnings),
fmt.Sprintf("%d", totalMissingTools),
"",
"",
}
Expand Down
Loading