From 4bbe871535dafe8bc9694e98e6ec745bddf74ac0 Mon Sep 17 00:00:00 2001 From: kRhythm53 <87687733+kRhythm53@users.noreply.github.com> Date: Wed, 17 Aug 2022 15:08:27 +0530 Subject: [PATCH] New incident management (#34) * remove this * added routes * Update source.go * added a function * renamed a constant * changed stuff * changed stuff acc to reviews * added log * added new incidents * added order * Update struct.go Co-authored-by: Rhythm <35167328+kRhythm@users.noreply.github.com> --- handlers/constants.go | 4 ++ handlers/incident.go | 94 +++++++++++++++++++++++++++++++++++++ handlers/routes.go | 3 ++ types/services/constants.go | 2 + types/services/database.go | 2 +- 5 files changed, 104 insertions(+), 1 deletion(-) create mode 100644 handlers/constants.go diff --git a/handlers/constants.go b/handlers/constants.go new file mode 100644 index 00000000..ecc3c8ac --- /dev/null +++ b/handlers/constants.go @@ -0,0 +1,4 @@ +package handlers + +const incidentsTimeoutInMinutes = 120.0 //custom +const resolved = "Resolved" diff --git a/handlers/incident.go b/handlers/incident.go index eca411cb..12506474 100644 --- a/handlers/incident.go +++ b/handlers/incident.go @@ -1,11 +1,14 @@ package handlers import ( + "fmt" "github.com/gorilla/mux" "github.com/statping/statping/types/errors" "github.com/statping/statping/types/incidents" + "github.com/statping/statping/types/services" "github.com/statping/statping/utils" "net/http" + "time" ) func findIncident(r *http.Request) (*incidents.Incident, int64, error) { @@ -33,6 +36,74 @@ func apiServiceIncidentsHandler(w http.ResponseWriter, r *http.Request) { returnJson(service.Incidents, w, r) } +func apiServiceActiveIncidentsHandler(w http.ResponseWriter, r *http.Request) { + service, err := findService(r) + if err != nil { + sendErrorJson(err, w, r) + return + } + visibleIncidents := getVisibleIncidentsOfService(service) + returnJson(visibleIncidents, w, r) +} + +func apiSubServiceActiveIncidentsHandler(w http.ResponseWriter, r *http.Request) { + service, err := findService(r) + if err != nil { + sendErrorJson(err, w, r) + return + } + subService, err := findPublicSubService(r, service) + if err != nil { + sendErrorJson(err, w, r) + return + } + + visibleIncidents := getVisibleIncidentsOfService(subService) + returnJson(visibleIncidents, w, r) +} + +func getVisibleIncidentsOfService(service *services.Service) []incidents.Incident { + var visibleIncidents []incidents.Incident + var visibleIncidentIds []int64 + for _, incident := range service.Incidents { + if hasZeroUpdates(incident.Updates) { + visibleIncidents = append(visibleIncidents, *incident) + visibleIncidentIds = append(visibleIncidentIds, incident.Id) + } else if checkResolvedVisibility(incident.Updates) { + incidentVar := *incident + reverse(incidentVar.Updates) + visibleIncidents = append(visibleIncidents, incidentVar) + visibleIncidentIds = append(visibleIncidentIds, incident.Id) + } + } + log.Info(fmt.Sprintf("Visible Incident Id's for the Service %v : %v", service.Name, visibleIncidentIds)) + return visibleIncidents +} + +func reverse(incidents []*incidents.IncidentUpdate) { + for i, j := 0, len(incidents)-1; i < j; i, j = i+1, j-1 { + incidents[i], incidents[j] = incidents[j], incidents[i] + } +} + +func hasZeroUpdates(Updates []*incidents.IncidentUpdate) bool { + if len(Updates) == 0 { + return true + } + return false +} + +func checkResolvedVisibility(incidentUpdates []*incidents.IncidentUpdate) bool { + if !(incidentUpdates[len(incidentUpdates)-1].Type == resolved && getTimeDiff(incidentUpdates[len(incidentUpdates)-1]) > incidentsTimeoutInMinutes) { + return true + } + return false +} + +func getTimeDiff(update *incidents.IncidentUpdate) float64 { + return time.Now().Sub(update.CreatedAt).Minutes() +} + func apiIncidentUpdatesHandler(w http.ResponseWriter, r *http.Request) { incid, _, err := findIncident(r) if err != nil { @@ -83,6 +154,29 @@ func apiCreateIncidentHandler(w http.ResponseWriter, r *http.Request) { sendJsonAction(incident, "create", w, r) } +func apiUpdateIncidentHandler(w http.ResponseWriter, r *http.Request) { + incident, _, err := findIncident(r) + if err != nil { + sendErrorJson(err, w, r) + return + } + + var updatedIncident *incidents.Incident + if err := DecodeJSON(r, &updatedIncident); err != nil { + sendErrorJson(err, w, r) + return + } + + incident.Title = updatedIncident.Title + incident.Description = updatedIncident.Description + if err := incident.Update(); err != nil { + sendErrorJson(err, w, r) + return + } + + sendJsonAction(incident, "update", w, r) +} + func apiIncidentUpdateHandler(w http.ResponseWriter, r *http.Request) { incident, _, err := findIncident(r) if err != nil { diff --git a/handlers/routes.go b/handlers/routes.go index 47040c87..f08800b8 100644 --- a/handlers/routes.go +++ b/handlers/routes.go @@ -155,8 +155,11 @@ func Router() *mux.Router { api.Handle("/api/services/{id}/sub_services/{sub_id}/block_series", http.HandlerFunc(apiSubServiceBlockSeriesHandler)).Methods("GET") // API INCIDENTS Routes + api.Handle("/api/services/{id}/active_incidents", http.HandlerFunc(apiServiceActiveIncidentsHandler)).Methods("GET") + api.Handle("/api/services/{id}/sub_services/{sub_id}/active_incidents", http.HandlerFunc(apiSubServiceActiveIncidentsHandler)).Methods("GET") api.Handle("/api/services/{id}/incidents", authenticated(apiServiceIncidentsHandler, false)).Methods("GET") api.Handle("/api/services/{id}/incidents", authenticated(apiCreateIncidentHandler, false)).Methods("POST") + api.Handle("/api/incidents/{id}", authenticated(apiUpdateIncidentHandler, false)).Methods("PATCH") api.Handle("/api/incidents/{id}", authenticated(apiIncidentUpdateHandler, false)).Methods("POST") api.Handle("/api/incidents/{id}", authenticated(apiDeleteIncidentHandler, false)).Methods("DELETE") diff --git a/types/services/constants.go b/types/services/constants.go index c3bb456e..7b1d1842 100644 --- a/types/services/constants.go +++ b/types/services/constants.go @@ -38,3 +38,5 @@ func HandleEmptyStatus(status string) string { return status } } + +const INCIDENTS = "Incidents" diff --git a/types/services/database.go b/types/services/database.go index 87aa93be..7a897841 100644 --- a/types/services/database.go +++ b/types/services/database.go @@ -92,7 +92,7 @@ func FindOne(id int64) (*Service, error) { return nil, errors.Missing(&Service{}, id) } service := &Service{} - db.First(&service, id) + db.Preload(INCIDENTS).First(&service, id) return service, nil }