From 75d8b4032781ef4a8ff49de3f31fa160976e9909 Mon Sep 17 00:00:00 2001 From: TwinProduction Date: Sat, 21 Aug 2021 10:59:09 -0400 Subject: [PATCH] Add GetAverageResponseTimeByKey method on store for response time badges --- storage/store/memory/memory.go | 28 ++++++++++++++++++ storage/store/sqlite/sqlite.go | 53 ++++++++++++++++++++++++++++++++++ storage/store/store.go | 3 ++ 3 files changed, 84 insertions(+) diff --git a/storage/store/memory/memory.go b/storage/store/memory/memory.go index e367c315..44f0304d 100644 --- a/storage/store/memory/memory.go +++ b/storage/store/memory/memory.go @@ -99,6 +99,34 @@ func (s *Store) GetUptimeByKey(key string, from, to time.Time) (float64, error) return float64(successfulExecutions) / float64(totalExecutions), nil } +// GetAverageResponseTimeByKey returns the average response time in milliseconds (value) during a time range +func (s *Store) GetAverageResponseTimeByKey(key string, from, to time.Time) (int, error) { + if from.After(to) { + return 0, common.ErrInvalidTimeRange + } + serviceStatus := s.cache.GetValue(key) + if serviceStatus == nil || serviceStatus.(*core.ServiceStatus).Uptime == nil { + return 0, common.ErrServiceNotFound + } + current := from + var totalExecutions, totalResponseTime uint64 + for to.Sub(current) >= 0 { + hourlyUnixTimestamp := current.Truncate(time.Hour).Unix() + hourlyStats := serviceStatus.(*core.ServiceStatus).Uptime.HourlyStatistics[hourlyUnixTimestamp] + if hourlyStats == nil || hourlyStats.TotalExecutions == 0 { + current = current.Add(time.Hour) + continue + } + totalExecutions += hourlyStats.TotalExecutions + totalResponseTime += hourlyStats.TotalExecutionsResponseTime + current = current.Add(time.Hour) + } + if totalExecutions == 0 { + return 0, nil + } + return int(float64(totalResponseTime) / float64(totalExecutions)), nil +} + // GetHourlyAverageResponseTimeByKey returns a map of hourly (key) average response time in milliseconds (value) during a time range func (s *Store) GetHourlyAverageResponseTimeByKey(key string, from, to time.Time) (map[int64]int, error) { if from.After(to) { diff --git a/storage/store/sqlite/sqlite.go b/storage/store/sqlite/sqlite.go index 173c1dc7..5471ad1b 100644 --- a/storage/store/sqlite/sqlite.go +++ b/storage/store/sqlite/sqlite.go @@ -219,6 +219,31 @@ func (s *Store) GetUptimeByKey(key string, from, to time.Time) (float64, error) return uptime, nil } +// GetAverageResponseTimeByKey returns the average response time in milliseconds (value) during a time range +func (s *Store) GetAverageResponseTimeByKey(key string, from, to time.Time) (int, error) { + if from.After(to) { + return 0, common.ErrInvalidTimeRange + } + tx, err := s.db.Begin() + if err != nil { + return 0, err + } + serviceID, _, _, err := s.getServiceIDGroupAndNameByKey(tx, key) + if err != nil { + _ = tx.Rollback() + return 0, err + } + averageResponseTime, err := s.getServiceAverageResponseTime(tx, serviceID, from, to) + if err != nil { + _ = tx.Rollback() + return 0, err + } + if err = tx.Commit(); err != nil { + _ = tx.Rollback() + } + return averageResponseTime, nil +} + // GetHourlyAverageResponseTimeByKey returns a map of hourly (key) average response time in milliseconds (value) during a time range func (s *Store) GetHourlyAverageResponseTimeByKey(key string, from, to time.Time) (map[int64]int, error) { if from.After(to) { @@ -678,6 +703,34 @@ func (s *Store) getServiceUptime(tx *sql.Tx, serviceID int64, from, to time.Time return } +func (s *Store) getServiceAverageResponseTime(tx *sql.Tx, serviceID int64, from, to time.Time) (int, error) { + rows, err := tx.Query( + ` + SELECT SUM(total_executions), SUM(total_response_time) + FROM service_uptime + WHERE service_id = $1 + AND total_executions > 0 + AND hour_unix_timestamp >= $2 + AND hour_unix_timestamp <= $3 + `, + serviceID, + from.Unix(), + to.Unix(), + ) + if err != nil { + return 0, err + } + var totalExecutions, totalResponseTime int + for rows.Next() { + _ = rows.Scan(&totalExecutions, &totalResponseTime) + } + _ = rows.Close() + if totalExecutions == 0 { + return 0, nil + } + return int(float64(totalResponseTime) / float64(totalExecutions)), nil +} + func (s *Store) getServiceHourlyAverageResponseTimes(tx *sql.Tx, serviceID int64, from, to time.Time) (map[int64]int, error) { rows, err := tx.Query( ` diff --git a/storage/store/store.go b/storage/store/store.go index fd02a893..a9af6b97 100644 --- a/storage/store/store.go +++ b/storage/store/store.go @@ -24,6 +24,9 @@ type Store interface { // GetUptimeByKey returns the uptime percentage during a time range GetUptimeByKey(key string, from, to time.Time) (float64, error) + // GetAverageResponseTimeByKey returns the average response time in milliseconds (value) during a time range + GetAverageResponseTimeByKey(key string, from, to time.Time) (int, error) + // GetHourlyAverageResponseTimeByKey returns a map of hourly (key) average response time in milliseconds (value) during a time range GetHourlyAverageResponseTimeByKey(key string, from, to time.Time) (map[int64]int, error)