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>
pull/1113/head
kRhythm53 2022-08-17 15:08:27 +05:30 committed by GitHub
parent 8aebb9570d
commit 4bbe871535
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 104 additions and 1 deletions

4
handlers/constants.go Normal file
View File

@ -0,0 +1,4 @@
package handlers
const incidentsTimeoutInMinutes = 120.0 //custom
const resolved = "Resolved"

View File

@ -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 {

View File

@ -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")

View File

@ -38,3 +38,5 @@ func HandleEmptyStatus(status string) string {
return status
}
}
const INCIDENTS = "Incidents"

View File

@ -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
}