From 9cd5c89d08e7538a9f49a858c469348e4e4f285b Mon Sep 17 00:00:00 2001 From: Aditya Thebe Date: Wed, 5 Jul 2023 11:30:33 +0545 Subject: [PATCH] calculate the window duration --- pkg/api.go | 4 ++++ pkg/api/api.go | 33 +++++++++++++++++++++++++++++++++ pkg/cache/cache.go | 1 + pkg/cache/postgres_query.go | 11 ++--------- 4 files changed, 40 insertions(+), 9 deletions(-) diff --git a/pkg/api.go b/pkg/api.go index 2d61d7b7d..914f2f03c 100644 --- a/pkg/api.go +++ b/pkg/api.go @@ -91,6 +91,10 @@ type Uptime struct { LastFail *time.Time `json:"last_fail,omitempty"` } +func (u Uptime) Total() int { + return u.Passed + u.Failed +} + func (u Uptime) String() string { if u.Passed == 0 && u.Failed == 0 { return "" diff --git a/pkg/api/api.go b/pkg/api/api.go index 52cfccd17..8c1eb05d5 100644 --- a/pkg/api/api.go +++ b/pkg/api/api.go @@ -1,6 +1,7 @@ package api import ( + "math" "net/http" "time" @@ -8,10 +9,14 @@ import ( "github.com/flanksource/canary-checker/pkg/runner" "github.com/flanksource/duty/models" "github.com/labstack/echo/v4" + "github.com/pkg/errors" "github.com/flanksource/canary-checker/pkg" ) +// The maximum data points returned by the graph API +const maxCheckStatuses = 100 + var DefaultWindow = "1h" type Response struct { @@ -20,10 +25,13 @@ type Response struct { Checks pkg.Checks `json:"checks"` ChecksSummary models.Checks `json:"checks_summary,omitempty"` } + type DetailResponse struct { Duration int `json:"duration,omitempty"` RunnerName string `json:"runnerName"` Status []pkg.Timeseries `json:"status"` + Latency pkg.Latency `json:"latency"` + Uptime pkg.Uptime `json:"uptime"` } func About(c echo.Context) error { @@ -41,6 +49,28 @@ func CheckDetails(c echo.Context) error { } start := time.Now() + + summary, err := cache.PostgresCache.Query(*q) + if err != nil { + return errorResonse(c, err, http.StatusInternalServerError) + } + checkSummary := summary[0] + + totalChecks := checkSummary.Uptime.Total() + if totalChecks <= maxCheckStatuses { + q.WindowDuration = time.Second // TODO: Maybe do not window at all + } else { + startTime := q.GetStartTime() + if startTime == nil { + return errorResonse(c, errors.New("start time must be a duration or RFC3339 timestamp"), http.StatusBadRequest) + } + + startDuration := time.Since(*startTime) + + windowsCount := int(math.Ceil(float64(totalChecks) / float64(maxCheckStatuses))) + q.WindowDuration = startDuration / time.Duration(windowsCount) + } + results, err := cache.PostgresCache.QueryStatus(c.Request().Context(), *q) if err != nil { return errorResonse(c, err, http.StatusInternalServerError) @@ -50,7 +80,10 @@ func CheckDetails(c echo.Context) error { RunnerName: runner.RunnerName, Status: results, Duration: int(time.Since(start).Milliseconds()), + Latency: checkSummary.Latency, + Uptime: checkSummary.Uptime, } + return c.JSON(http.StatusOK, apiResponse) } diff --git a/pkg/cache/cache.go b/pkg/cache/cache.go index 1e360090e..08ac56f84 100644 --- a/pkg/cache/cache.go +++ b/pkg/cache/cache.go @@ -28,6 +28,7 @@ type QueryParams struct { StatusCount int Labels map[string]string Trace bool + WindowDuration time.Duration } func (q QueryParams) Validate() error { diff --git a/pkg/cache/postgres_query.go b/pkg/cache/postgres_query.go index 8a0e8c157..f62099b60 100644 --- a/pkg/cache/postgres_query.go +++ b/pkg/cache/postgres_query.go @@ -101,17 +101,10 @@ FROM GROUP BY time ` - dur, err := duration.ParseDuration(q.Start) - if err != nil { - return nil, err - } - - start := time.Now().Add(-time.Duration(dur)).Format(time.RFC3339) + start := q.GetStartTime().Format(time.RFC3339) end := time.Now().Format(time.RFC3339) // TODO: connect with the new date range picker - // TODO: Find the perfect window duration - windowDurationSeconds := (time.Minute * 15).Seconds() - rows, err := db.Query(ctx, query, windowDurationSeconds/2, windowDurationSeconds, start, end, q.Check) + rows, err := db.Query(ctx, query, q.WindowDuration.Seconds()/2, q.WindowDuration.Seconds(), start, end, q.Check) if err != nil { return nil, err }