package api import ( "fmt" "io/ioutil" "log" "net/http" "os" "path" "strings" "time" "srs.epita.fr/fic-server/admin/pki" "srs.epita.fr/fic-server/libfic" "github.com/gin-gonic/gin" ) var TimestampCheck = "submissions" func declareHealthRoutes(router *gin.RouterGroup) { router.GET("/timestamps.json", func(c *gin.Context) { stat, err := os.Stat(TimestampCheck) if err != nil { c.AbortWithStatusJSON(http.StatusNotFound, gin.H{"errmsg": fmt.Sprintf("timestamp.json: %s", err.Error())}) return } now := time.Now().UTC() c.JSON(http.StatusOK, gin.H{ "frontend": stat.ModTime().UTC(), "backend": now, "diffFB": now.Sub(stat.ModTime()), }) }) router.GET("/health.json", GetHealth) router.GET("/submissions-stats.json", GetSubmissionsStats) router.GET("/validations-stats.json", GetValidationsStats) router.DELETE("/submissions/*path", func(c *gin.Context) { err := os.Remove(path.Join(TimestampCheck, c.Params.ByName("path"))) if err != nil { c.AbortWithStatusJSON(http.StatusNotFound, gin.H{"errmsg": err.Error()}) return } c.Status(http.StatusOK) }) } type healthFileReport struct { IdTeam string `json:"id_team,omitempty"` Path string `json:"path"` Error string `json:"error"` } func getHealth(pathname string) (ret []healthFileReport) { if ds, err := ioutil.ReadDir(pathname); err != nil { ret = append(ret, healthFileReport{ Path: strings.TrimPrefix(pathname, TimestampCheck), Error: fmt.Sprintf("unable to ReadDir: %s", err), }) return } else { for _, d := range ds { p := path.Join(pathname, d.Name()) if d.IsDir() && d.Name() != ".tmp" && d.Mode()&os.ModeSymlink == 0 { ret = append(ret, getHealth(p)...) } else if !d.IsDir() && d.Mode()&os.ModeSymlink == 0 && time.Since(d.ModTime()) > 2*time.Second { if d.Name() == ".locked" { continue } teamDir := strings.TrimPrefix(pathname, TimestampCheck) idteam, _ := pki.GetAssociation(path.Join(TeamsDir, teamDir)) ret = append(ret, healthFileReport{ IdTeam: idteam, Path: path.Join(teamDir, d.Name()), Error: "existing untreated file", }) } } return } } func GetHealth(c *gin.Context) { if _, err := os.Stat(TimestampCheck); err != nil { c.AbortWithStatusJSON(http.StatusNotFound, gin.H{"errmsg": fmt.Sprintf("health.json: %s", err.Error())}) return } c.JSON(http.StatusOK, getHealth(TimestampCheck)) } type SubmissionsStats struct { NbSubmissionLastMinute uint `json:"nbsubminute"` NbSubmissionLast5Minute uint `json:"nbsub5minute"` NbSubmissionLastQuarter uint `json:"nbsubquarter"` NbSubmissionLastHour uint `json:"nbsubhour"` NbSubmissionLastDay uint `json:"nbsubday"` } func calcSubmissionsStats(tries []time.Time) (stats SubmissionsStats) { lastMinute := time.Now().Add(-1 * time.Minute) last5Minute := time.Now().Add(-5 * time.Minute) lastQuarter := time.Now().Add(-15 * time.Minute) lastHour := time.Now().Add(-1 * time.Hour) lastDay := time.Now().Add(-24 * time.Hour) for _, t := range tries { if lastMinute.Before(t) { stats.NbSubmissionLastMinute += 1 stats.NbSubmissionLast5Minute += 1 stats.NbSubmissionLastQuarter += 1 stats.NbSubmissionLastHour += 1 stats.NbSubmissionLastDay += 1 } else if last5Minute.Before(t) { stats.NbSubmissionLast5Minute += 1 stats.NbSubmissionLastQuarter += 1 stats.NbSubmissionLastHour += 1 stats.NbSubmissionLastDay += 1 } else if lastQuarter.Before(t) { stats.NbSubmissionLastQuarter += 1 stats.NbSubmissionLastHour += 1 stats.NbSubmissionLastDay += 1 } else if lastHour.Before(t) { stats.NbSubmissionLastHour += 1 stats.NbSubmissionLastDay += 1 } else if lastDay.Before(t) { stats.NbSubmissionLastDay += 1 } } return } func GetSubmissionsStats(c *gin.Context) { tries, err := fic.GetTries(nil, nil) if err != nil { log.Println("Unable to GetTries:", err.Error()) c.AbortWithStatusJSON(http.StatusInternalServerError, gin.H{"errmsg": "Unable to retrieves tries."}) return } c.JSON(http.StatusOK, calcSubmissionsStats(tries)) } func GetValidationsStats(c *gin.Context) { tries, err := fic.GetValidations(nil, nil) if err != nil { log.Println("Unable to GetTries:", err.Error()) c.AbortWithStatusJSON(http.StatusInternalServerError, gin.H{"errmsg": "Unable to retrieves tries."}) return } c.JSON(http.StatusOK, calcSubmissionsStats(tries)) }