Skip to content

Commit

Permalink
feat: added extended statistics
Browse files Browse the repository at this point in the history
  • Loading branch information
Alec Cunningham authored and Alec Cunningham committed Oct 23, 2024
1 parent b5a5350 commit c738d70
Show file tree
Hide file tree
Showing 9 changed files with 68 additions and 28 deletions.
2 changes: 1 addition & 1 deletion cmd/server/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ func main() {
wp.Start()

// Start the API server
go api.StartServer(cfg, database, githubClient)
go api.StartServer(cfg, database, githubClient, wp)

// Wait for interrupt signal to gracefully shut down the worker pool
quit := make(chan os.Signal, 1)
Expand Down
10 changes: 5 additions & 5 deletions docs/DESIGN.md
Original file line number Diff line number Diff line change
Expand Up @@ -73,11 +73,11 @@ Recommended Approach
### Database Schema Design

- Tables:
- users: Stores user information.
- repositories: Tracks repositories being monitored.
- workflows: Contains workflow definitions.
- workflow_runs: Records individual workflow executions.
- statistics: Stores precomputed stats for quick access.
- `users`: Stores user information.
- `repositories`: Tracks repositories being monitored.
- `workflows`: Contains workflow definitions.
- `workflow_runs`: Records individual workflow executions.
- `statistics`: Stores precomputed stats for quick access.

- Relationships:
- Establish foreign keys between tables for referential integrity.
Expand Down
42 changes: 29 additions & 13 deletions pkg/api/handlers.go
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
// pkg/api/handlers.go

package api

import (
Expand Down Expand Up @@ -80,37 +78,55 @@ func GetWorkflowStats(c *gin.Context) {
return
}

// Calculate statistics
// Initialize counters
totalRuns := len(runs)
successCount := 0
failureCount := 0
cancelledCount := 0
timedOutCount := 0
actionRequiredCount := 0

for _, run := range runs {
switch run.Conclusion {
case "success":
successCount++
case "failure":
failureCount++
case "cancelled":
cancelledCount++
case "timed_out":
timedOutCount++
case "action_required":
actionRequiredCount++
}
}

// Calculate percentages
var successRate, failureRate float64
var successRate, failureRate, cancelledRate, timedOutRate, actionRequiredRate float64
if totalRuns > 0 {
successRate = float64(successCount) / float64(totalRuns) * 100
failureRate = float64(failureCount) / float64(totalRuns) * 100
cancelledRate = float64(cancelledCount) / float64(totalRuns) * 100
timedOutRate = float64(timedOutCount) / float64(totalRuns) * 100
actionRequiredRate = float64(actionRequiredCount) / float64(totalRuns) * 100
}

// Respond with statistics
c.JSON(http.StatusOK, gin.H{
"workflow_id": workflowID,
"workflow_name": workflow.Name,
"total_runs": totalRuns,
"success_count": successCount,
"failure_count": failureCount,
"success_rate": successRate,
"failure_rate": failureRate,
"start_time": startTime.Format(time.RFC3339),
"end_time": endTime.Format(time.RFC3339),
"workflow_id": workflowID, //The unique identifier of the workflow (e.g., 123).
"workflow_name": workflow.Name, //The name of the workflow (e.g., "CI Build and Test").
"total_runs": totalRuns, //The total number of workflow runs within the specified time range (e.g., 200).
"success_count": successCount, //The number of runs that concluded with a success status (e.g., 150).
"failure_count": failureCount, //The number of runs that concluded with a failure status (e.g., 30).
"cancelled_count": cancelledCount, //The number of runs that were cancelled (e.g., 10).
"timed_out_count": timedOutCount, //The number of runs that timed out (e.g., 5).
"action_required_count": actionRequiredCount, //The number of runs that required action (e.g., 5).
"success_rate": successRate, //The percentage of runs that were successful (success_count / total_runs * 100, e.g., 75.0).
"failure_rate": failureRate, //The percentage of runs that failed (failure_count / total_runs * 100, e.g., 15.0).
"cancelled_rate": cancelledRate, //The percentage of runs that were cancelled (cancelled_count / total_runs * 100, e.g., 5.0).
"timed_out_rate": timedOutRate, //The percentage of runs that timed out (timed_out_count / total_runs * 100, e.g., 2.5).
"action_required_rate": actionRequiredRate, //The percentage of runs that required action (action_required_count / total_runs * 100, e.g., 2.5).
"start_time": startTime.Format(time.RFC3339), //The start of the time range for the statistics (e.g., "2023-09-01T00:00:00Z").
"end_time": endTime.Format(time.RFC3339), //The end of the time range for the statistics (e.g., "2023-09-30T23:59:59Z").
})
}
12 changes: 11 additions & 1 deletion pkg/api/middleware.go
Original file line number Diff line number Diff line change
@@ -1,3 +1,13 @@
package api

// Middleware functions for request logging, authentication checks, etc.
import (
"github.com/gin-gonic/gin"
"gorm.io/gorm"
)

func DBMiddleware(db *gorm.DB) gin.HandlerFunc {
return func(c *gin.Context) {
c.Set("db", db)
c.Next()
}
}
3 changes: 3 additions & 0 deletions pkg/api/router.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,9 @@ import (
func StartServer(cfg *config.Config, db *db.Database, githubClient *github.Client, workerPool *worker.WorkerPool) {
r := gin.Default()

// Apply the database middleware
r.Use(DBMiddleware(db.Conn))

// Public routes
r.GET("/login", auth.GitHubLogin)
r.GET("/callback", auth.GitHubCallback)
Expand Down
7 changes: 0 additions & 7 deletions pkg/auth/oauth.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@ import (
"os"

"github.com/gin-gonic/gin"
"github.com/moosh3/github-actions-aggregator/pkg/db"
"github.com/moosh3/github-actions-aggregator/pkg/db/models"
"golang.org/x/oauth2"
"golang.org/x/oauth2/github"
Expand Down Expand Up @@ -54,12 +53,6 @@ func GitHubCallback(c *gin.Context) {
return
}

// Save or update user in database
err = db.SaveUser(user)
if err != nil {
c.AbortWithStatusJSON(http.StatusInternalServerError, gin.H{"error": "Failed to save user"})
return
}
// Set user session (implement setUserSession)
setUserSession(c, user)

Expand Down
2 changes: 1 addition & 1 deletion pkg/worker/worker.go
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ func (wp *WorkerPool) worker(id int) {
for {
select {
case job := <-wp.JobQueue:

log.Printf("Worker %d received job: %v", id, job)
// ...
}
}
Expand Down
1 change: 1 addition & 0 deletions tests/fixtures/api/workflow-[id]-stats/request.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
GET /workflows/123/stats?start_time=2023-09-01T00:00:00Z&end_time=2023-09-30T23:59:59Z
17 changes: 17 additions & 0 deletions tests/fixtures/api/workflow-[id]-stats/response.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
{
"workflow_id": 123,
"workflow_name": "CI Build and Test",
"total_runs": 200,
"success_count": 150,
"failure_count": 30,
"cancelled_count": 10,
"timed_out_count": 5,
"action_required_count": 5,
"success_rate": 75.0,
"failure_rate": 15.0,
"cancelled_rate": 5.0,
"timed_out_rate": 2.5,
"action_required_rate": 2.5,
"start_time": "2023-09-01T00:00:00Z",
"end_time": "2023-09-30T23:59:59Z"
}

0 comments on commit c738d70

Please sign in to comment.