cairn/internal/handler/dashboard.go

100 lines
2.8 KiB
Go

package handler
import (
"net/http"
"time"
"github.com/gin-gonic/gin"
"github.com/mattnite/cairn/internal/models"
"gorm.io/gorm"
)
type DashboardHandler struct {
DB *gorm.DB
}
type DashboardStats struct {
TotalArtifacts int64 `json:"total_artifacts"`
TotalRepos int64 `json:"total_repos"`
TotalCrashGroups int64 `json:"total_crash_groups"`
OpenCrashGroups int64 `json:"open_crash_groups"`
ActiveCampaigns int64 `json:"active_campaigns"`
}
type TrendPoint struct {
Date string `json:"date"`
Count int64 `json:"count"`
}
type TopCrasher struct {
Title string `json:"title"`
OccurrenceCount uint `json:"occurrence_count"`
RepoName string `json:"repo_name"`
CrashGroupID uint `json:"crash_group_id"`
}
type DashboardResponse struct {
Stats DashboardStats `json:"stats"`
Trend []TrendPoint `json:"trend"`
TopCrashers []TopCrasher `json:"top_crashers"`
}
func (h *DashboardHandler) Stats(c *gin.Context) {
ctx := c.Request.Context()
var stats DashboardStats
_ = h.DB.WithContext(ctx).Model(&models.Artifact{}).Count(&stats.TotalArtifacts).Error
_ = h.DB.WithContext(ctx).Model(&models.Repository{}).Count(&stats.TotalRepos).Error
_ = h.DB.WithContext(ctx).Model(&models.CrashGroup{}).Count(&stats.TotalCrashGroups).Error
_ = h.DB.WithContext(ctx).Model(&models.CrashGroup{}).Where("status = ?", "open").Count(&stats.OpenCrashGroups).Error
_ = h.DB.WithContext(ctx).Model(&models.Campaign{}).Where("status = ?", "running").Count(&stats.ActiveCampaigns).Error
// Artifact trend for the last 30 days.
var trend []TrendPoint
type trendRow struct {
Day time.Time
Count int64
}
var rows []trendRow
err := h.DB.WithContext(ctx).
Table("artifacts").
Select("DATE(created_at) as day, COUNT(*) as count").
Where("created_at >= ?", time.Now().AddDate(0, 0, -30)).
Group("day").
Order("day").
Scan(&rows).Error
if err == nil {
for _, row := range rows {
trend = append(trend, TrendPoint{Date: row.Day.Format("2006-01-02"), Count: row.Count})
}
}
// Top crashers (most frequent open crash groups).
var groups []models.CrashGroup
err = h.DB.WithContext(ctx).Where("status = ?", "open").Order("last_seen_at DESC").Limit(50).Find(&groups).Error
topCrashers := make([]TopCrasher, 0, 10)
if err == nil {
for _, group := range groups {
fullGroup, fullErr := models.GetCrashGroup(ctx, h.DB, group.ID)
if fullErr != nil {
continue
}
topCrashers = append(topCrashers, TopCrasher{
CrashGroupID: fullGroup.ID,
Title: fullGroup.Title,
OccurrenceCount: fullGroup.OccurrenceCount,
RepoName: fullGroup.RepoName,
})
if len(topCrashers) == 10 {
break
}
}
}
c.JSON(http.StatusOK, DashboardResponse{
Stats: stats,
Trend: trend,
TopCrashers: topCrashers,
})
}