Remove Uptime.Last* parameters

This commit is contained in:
TwinProduction
2021-08-13 01:25:50 -04:00
committed by Chris
parent 0b6fc6b520
commit d65cebb1fb
15 changed files with 48 additions and 173 deletions
+10 -2
View File
@@ -138,20 +138,28 @@ func serviceStatusesHandler(writer http.ResponseWriter, r *http.Request) {
func serviceStatusHandler(writer http.ResponseWriter, r *http.Request) { func serviceStatusHandler(writer http.ResponseWriter, r *http.Request) {
page, pageSize := extractPageAndPageSizeFromRequest(r) page, pageSize := extractPageAndPageSizeFromRequest(r)
vars := mux.Vars(r) vars := mux.Vars(r)
serviceStatus := storage.Get().GetServiceStatusByKey(vars["key"], paging.NewServiceStatusParams().WithResults(page, pageSize).WithEvents(1, common.MaximumNumberOfEvents).WithUptime()) serviceStatus := storage.Get().GetServiceStatusByKey(vars["key"], paging.NewServiceStatusParams().WithResults(page, pageSize).WithEvents(1, common.MaximumNumberOfEvents))
if serviceStatus == nil { if serviceStatus == nil {
log.Printf("[controller][serviceStatusHandler] Service with key=%s not found", vars["key"]) log.Printf("[controller][serviceStatusHandler] Service with key=%s not found", vars["key"])
writer.WriteHeader(http.StatusNotFound) writer.WriteHeader(http.StatusNotFound)
_, _ = writer.Write([]byte("not found")) _, _ = writer.Write([]byte("not found"))
return return
} }
uptime7Days, _ := storage.Get().GetUptimeByKey(vars["key"], time.Now().Add(-time.Hour*24*7), time.Now())
uptime24Hours, _ := storage.Get().GetUptimeByKey(vars["key"], time.Now().Add(-time.Hour*24), time.Now())
uptime1Hour, _ := storage.Get().GetUptimeByKey(vars["key"], time.Now().Add(-time.Hour), time.Now())
data := map[string]interface{}{ data := map[string]interface{}{
"serviceStatus": serviceStatus, "serviceStatus": serviceStatus,
// The following fields, while present on core.ServiceStatus, are annotated to remain hidden so that we can // The following fields, while present on core.ServiceStatus, are annotated to remain hidden so that we can
// expose only the necessary data on /api/v1/statuses. // expose only the necessary data on /api/v1/statuses.
// Since the /api/v1/statuses/{key} endpoint does need this data, however, we explicitly expose it here // Since the /api/v1/statuses/{key} endpoint does need this data, however, we explicitly expose it here
"events": serviceStatus.Events, "events": serviceStatus.Events,
"uptime": serviceStatus.Uptime, // TODO: remove this in v3.0.0. Not used by front-end, only used for API. Left here for v2.x.x backward compatibility
"uptime": map[string]float64{
"7d": uptime7Days,
"24h": uptime24Hours,
"1h": uptime1Hour,
},
} }
output, err := json.Marshal(data) output, err := json.Marshal(data)
if err != nil { if err != nil {
-4
View File
@@ -3,10 +3,6 @@ package core
// Uptime is the struct that contains the relevant data for calculating the uptime as well as the uptime itself // Uptime is the struct that contains the relevant data for calculating the uptime as well as the uptime itself
// and some other statistics // and some other statistics
type Uptime struct { type Uptime struct {
LastSevenDays float64 `json:"7d"` // Uptime percentage over the past 7 days
LastTwentyFourHours float64 `json:"24h"` // Uptime percentage over the past 24 hours
LastHour float64 `json:"1h"` // Uptime percentage over the past hour
// SuccessfulExecutionsPerHour is a map containing the number of successes (value) // SuccessfulExecutionsPerHour is a map containing the number of successes (value)
// for every hourly unix timestamps (key) // for every hourly unix timestamps (key)
// Deprecated // Deprecated
+4 -11
View File
@@ -2,11 +2,10 @@ package paging
// ServiceStatusParams represents all parameters that can be used for paging purposes // ServiceStatusParams represents all parameters that can be used for paging purposes
type ServiceStatusParams struct { type ServiceStatusParams struct {
EventsPage int // Number of the event page EventsPage int // Number of the event page
EventsPageSize int // Size of the event page EventsPageSize int // Size of the event page
ResultsPage int // Number of the result page ResultsPage int // Number of the result page
ResultsPageSize int // Size of the result page ResultsPageSize int // Size of the result page
IncludeUptime bool // Whether to include uptime data
} }
// NewServiceStatusParams creates a new ServiceStatusParams // NewServiceStatusParams creates a new ServiceStatusParams
@@ -27,9 +26,3 @@ func (params *ServiceStatusParams) WithResults(page, pageSize int) *ServiceStatu
params.ResultsPageSize = pageSize params.ResultsPageSize = pageSize
return params return params
} }
// WithUptime sets the value IncludeUptime to true
func (params *ServiceStatusParams) WithUptime() *ServiceStatusParams {
params.IncludeUptime = true
return params
}
+2 -11
View File
@@ -10,7 +10,6 @@ func TestNewServiceStatusParams(t *testing.T) {
ExpectedEventsPageSize int ExpectedEventsPageSize int
ExpectedResultsPage int ExpectedResultsPage int
ExpectedResultsPageSize int ExpectedResultsPageSize int
ExpectedIncludeUptime bool
} }
scenarios := []Scenario{ scenarios := []Scenario{
{ {
@@ -20,7 +19,6 @@ func TestNewServiceStatusParams(t *testing.T) {
ExpectedEventsPageSize: 0, ExpectedEventsPageSize: 0,
ExpectedResultsPage: 0, ExpectedResultsPage: 0,
ExpectedResultsPageSize: 0, ExpectedResultsPageSize: 0,
ExpectedIncludeUptime: false,
}, },
{ {
Name: "with-events-page-2-size-7", Name: "with-events-page-2-size-7",
@@ -29,25 +27,22 @@ func TestNewServiceStatusParams(t *testing.T) {
ExpectedEventsPageSize: 7, ExpectedEventsPageSize: 7,
ExpectedResultsPage: 0, ExpectedResultsPage: 0,
ExpectedResultsPageSize: 0, ExpectedResultsPageSize: 0,
ExpectedIncludeUptime: false,
}, },
{ {
Name: "with-events-page-4-size-3-uptime", Name: "with-events-page-4-size-3-uptime",
Params: NewServiceStatusParams().WithEvents(4, 3).WithUptime(), Params: NewServiceStatusParams().WithEvents(4, 3),
ExpectedEventsPage: 4, ExpectedEventsPage: 4,
ExpectedEventsPageSize: 3, ExpectedEventsPageSize: 3,
ExpectedResultsPage: 0, ExpectedResultsPage: 0,
ExpectedResultsPageSize: 0, ExpectedResultsPageSize: 0,
ExpectedIncludeUptime: true,
}, },
{ {
Name: "with-results-page-1-size-20-uptime", Name: "with-results-page-1-size-20-uptime",
Params: NewServiceStatusParams().WithResults(1, 20).WithUptime(), Params: NewServiceStatusParams().WithResults(1, 20),
ExpectedEventsPage: 0, ExpectedEventsPage: 0,
ExpectedEventsPageSize: 0, ExpectedEventsPageSize: 0,
ExpectedResultsPage: 1, ExpectedResultsPage: 1,
ExpectedResultsPageSize: 20, ExpectedResultsPageSize: 20,
ExpectedIncludeUptime: true,
}, },
{ {
Name: "with-results-page-2-size-10-events-page-3-size-50", Name: "with-results-page-2-size-10-events-page-3-size-50",
@@ -56,7 +51,6 @@ func TestNewServiceStatusParams(t *testing.T) {
ExpectedEventsPageSize: 50, ExpectedEventsPageSize: 50,
ExpectedResultsPage: 2, ExpectedResultsPage: 2,
ExpectedResultsPageSize: 10, ExpectedResultsPageSize: 10,
ExpectedIncludeUptime: false,
}, },
} }
for _, scenario := range scenarios { for _, scenario := range scenarios {
@@ -73,9 +67,6 @@ func TestNewServiceStatusParams(t *testing.T) {
if scenario.Params.ResultsPageSize != scenario.ExpectedResultsPageSize { if scenario.Params.ResultsPageSize != scenario.ExpectedResultsPageSize {
t.Errorf("expected ResultsPageSize to be %d, was %d", scenario.ExpectedResultsPageSize, scenario.Params.ResultsPageSize) t.Errorf("expected ResultsPageSize to be %d, was %d", scenario.ExpectedResultsPageSize, scenario.Params.ResultsPageSize)
} }
if scenario.Params.IncludeUptime != scenario.ExpectedIncludeUptime {
t.Errorf("expected IncludeUptime to be %v, was %v", scenario.ExpectedIncludeUptime, scenario.Params.IncludeUptime)
}
}) })
} }
} }
-51
View File
@@ -45,57 +45,6 @@ func processUptimeAfterResult(uptime *core.Uptime, result *core.Result) {
} }
} }
} }
if result.Success {
// Recalculate uptime if at least one of the 1h, 24h or 7d uptime are not 100%
// If they're all 100%, then recalculating the uptime would be useless unless
// the result added was a failure (!result.Success)
if uptime.LastSevenDays != 1 || uptime.LastTwentyFourHours != 1 || uptime.LastHour != 1 {
recalculateUptime(uptime)
}
} else {
// Recalculate uptime if at least one of the 1h, 24h or 7d uptime are not 0%
// If they're all 0%, then recalculating the uptime would be useless unless
// the result added was a success (result.Success)
if uptime.LastSevenDays != 0 || uptime.LastTwentyFourHours != 0 || uptime.LastHour != 0 {
recalculateUptime(uptime)
}
}
}
// recalculateUptime calculates the uptime over the past 7 days, 24 hours and 1 hour.
func recalculateUptime(uptime *core.Uptime) {
uptimeBrackets := make(map[string]uint64)
now := time.Now()
// The oldest uptime bracket starts 7 days ago, so we'll start from there
timestamp := now.Add(-sevenDays)
for now.Sub(timestamp) >= 0 {
hourlyUnixTimestamp := timestamp.Truncate(time.Hour).Unix()
hourlyStats := uptime.HourlyStatistics[hourlyUnixTimestamp]
if hourlyStats == nil || hourlyStats.TotalExecutions == 0 {
timestamp = timestamp.Add(time.Hour)
continue
}
uptimeBrackets["7d_success"] += hourlyStats.SuccessfulExecutions
uptimeBrackets["7d_total"] += hourlyStats.TotalExecutions
if now.Sub(timestamp) <= 24*time.Hour {
uptimeBrackets["24h_success"] += hourlyStats.SuccessfulExecutions
uptimeBrackets["24h_total"] += hourlyStats.TotalExecutions
}
if now.Sub(timestamp) <= time.Hour {
uptimeBrackets["1h_success"] += hourlyStats.SuccessfulExecutions
uptimeBrackets["1h_total"] += hourlyStats.TotalExecutions
}
timestamp = timestamp.Add(time.Hour)
}
if uptimeBrackets["7d_total"] > 0 {
uptime.LastSevenDays = float64(uptimeBrackets["7d_success"]) / float64(uptimeBrackets["7d_total"])
}
if uptimeBrackets["24h_total"] > 0 {
uptime.LastTwentyFourHours = float64(uptimeBrackets["24h_success"]) / float64(uptimeBrackets["24h_total"])
}
if uptimeBrackets["1h_total"] > 0 {
uptime.LastHour = float64(uptimeBrackets["1h_success"]) / float64(uptimeBrackets["1h_total"])
}
} }
// XXX: Remove this on v3.0.0 // XXX: Remove this on v3.0.0
-26
View File
@@ -12,22 +12,16 @@ func TestProcessUptimeAfterResult(t *testing.T) {
serviceStatus := core.NewServiceStatus(service.Key(), service.Group, service.Name) serviceStatus := core.NewServiceStatus(service.Key(), service.Group, service.Name)
uptime := serviceStatus.Uptime uptime := serviceStatus.Uptime
checkUptimes(t, serviceStatus, 0.00, 0.00, 0.00)
now := time.Now() now := time.Now()
now = time.Date(now.Year(), now.Month(), now.Day(), now.Hour(), 0, 0, 0, now.Location()) now = time.Date(now.Year(), now.Month(), now.Day(), now.Hour(), 0, 0, 0, now.Location())
processUptimeAfterResult(uptime, &core.Result{Timestamp: now.Add(-7 * 24 * time.Hour), Success: true}) processUptimeAfterResult(uptime, &core.Result{Timestamp: now.Add(-7 * 24 * time.Hour), Success: true})
checkUptimes(t, serviceStatus, 1.00, 0.00, 0.00)
processUptimeAfterResult(uptime, &core.Result{Timestamp: now.Add(-6 * 24 * time.Hour), Success: false}) processUptimeAfterResult(uptime, &core.Result{Timestamp: now.Add(-6 * 24 * time.Hour), Success: false})
checkUptimes(t, serviceStatus, 0.50, 0.00, 0.00)
processUptimeAfterResult(uptime, &core.Result{Timestamp: now.Add(-8 * 24 * time.Hour), Success: true}) processUptimeAfterResult(uptime, &core.Result{Timestamp: now.Add(-8 * 24 * time.Hour), Success: true})
checkUptimes(t, serviceStatus, 0.50, 0.00, 0.00)
processUptimeAfterResult(uptime, &core.Result{Timestamp: now.Add(-24 * time.Hour), Success: true}) processUptimeAfterResult(uptime, &core.Result{Timestamp: now.Add(-24 * time.Hour), Success: true})
processUptimeAfterResult(uptime, &core.Result{Timestamp: now.Add(-12 * time.Hour), Success: true}) processUptimeAfterResult(uptime, &core.Result{Timestamp: now.Add(-12 * time.Hour), Success: true})
checkUptimes(t, serviceStatus, 0.75, 1.00, 0.00)
processUptimeAfterResult(uptime, &core.Result{Timestamp: now.Add(-1 * time.Hour), Success: true, Duration: 10 * time.Millisecond}) processUptimeAfterResult(uptime, &core.Result{Timestamp: now.Add(-1 * time.Hour), Success: true, Duration: 10 * time.Millisecond})
checkHourlyStatistics(t, uptime.HourlyStatistics[now.Unix()-now.Unix()%3600-3600], 10, 1, 1) checkHourlyStatistics(t, uptime.HourlyStatistics[now.Unix()-now.Unix()%3600-3600], 10, 1, 1)
@@ -37,7 +31,6 @@ func TestProcessUptimeAfterResult(t *testing.T) {
checkHourlyStatistics(t, uptime.HourlyStatistics[now.Unix()-now.Unix()%3600-3600], 535, 3, 1) checkHourlyStatistics(t, uptime.HourlyStatistics[now.Unix()-now.Unix()%3600-3600], 535, 3, 1)
processUptimeAfterResult(uptime, &core.Result{Timestamp: now.Add(-10 * time.Minute), Success: false}) processUptimeAfterResult(uptime, &core.Result{Timestamp: now.Add(-10 * time.Minute), Success: false})
checkUptimes(t, serviceStatus, 0.50, 0.50, 0.25)
processUptimeAfterResult(uptime, &core.Result{Timestamp: now.Add(-120 * time.Hour), Success: true}) processUptimeAfterResult(uptime, &core.Result{Timestamp: now.Add(-120 * time.Hour), Success: true})
processUptimeAfterResult(uptime, &core.Result{Timestamp: now.Add(-119 * time.Hour), Success: true}) processUptimeAfterResult(uptime, &core.Result{Timestamp: now.Add(-119 * time.Hour), Success: true})
@@ -47,7 +40,6 @@ func TestProcessUptimeAfterResult(t *testing.T) {
processUptimeAfterResult(uptime, &core.Result{Timestamp: now.Add(-8 * time.Hour), Success: true}) processUptimeAfterResult(uptime, &core.Result{Timestamp: now.Add(-8 * time.Hour), Success: true})
processUptimeAfterResult(uptime, &core.Result{Timestamp: now.Add(-30 * time.Minute), Success: true}) processUptimeAfterResult(uptime, &core.Result{Timestamp: now.Add(-30 * time.Minute), Success: true})
processUptimeAfterResult(uptime, &core.Result{Timestamp: now.Add(-25 * time.Minute), Success: true}) processUptimeAfterResult(uptime, &core.Result{Timestamp: now.Add(-25 * time.Minute), Success: true})
checkUptimes(t, serviceStatus, 0.75, 0.70, 0.50)
} }
func TestAddResultUptimeIsCleaningUpAfterItself(t *testing.T) { func TestAddResultUptimeIsCleaningUpAfterItself(t *testing.T) {
@@ -62,29 +54,11 @@ func TestAddResultUptimeIsCleaningUpAfterItself(t *testing.T) {
if len(serviceStatus.Uptime.HourlyStatistics) > numberOfHoursInTenDays { if len(serviceStatus.Uptime.HourlyStatistics) > numberOfHoursInTenDays {
t.Errorf("At no point in time should there be more than %d entries in serviceStatus.SuccessfulExecutionsPerHour, but there are %d", numberOfHoursInTenDays, len(serviceStatus.Uptime.HourlyStatistics)) t.Errorf("At no point in time should there be more than %d entries in serviceStatus.SuccessfulExecutionsPerHour, but there are %d", numberOfHoursInTenDays, len(serviceStatus.Uptime.HourlyStatistics))
} }
if now.Sub(timestamp) > time.Hour && serviceStatus.Uptime.LastHour != 0 {
t.Error("most recent timestamp > 1h ago, expected serviceStatus.Uptime.LastHour to be 0, got", serviceStatus.Uptime.LastHour)
}
if now.Sub(timestamp) < time.Hour && serviceStatus.Uptime.LastHour == 0 {
t.Error("most recent timestamp < 1h ago, expected serviceStatus.Uptime.LastHour to NOT be 0, got", serviceStatus.Uptime.LastHour)
}
// Simulate service with an interval of 3 minutes // Simulate service with an interval of 3 minutes
timestamp = timestamp.Add(3 * time.Minute) timestamp = timestamp.Add(3 * time.Minute)
} }
} }
func checkUptimes(t *testing.T, status *core.ServiceStatus, expectedUptimeDuringLastSevenDays, expectedUptimeDuringLastTwentyFourHours, expectedUptimeDuringLastHour float64) {
if status.Uptime.LastSevenDays != expectedUptimeDuringLastSevenDays {
t.Errorf("expected status.Uptime.LastSevenDays to be %f, got %f", expectedUptimeDuringLastHour, status.Uptime.LastSevenDays)
}
if status.Uptime.LastTwentyFourHours != expectedUptimeDuringLastTwentyFourHours {
t.Errorf("expected status.Uptime.LastTwentyFourHours to be %f, got %f", expectedUptimeDuringLastTwentyFourHours, status.Uptime.LastTwentyFourHours)
}
if status.Uptime.LastHour != expectedUptimeDuringLastHour {
t.Errorf("expected status.Uptime.LastHour to be %f, got %f", expectedUptimeDuringLastHour, status.Uptime.LastHour)
}
}
func checkHourlyStatistics(t *testing.T, hourlyUptimeStatistics *core.HourlyUptimeStatistics, expectedTotalExecutionsResponseTime uint64, expectedTotalExecutions uint64, expectedSuccessfulExecutions uint64) { func checkHourlyStatistics(t *testing.T, hourlyUptimeStatistics *core.HourlyUptimeStatistics, expectedTotalExecutionsResponseTime uint64, expectedTotalExecutions uint64, expectedSuccessfulExecutions uint64) {
if hourlyUptimeStatistics.TotalExecutionsResponseTime != expectedTotalExecutionsResponseTime { if hourlyUptimeStatistics.TotalExecutionsResponseTime != expectedTotalExecutionsResponseTime {
t.Error("TotalExecutionsResponseTime should've been", expectedTotalExecutionsResponseTime, "got", hourlyUptimeStatistics.TotalExecutionsResponseTime) t.Error("TotalExecutionsResponseTime should've been", expectedTotalExecutionsResponseTime, "got", hourlyUptimeStatistics.TotalExecutionsResponseTime)
-5
View File
@@ -29,11 +29,6 @@ func ShallowCopyServiceStatus(ss *core.ServiceStatus, params *paging.ServiceStat
} else { } else {
shallowCopy.Events = ss.Events[eventsStart:eventsEnd] shallowCopy.Events = ss.Events[eventsStart:eventsEnd]
} }
if params.IncludeUptime {
shallowCopy.Uptime.LastHour = ss.Uptime.LastHour
shallowCopy.Uptime.LastTwentyFourHours = ss.Uptime.LastTwentyFourHours
shallowCopy.Uptime.LastSevenDays = ss.Uptime.LastSevenDays
}
return shallowCopy return shallowCopy
} }
-14
View File
@@ -63,18 +63,4 @@ func TestShallowCopyServiceStatus(t *testing.T) {
if len(ShallowCopyServiceStatus(serviceStatus, paging.NewServiceStatusParams().WithResults(1, 50)).Results) != 25 { if len(ShallowCopyServiceStatus(serviceStatus, paging.NewServiceStatusParams().WithResults(1, 50)).Results) != 25 {
t.Error("expected to have 25 results, because there's only 25 results") t.Error("expected to have 25 results, because there's only 25 results")
} }
uptime := ShallowCopyServiceStatus(serviceStatus, paging.NewServiceStatusParams().WithUptime()).Uptime
if uptime == nil {
t.Error("expected uptime to not be nil")
} else {
if uptime.LastHour != 1 {
t.Error("expected uptime.LastHour to not be 1, got", uptime.LastHour)
}
if uptime.LastTwentyFourHours != 0.5 {
t.Error("expected uptime.LastTwentyFourHours to not be 0.5, got", uptime.LastTwentyFourHours)
}
if uptime.LastSevenDays != 0.52 {
t.Error("expected uptime.LastSevenDays to not be 0.52, got", uptime.LastSevenDays)
}
}
} }
+6 -6
View File
@@ -501,12 +501,12 @@ func (s *Store) getServiceStatusByKey(tx *sql.Tx, key string, parameters *paging
log.Printf("[sqlite][getServiceStatusByKey] Failed to retrieve results for key=%s: %s", key, err.Error()) log.Printf("[sqlite][getServiceStatusByKey] Failed to retrieve results for key=%s: %s", key, err.Error())
} }
} }
if parameters.IncludeUptime { //if parameters.IncludeUptime {
now := time.Now() // now := time.Now()
serviceStatus.Uptime.LastHour, _, err = s.getServiceUptime(tx, serviceID, now.Add(-time.Hour), now) // serviceStatus.Uptime.LastHour, _, err = s.getServiceUptime(tx, serviceID, now.Add(-time.Hour), now)
serviceStatus.Uptime.LastTwentyFourHours, _, err = s.getServiceUptime(tx, serviceID, now.Add(-24*time.Hour), now) // serviceStatus.Uptime.LastTwentyFourHours, _, err = s.getServiceUptime(tx, serviceID, now.Add(-24*time.Hour), now)
serviceStatus.Uptime.LastSevenDays, _, err = s.getServiceUptime(tx, serviceID, now.Add(-7*24*time.Hour), now) // serviceStatus.Uptime.LastSevenDays, _, err = s.getServiceUptime(tx, serviceID, now.Add(-7*24*time.Hour), now)
} //}
return serviceStatus, nil return serviceStatus, nil
} }
+13 -4
View File
@@ -174,16 +174,25 @@ func TestStore_Persistence(t *testing.T) {
store, _ := NewStore("sqlite", file) store, _ := NewStore("sqlite", file)
store.Insert(&testService, &testSuccessfulResult) store.Insert(&testService, &testSuccessfulResult)
store.Insert(&testService, &testUnsuccessfulResult) store.Insert(&testService, &testUnsuccessfulResult)
ssFromOldStore := store.GetServiceStatus(testService.Group, testService.Name, paging.NewServiceStatusParams().WithResults(1, common.MaximumNumberOfResults).WithEvents(1, common.MaximumNumberOfEvents).WithUptime()) if uptime, _ := store.GetUptimeByKey(testService.Key(), time.Now().Add(-time.Hour), time.Now()); uptime != 0.5 {
if ssFromOldStore == nil || ssFromOldStore.Group != "group" || ssFromOldStore.Name != "name" || len(ssFromOldStore.Events) != 3 || len(ssFromOldStore.Results) != 2 || ssFromOldStore.Uptime.LastHour != 0.5 || ssFromOldStore.Uptime.LastTwentyFourHours != 0.5 || ssFromOldStore.Uptime.LastSevenDays != 0.5 { t.Errorf("the uptime over the past 1h should've been 0.5, got %f", uptime)
}
if uptime, _ := store.GetUptimeByKey(testService.Key(), time.Now().Add(-time.Hour*24), time.Now()); uptime != 0.5 {
t.Errorf("the uptime over the past 24h should've been 0.5, got %f", uptime)
}
if uptime, _ := store.GetUptimeByKey(testService.Key(), time.Now().Add(-time.Hour*24*7), time.Now()); uptime != 0.5 {
t.Errorf("the uptime over the past 7d should've been 0.5, got %f", uptime)
}
ssFromOldStore := store.GetServiceStatus(testService.Group, testService.Name, paging.NewServiceStatusParams().WithResults(1, common.MaximumNumberOfResults).WithEvents(1, common.MaximumNumberOfEvents))
if ssFromOldStore == nil || ssFromOldStore.Group != "group" || ssFromOldStore.Name != "name" || len(ssFromOldStore.Events) != 3 || len(ssFromOldStore.Results) != 2 {
store.Close() store.Close()
t.Fatal("sanity check failed") t.Fatal("sanity check failed")
} }
store.Close() store.Close()
store, _ = NewStore("sqlite", file) store, _ = NewStore("sqlite", file)
defer store.Close() defer store.Close()
ssFromNewStore := store.GetServiceStatus(testService.Group, testService.Name, paging.NewServiceStatusParams().WithResults(1, common.MaximumNumberOfResults).WithEvents(1, common.MaximumNumberOfEvents).WithUptime()) ssFromNewStore := store.GetServiceStatus(testService.Group, testService.Name, paging.NewServiceStatusParams().WithResults(1, common.MaximumNumberOfResults).WithEvents(1, common.MaximumNumberOfEvents))
if ssFromNewStore == nil || ssFromNewStore.Group != "group" || ssFromNewStore.Name != "name" || len(ssFromNewStore.Events) != 3 || len(ssFromNewStore.Results) != 2 || ssFromNewStore.Uptime.LastHour != 0.5 || ssFromNewStore.Uptime.LastTwentyFourHours != 0.5 || ssFromNewStore.Uptime.LastSevenDays != 0.5 { if ssFromNewStore == nil || ssFromNewStore.Group != "group" || ssFromNewStore.Name != "name" || len(ssFromNewStore.Events) != 3 || len(ssFromNewStore.Results) != 2 {
t.Fatal("failed sanity check") t.Fatal("failed sanity check")
} }
if ssFromNewStore == ssFromOldStore { if ssFromNewStore == ssFromOldStore {
+5 -17
View File
@@ -127,7 +127,7 @@ func TestStore_GetServiceStatusByKey(t *testing.T) {
scenario.Store.Insert(&testService, &firstResult) scenario.Store.Insert(&testService, &firstResult)
scenario.Store.Insert(&testService, &secondResult) scenario.Store.Insert(&testService, &secondResult)
serviceStatus := scenario.Store.GetServiceStatusByKey(testService.Key(), paging.NewServiceStatusParams().WithEvents(1, common.MaximumNumberOfEvents).WithResults(1, common.MaximumNumberOfResults).WithUptime()) serviceStatus := scenario.Store.GetServiceStatusByKey(testService.Key(), paging.NewServiceStatusParams().WithEvents(1, common.MaximumNumberOfEvents).WithResults(1, common.MaximumNumberOfResults))
if serviceStatus == nil { if serviceStatus == nil {
t.Fatalf("serviceStatus shouldn't have been nil") t.Fatalf("serviceStatus shouldn't have been nil")
} }
@@ -143,18 +143,6 @@ func TestStore_GetServiceStatusByKey(t *testing.T) {
if serviceStatus.Results[0].Timestamp.After(serviceStatus.Results[1].Timestamp) { if serviceStatus.Results[0].Timestamp.After(serviceStatus.Results[1].Timestamp) {
t.Error("The result at index 0 should've been older than the result at index 1") t.Error("The result at index 0 should've been older than the result at index 1")
} }
if serviceStatus.Uptime == nil {
t.Fatalf("serviceStatus.Uptime shouldn't have been nil")
}
if serviceStatus.Uptime.LastHour != 0.5 {
t.Errorf("serviceStatus.Uptime.LastHour should've been 0.5, got %f", serviceStatus.Uptime.LastHour)
}
if serviceStatus.Uptime.LastTwentyFourHours != 0.5 {
t.Errorf("serviceStatus.Uptime.LastTwentyFourHours should've been 0.5, got %f", serviceStatus.Uptime.LastTwentyFourHours)
}
if serviceStatus.Uptime.LastSevenDays != 0.5 {
t.Errorf("serviceStatus.Uptime.LastSevenDays should've been 0.5, got %f", serviceStatus.Uptime.LastSevenDays)
}
scenario.Store.Clear() scenario.Store.Clear()
}) })
} }
@@ -166,15 +154,15 @@ func TestStore_GetServiceStatusForMissingStatusReturnsNil(t *testing.T) {
for _, scenario := range scenarios { for _, scenario := range scenarios {
t.Run(scenario.Name, func(t *testing.T) { t.Run(scenario.Name, func(t *testing.T) {
scenario.Store.Insert(&testService, &testSuccessfulResult) scenario.Store.Insert(&testService, &testSuccessfulResult)
serviceStatus := scenario.Store.GetServiceStatus("nonexistantgroup", "nonexistantname", paging.NewServiceStatusParams().WithEvents(1, common.MaximumNumberOfEvents).WithResults(1, common.MaximumNumberOfResults).WithUptime()) serviceStatus := scenario.Store.GetServiceStatus("nonexistantgroup", "nonexistantname", paging.NewServiceStatusParams().WithEvents(1, common.MaximumNumberOfEvents).WithResults(1, common.MaximumNumberOfResults))
if serviceStatus != nil { if serviceStatus != nil {
t.Errorf("Returned service status for group '%s' and name '%s' not nil after inserting the service into the store", testService.Group, testService.Name) t.Errorf("Returned service status for group '%s' and name '%s' not nil after inserting the service into the store", testService.Group, testService.Name)
} }
serviceStatus = scenario.Store.GetServiceStatus(testService.Group, "nonexistantname", paging.NewServiceStatusParams().WithEvents(1, common.MaximumNumberOfEvents).WithResults(1, common.MaximumNumberOfResults).WithUptime()) serviceStatus = scenario.Store.GetServiceStatus(testService.Group, "nonexistantname", paging.NewServiceStatusParams().WithEvents(1, common.MaximumNumberOfEvents).WithResults(1, common.MaximumNumberOfResults))
if serviceStatus != nil { if serviceStatus != nil {
t.Errorf("Returned service status for group '%s' and name '%s' not nil after inserting the service into the store", testService.Group, "nonexistantname") t.Errorf("Returned service status for group '%s' and name '%s' not nil after inserting the service into the store", testService.Group, "nonexistantname")
} }
serviceStatus = scenario.Store.GetServiceStatus("nonexistantgroup", testService.Name, paging.NewServiceStatusParams().WithEvents(1, common.MaximumNumberOfEvents).WithResults(1, common.MaximumNumberOfResults).WithUptime()) serviceStatus = scenario.Store.GetServiceStatus("nonexistantgroup", testService.Name, paging.NewServiceStatusParams().WithEvents(1, common.MaximumNumberOfEvents).WithResults(1, common.MaximumNumberOfResults))
if serviceStatus != nil { if serviceStatus != nil {
t.Errorf("Returned service status for group '%s' and name '%s' not nil after inserting the service into the store", "nonexistantgroup", testService.Name) t.Errorf("Returned service status for group '%s' and name '%s' not nil after inserting the service into the store", "nonexistantgroup", testService.Name)
} }
@@ -316,7 +304,7 @@ func TestStore_Insert(t *testing.T) {
scenario.Store.Insert(&testService, &testSuccessfulResult) scenario.Store.Insert(&testService, &testSuccessfulResult)
scenario.Store.Insert(&testService, &testUnsuccessfulResult) scenario.Store.Insert(&testService, &testUnsuccessfulResult)
ss := scenario.Store.GetServiceStatusByKey(testService.Key(), paging.NewServiceStatusParams().WithEvents(1, common.MaximumNumberOfEvents).WithResults(1, common.MaximumNumberOfResults).WithUptime()) ss := scenario.Store.GetServiceStatusByKey(testService.Key(), paging.NewServiceStatusParams().WithEvents(1, common.MaximumNumberOfEvents).WithResults(1, common.MaximumNumberOfResults))
if ss == nil { if ss == nil {
t.Fatalf("Store should've had key '%s', but didn't", testService.Key()) t.Fatalf("Store should've had key '%s', but didn't", testService.Key())
} }
+5 -19
View File
@@ -14,33 +14,20 @@
/> />
<Pagination @page="changePage"/> <Pagination @page="changePage"/>
</slot> </slot>
<div v-if="uptime" class="mt-12"> <div class="mt-12">
<h1 class="text-xl xl:text-3xl font-mono text-gray-400">UPTIME</h1> <h1 class="text-xl xl:text-3xl font-mono text-gray-400">UPTIME</h1>
<hr /> <hr />
<div class="flex space-x-4 text-center text-xl xl:text-2xl mt-3"> <div v-if="serviceStatus && serviceStatus.key" class="flex space-x-4 text-center text-2xl mt-6 relative bottom-2 mb-10">
<div class="flex-1">
{{ prettifyUptime(uptime['7d']) }}
<h2 class="text-sm text-gray-400">Last 7 days</h2>
</div>
<div class="flex-1">
{{ prettifyUptime(uptime['24h']) }}
<h2 class="text-sm text-gray-400">Last 24 hours</h2>
</div>
<div class="flex-1">
{{ prettifyUptime(uptime['1h']) }}
<h2 class="text-sm text-gray-400">Last hour</h2>
</div>
</div>
<hr class="mt-1"/>
<h3 class="text-xl font-mono text-gray-400 mt-1 text-right">BADGES</h3>
<div v-if="serviceStatus && serviceStatus.key" class="flex space-x-4 text-center text-2xl mt-6 relative bottom-12">
<div class="flex-1"> <div class="flex-1">
<h2 class="text-sm text-gray-400 mb-1">Last 7 days</h2>
<img :src="generateBadgeImageURL('7d')" alt="7d uptime badge" class="mx-auto" /> <img :src="generateBadgeImageURL('7d')" alt="7d uptime badge" class="mx-auto" />
</div> </div>
<div class="flex-1"> <div class="flex-1">
<h2 class="text-sm text-gray-400 mb-1">Last 24 hours</h2>
<img :src="generateBadgeImageURL('24h')" alt="24h uptime badge" class="mx-auto" /> <img :src="generateBadgeImageURL('24h')" alt="24h uptime badge" class="mx-auto" />
</div> </div>
<div class="flex-1"> <div class="flex-1">
<h2 class="text-sm text-gray-400 mb-1">Last hour</h2>
<img :src="generateBadgeImageURL('1h')" alt="1h uptime badge" class="mx-auto" /> <img :src="generateBadgeImageURL('1h')" alt="1h uptime badge" class="mx-auto" />
</div> </div>
</div> </div>
@@ -159,7 +146,6 @@ export default {
return { return {
serviceStatus: {}, serviceStatus: {},
events: [], events: [],
uptime: {"7d": 0, "24h": 0, "1h": 0},
// Since this page isn't at the root, we need to modify the server URL a bit // Since this page isn't at the root, we need to modify the server URL a bit
serverUrl: SERVER_URL === '.' ? '..' : SERVER_URL, serverUrl: SERVER_URL === '.' ? '..' : SERVER_URL,
currentPage: 1, currentPage: 1,
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
+1 -1
View File
File diff suppressed because one or more lines are too long