diff --git a/controller/handler/chart.go b/controller/handler/chart.go index b8213b9c..5ef4b803 100644 --- a/controller/handler/chart.go +++ b/controller/handler/chart.go @@ -1,6 +1,7 @@ package handler import ( + "encoding/json" "log" "math" "net/http" @@ -117,3 +118,41 @@ func ResponseTimeChart(writer http.ResponseWriter, r *http.Request) { return } } + +func ResponseTime(writer http.ResponseWriter, r *http.Request) { + vars := mux.Vars(r) + duration := vars["duration"] + var from time.Time + switch duration { + case "7d": + from = time.Now().Truncate(time.Hour).Add(-24 * 7 * time.Hour) + case "24h": + from = time.Now().Truncate(time.Hour).Add(-24 * time.Hour) + default: + http.Error(writer, "Durations supported: 7d, 24h", http.StatusBadRequest) + return + } + hourlyAverageResponseTime, err := store.Get().GetHourlyAverageResponseTimeByKey(vars["key"], from, time.Now()) + if err != nil { + if err == common.ErrEndpointNotFound { + http.Error(writer, err.Error(), http.StatusNotFound) + } else if err == common.ErrInvalidTimeRange { + http.Error(writer, err.Error(), http.StatusBadRequest) + } else { + http.Error(writer, err.Error(), http.StatusInternalServerError) + } + return + } + if len(hourlyAverageResponseTime) == 0 { + http.Error(writer, "", http.StatusNoContent) + return + } + data, err := json.Marshal(hourlyAverageResponseTime) + if err != nil { + http.Error(writer, err.Error(), http.StatusInternalServerError) + return + } + writer.Header().Add("Content-Type", "application/json") + writer.WriteHeader(http.StatusOK) + _, _ = writer.Write(data) +} diff --git a/controller/handler/handler.go b/controller/handler/handler.go index 9253b929..a1b1b255 100644 --- a/controller/handler/handler.go +++ b/controller/handler/handler.go @@ -23,6 +23,7 @@ func CreateRouter(staticFolder string, securityConfig *security.Config, uiConfig router.HandleFunc("/api/v1/endpoints/{key}/uptimes/{duration}/badge.svg", UptimeBadge).Methods("GET") router.HandleFunc("/api/v1/endpoints/{key}/response-times/{duration}/badge.svg", ResponseTimeBadge).Methods("GET") router.HandleFunc("/api/v1/endpoints/{key}/response-times/{duration}/chart.svg", ResponseTimeChart).Methods("GET") + router.HandleFunc("/api/v1/endpoints/{key}/response-times/{duration}", ResponseTime).Methods("GET") // XXX: Remove the lines between this and the next XXX comment in v4.0.0 router.HandleFunc("/api/v1/services/statuses", secureIfNecessary(securityConfig, EndpointStatuses)).Methods("GET") // No GzipHandler for this one, because we cache the content as Gzipped already router.HandleFunc("/api/v1/services/{key}/statuses", secureIfNecessary(securityConfig, GzipHandlerFunc(EndpointStatus))).Methods("GET") diff --git a/web/app/package.json b/web/app/package.json index 7846c39c..e3a183aa 100644 --- a/web/app/package.json +++ b/web/app/package.json @@ -10,6 +10,7 @@ "dependencies": { "core-js": "^3.19.1", "vue": "3.2.21", + "vue-chart-3": "^0.5.11", "vue-router": "^4.0.11" }, "devDependencies": { diff --git a/web/app/src/views/Details.vue b/web/app/src/views/Details.vue index a30aeeec..3b5962c3 100644 --- a/web/app/src/views/Details.vue +++ b/web/app/src/views/Details.vue @@ -37,6 +37,9 @@