server: Implement /api/history/week

Luther Wen Xu 2020-04-23 21:44:23 +07:00
parent 6d5d07e2e5
commit 84501beb23
Signed by: chanbakjsd
GPG Key ID: B7D77E3E9D102B70
4 changed files with 89 additions and 6 deletions

@ -39,3 +39,17 @@ func dayHistory(w http.ResponseWriter, req *http.Request) {
entries := db.GetFromDB(keys[0], time.Now().Add(time.Duration(-24)*time.Hour), time.Now()) entries := db.GetFromDB(keys[0], time.Now().Add(time.Duration(-24)*time.Hour), time.Now())
writeJSON(w, entries) writeJSON(w, entries)
} }
func weekHistory(w http.ResponseWriter, req *http.Request) {
keys, ok := req.URL.Query()["service_name"]
if !ok || len(keys) == 0 || len(keys[0]) < 1 {
http.Error(w, "`service_name` not provided", http.StatusBadRequest)
return
}
if len(keys) >= 2 {
http.Error(w, "Only one `service_name` allowed", http.StatusBadRequest)
return
}
entries := getWeek(keys[0])
writeJSON(w, entries)
}

@ -3,17 +3,54 @@ package server
import ( import (
"time" "time"
"status/check"
"status/db" "status/db"
) )
func getStatus() map[string]db.PingEntry { type stat struct {
entries := db.GetFromDB("", time.Now().Add(time.Duration(-2)*time.Minute), time.Now()) StartTime time.Time `json:"start_time"`
result := make(map[string]db.PingEntry) TotalPing int64 `json:"total_ping"`
SampleCount int `json:"sample_count"`
SuccessCount int `json:"success_count"`
FailCount int `json:"fail_count"`
Summary check.Result `json:"summary"`
}
var dayAggregation map[string]map[time.Time]stat
func convertToResult(successCount, totalCount int) check.Result {
if successCount >= totalCount*99/100 {
return check.Online
}
if successCount >= totalCount*9/10 {
return check.Unstable
}
return check.Offline
}
func getDay(serviceName string, day time.Time) stat {
if cached, ok := dayAggregation[serviceName][day]; ok {
return cached
}
entries := db.GetFromDB(serviceName, day.AddDate(0, 0, -1), day)
result := stat{
StartTime: day,
}
for _, v := range entries { for _, v := range entries {
if v.Time.Before(result[v.ServiceName].Time) { result.SampleCount++
continue result.TotalPing += v.Ping
switch v.Status {
case check.Online:
result.SuccessCount++
case check.Offline:
result.FailCount++
} }
result[v.ServiceName] = v
} }
result.Summary = convertToResult(result.SuccessCount, result.SampleCount)
return result return result
} }
func today() time.Time {
now := time.Now()
return time.Date(now.Year(), now.Month(), now.Day(), 0, 0, 0, 0, time.UTC)
}

@ -0,0 +1,31 @@
package server
import (
"time"
"status/db"
)
func getStatus() map[string]db.PingEntry {
entries := db.GetFromDB("", time.Now().Add(time.Duration(-2)*time.Minute), time.Now())
result := make(map[string]db.PingEntry)
for _, v := range entries {
if v.Time.Before(result[v.ServiceName].Time) {
continue
}
result[v.ServiceName] = v
}
return result
}
func getWeek(serviceName string) []stat {
currentDay := today()
result := make([]stat, 0)
for i := -6; i <= 0; i++ {
dayData := getDay(serviceName, currentDay.AddDate(0, 0, i))
if dayData.SampleCount > 0 {
result = append(result, dayData)
}
}
return result
}

@ -9,6 +9,7 @@ import (
func apiEndpoints() { func apiEndpoints() {
http.HandleFunc("/api/latest", allStatus) http.HandleFunc("/api/latest", allStatus)
http.HandleFunc("/api/history/day", dayHistory) http.HandleFunc("/api/history/day", dayHistory)
http.HandleFunc("/api/history/week", weekHistory)
} }
func StartServer(port int) { func StartServer(port int) {