diff --git a/Makefile b/Makefile index 738bc865..b6a73fc2 100644 --- a/Makefile +++ b/Makefile @@ -127,7 +127,7 @@ print_details: @echo \==== Monitoring and IDE ==== @echo \Grafana: http://localhost:3000 \(username: admin, password: admin\) -build-all: xgo-install build-mac build-linux build-linux build-alpine +build-all: xgo-install build-mac build-linux build-windows build-linux build-alpine compress download-key: wget -O statping.gpg $(KEY_URL) diff --git a/handlers/prometheus.go b/handlers/prometheus.go index 1f474e0d..7cdcd1f0 100644 --- a/handlers/prometheus.go +++ b/handlers/prometheus.go @@ -81,7 +81,7 @@ func prometheusHandler(w http.ResponseWriter, r *http.Request) { return } - for _, ser := range services.All() { + for _, ser := range services.AllInOrder() { online := 1 if !ser.Online { online = 0 @@ -106,8 +106,22 @@ func prometheusHandler(w http.ResponseWriter, r *http.Request) { for _, notif := range notifications.All() { PrometheusComment(fmt.Sprintf("Notifier %s:", notif.Method)) - PrometheusExportKey("notifier_on_success", notif.Id, notif.Method, 0) - PrometheusExportKey("notifier_on_failure", notif.Id, notif.Method, 0) + enabled := 0 + if notif.Enabled.Bool { + enabled = 1 + } + PrometheusExportKey("notifier_enabled", notif.Id, notif.Method, enabled) + PrometheusExportKey("notifier_on_success", notif.Id, notif.Method, notif.Hits.OnSuccess) + PrometheusExportKey("notifier_on_failure", notif.Id, notif.Method, notif.Hits.OnFailure) + PrometheusExportKey("notifier_on_user_new", notif.Id, notif.Method, notif.Hits.OnNewUser) + PrometheusExportKey("notifier_on_user_update", notif.Id, notif.Method, notif.Hits.OnUpdatedUser) + PrometheusExportKey("notifier_on_user_delete", notif.Id, notif.Method, notif.Hits.OnDeletedUser) + PrometheusExportKey("notifier_on_service_new", notif.Id, notif.Method, notif.Hits.OnNewService) + PrometheusExportKey("notifier_on_service_update", notif.Id, notif.Method, notif.Hits.OnUpdatedService) + PrometheusExportKey("notifier_on_service_delete", notif.Id, notif.Method, notif.Hits.OnDeletedService) + PrometheusExportKey("notifier_on_notifier_new", notif.Id, notif.Method, notif.Hits.OnNewNotifier) + PrometheusExportKey("notifier_on_notifier_update", notif.Id, notif.Method, notif.Hits.OnUpdatedNotifier) + PrometheusExportKey("notifier_on_notifier_save", notif.Id, notif.Method, notif.Hits.OnSave) } PrometheusComment("HTTP Metrics") diff --git a/handlers/services.go b/handlers/services.go index 370ba924..2b8eba17 100644 --- a/handlers/services.go +++ b/handlers/services.go @@ -189,8 +189,7 @@ func apiServiceDeleteHandler(w http.ResponseWriter, r *http.Request) { } func apiAllServicesHandler(r *http.Request) interface{} { - services := services.All() - return services + return services.AllInOrder() } func joinServices(srvss map[int64]*services.Service) []*services.Service { diff --git a/types/checkins/database.go b/types/checkins/database.go index 66cd80cd..7bd898d5 100644 --- a/types/checkins/database.go +++ b/types/checkins/database.go @@ -14,15 +14,15 @@ func DBhits() database.Database { } func Find(id int64) (*Checkin, error) { - var checkin *Checkin + var checkin Checkin db := DB().Where("id = ?", id).Find(&checkin) - return checkin, db.Error() + return &checkin, db.Error() } func FindByAPI(key string) (*Checkin, error) { - var checkin *Checkin + var checkin Checkin db := DB().Where("api = ?", key).Find(&checkin) - return checkin, db.Error() + return &checkin, db.Error() } func All() []*Checkin { @@ -33,7 +33,7 @@ func All() []*Checkin { func (c *Checkin) Create() error { c.ApiKey = utils.RandomString(7) - db := DB().Create(&c) + db := DB().Create(c) c.Start() go c.CheckinRoutine() @@ -41,12 +41,12 @@ func (c *Checkin) Create() error { } func (c *Checkin) Update() error { - db := DB().Update(&c) + db := DB().Update(c) return db.Error() } func (c *Checkin) Delete() error { c.Close() - db := DB().Delete(&c) + db := DB().Delete(c) return db.Error() } diff --git a/types/checkins/database_hits.go b/types/checkins/database_hits.go index 9c608b27..657337a8 100644 --- a/types/checkins/database_hits.go +++ b/types/checkins/database_hits.go @@ -1,9 +1,9 @@ package checkins func (c *Checkin) LastHit() *CheckinHit { - var hit *CheckinHit + var hit CheckinHit DBhits().Where("checkin = ?", c.Id).Limit(1).Find(&hit) - return hit + return &hit } func (c *Checkin) Hits() []*CheckinHit { @@ -14,16 +14,16 @@ func (c *Checkin) Hits() []*CheckinHit { } func (c *CheckinHit) Create() error { - db := DBhits().Create(&c) + db := DBhits().Create(c) return db.Error() } func (c *CheckinHit) Update() error { - db := DBhits().Update(&c) + db := DBhits().Update(c) return db.Error() } func (c *CheckinHit) Delete() error { - db := DBhits().Delete(&c) + db := DBhits().Delete(c) return db.Error() } diff --git a/types/core/database.go b/types/core/database.go index a3fcd2c7..bebb950c 100644 --- a/types/core/database.go +++ b/types/core/database.go @@ -30,7 +30,6 @@ func Select() (*Core, error) { App = &c App.UseCdn = null.NewNullBool(os.Getenv("USE_CDN") == "true") return App, db.Error() - } func (c *Core) Create() error { @@ -50,7 +49,7 @@ func (c *Core) Create() error { } func (c *Core) Update() error { - db := DB().Update(&c) + db := DB().Update(c) return db.Error() } @@ -74,6 +73,6 @@ func Sample() error { Footer: null.NewNullString(""), } - db := DB().Create(&core) + db := DB().Create(core) return db.Error() } diff --git a/types/failures/database.go b/types/failures/database.go index 2f1cb307..2dd71248 100644 --- a/types/failures/database.go +++ b/types/failures/database.go @@ -7,9 +7,9 @@ func DB() database.Database { } func Find(id int64) (*Failure, error) { - var failure *Failure + var failure Failure db := DB().Where("id = ?", id).Find(&failure) - return failure, db.Error() + return &failure, db.Error() } func All() []*Failure { @@ -19,16 +19,16 @@ func All() []*Failure { } func (f *Failure) Create() error { - db := DB().Create(&f) + db := DB().Create(f) return db.Error() } func (f *Failure) Update() error { - db := DB().Update(&f) + db := DB().Update(f) return db.Error() } func (f *Failure) Delete() error { - db := DB().Delete(&f) + db := DB().Delete(f) return db.Error() } diff --git a/types/groups/database.go b/types/groups/database.go index 1f23be72..c09488f7 100644 --- a/types/groups/database.go +++ b/types/groups/database.go @@ -22,17 +22,17 @@ func All() []*Group { } func (g *Group) Create() error { - db := DB().Create(&g) + db := DB().Create(g) return db.Error() } func (g *Group) Update() error { - db := DB().Update(&g) + db := DB().Update(g) return db.Error() } func (g *Group) Delete() error { - db := DB().Delete(&g) + db := DB().Delete(g) return db.Error() } diff --git a/types/hits/database.go b/types/hits/database.go index 50f91b7c..659a71cb 100644 --- a/types/hits/database.go +++ b/types/hits/database.go @@ -12,9 +12,9 @@ func DB() database.Database { } func Find(id int64) (*Hit, error) { - var group *Hit + var group Hit db := DB().Where("id = ?", id).Find(&group) - return group, db.Error() + return &group, db.Error() } func All() []*Hit { @@ -24,16 +24,16 @@ func All() []*Hit { } func (h *Hit) Create() error { - db := DB().Create(&h) + db := DB().Create(h) return db.Error() } func (h *Hit) Update() error { - db := DB().Update(&h) + db := DB().Update(h) return db.Error() } func (h *Hit) Delete() error { - db := DB().Delete(&h) + db := DB().Delete(h) return db.Error() } diff --git a/types/incidents/database.go b/types/incidents/database.go index 704875ff..cd853b52 100644 --- a/types/incidents/database.go +++ b/types/incidents/database.go @@ -3,9 +3,9 @@ package incidents import "github.com/hunterlong/statping/database" func Find(id int64) (*Incident, error) { - var incident *Incident + var incident Incident db := database.DB().Model(&Incident{}).Where("id = ?", id).Find(&incident) - return incident, db.Error() + return &incident, db.Error() } func All() []*Incident { @@ -15,16 +15,16 @@ func All() []*Incident { } func (i *Incident) Create() error { - db := database.DB().Create(&i) + db := database.DB().Create(i) return db.Error() } func (i *Incident) Update() error { - db := database.DB().Update(&i) + db := database.DB().Update(i) return db.Error() } func (i *Incident) Delete() error { - db := database.DB().Delete(&i) + db := database.DB().Delete(i) return db.Error() } diff --git a/types/integrations/database.go b/types/integrations/database.go index 0ee90b7f..7218d97e 100644 --- a/types/integrations/database.go +++ b/types/integrations/database.go @@ -10,9 +10,9 @@ func DB() database.Database { } func Find(name string) (*Integration, error) { - var integration *Integration + var integration Integration db := DB().Where("name = ?", name).Find(&integration) - return integration, db.Error() + return &integration, db.Error() } func All() []*Integration { @@ -26,16 +26,16 @@ func List(i Integrator) ([]*services.Service, error) { } func (i *Integration) Create() error { - db := DB().Create(&i) + db := DB().Create(i) return db.Error() } func (i *Integration) Update() error { - db := DB().Update(&i) + db := DB().Update(i) return db.Error() } func (i *Integration) Delete() error { - db := DB().Delete(&i) + db := DB().Delete(i) return db.Error() } diff --git a/types/notifications/database.go b/types/notifications/database.go index 5d8252b5..ba406363 100644 --- a/types/notifications/database.go +++ b/types/notifications/database.go @@ -9,10 +9,10 @@ func DB() database.Database { return database.DB().Model(&Notification{}) } -func Find(method string) (Notifier, error) { +func Find(name string) (Notifier, error) { for _, n := range AllCommunications { notif := n.Select() - if notif.Method == method { + if notif.Name() == name || notif.Method == name { return n, nil } } @@ -26,26 +26,21 @@ func All() []*Notification { } func (n *Notification) Create() error { - db := DB().FirstOrCreate(&n) + db := DB().Create(n) return db.Error() } -func Update(notifier Notifier) error { - n := notifier.Select() +func (n *Notification) Update() error { n.ResetQueue() - err := n.Update() if n.Enabled.Bool { n.Close() n.Start() - go Queue(notifier) + go Queue(Notifier(n)) } else { n.Close() } - return err -} - -func (n *Notification) Update() error { - return Update(n) + err := DB().Update(n) + return err.Error() } func (n *Notification) Delete() error { diff --git a/types/notifications/events.go b/types/notifications/events.go index 65874af7..c04d0210 100644 --- a/types/notifications/events.go +++ b/types/notifications/events.go @@ -60,6 +60,7 @@ sendMessages: WithField("trigger", "OnFailure"). WithFields(utils.ToFields(notifier, s)).Debugln(fmt.Sprintf("Sending [OnFailure] '%v' notification for service %v", notifier.Method, s.Name)) comm.(BasicEvents).OnFailure(s, f) + comm.Select().Hits.OnFailure++ } } } @@ -82,6 +83,7 @@ func OnSuccess(s *services.Service) { WithField("trigger", "OnSuccess"). WithFields(utils.ToFields(notifier, s)).Debugln(fmt.Sprintf("Sending [OnSuccess] '%v' notification for service %v", notifier.Method, s.Name)) comm.(BasicEvents).OnSuccess(s) + comm.Select().Hits.OnSuccess++ } } } @@ -94,6 +96,7 @@ func OnNewService(s *services.Service) { WithField("trigger", "OnNewService"). Debugln(fmt.Sprintf("Sending new service notification for service %v", s.Name)) comm.(ServiceEvents).OnNewService(s) + comm.Select().Hits.OnNewService++ } } } @@ -107,6 +110,7 @@ func OnUpdatedService(s *services.Service) { if utils.IsType(comm, new(ServiceEvents)) && isEnabled(comm) && inLimits(comm) { log.Debugln(fmt.Sprintf("Sending updated service notification for service %v", s.Name)) comm.(ServiceEvents).OnUpdatedService(s) + comm.Select().Hits.OnUpdatedService++ } } } @@ -120,6 +124,7 @@ func OnDeletedService(s *services.Service) { if utils.IsType(comm, new(ServiceEvents)) && isEnabled(comm) && inLimits(comm) { log.Debugln(fmt.Sprintf("Sending deleted service notification for service %v", s.Name)) comm.(ServiceEvents).OnDeletedService(s) + comm.Select().Hits.OnDeletedService++ } } } @@ -130,6 +135,7 @@ func OnNewUser(u *users.User) { if utils.IsType(comm, new(UserEvents)) && isEnabled(comm) && inLimits(comm) { log.Debugln(fmt.Sprintf("Sending new user notification for user %v", u.Username)) comm.(UserEvents).OnNewUser(u) + comm.Select().Hits.OnNewUser++ } } } @@ -140,6 +146,7 @@ func OnUpdatedUser(u *users.User) { if utils.IsType(comm, new(UserEvents)) && isEnabled(comm) && inLimits(comm) { log.Debugln(fmt.Sprintf("Sending updated user notification for user %v", u.Username)) comm.(UserEvents).OnUpdatedUser(u) + comm.Select().Hits.OnUpdatedUser++ } } } @@ -150,6 +157,7 @@ func OnDeletedUser(u *users.User) { if utils.IsType(comm, new(UserEvents)) && isEnabled(comm) && inLimits(comm) { log.Debugln(fmt.Sprintf("Sending deleted user notification for user %v", u.Username)) comm.(UserEvents).OnDeletedUser(u) + comm.Select().Hits.OnDeletedUser++ } } } @@ -178,6 +186,7 @@ func OnNewNotifier(n *Notification) { for _, comm := range AllCommunications { if utils.IsType(comm, new(NotifierEvents)) && isEnabled(comm) && inLimits(comm) { comm.(NotifierEvents).OnNewNotifier(n) + comm.Select().Hits.OnNewNotifier++ } } } @@ -188,6 +197,7 @@ func OnUpdatedNotifier(n *Notification) { if utils.IsType(comm, new(NotifierEvents)) && isEnabled(comm) && inLimits(comm) { log.Infoln(fmt.Sprintf("Sending updated notifier for %v", n.Id)) comm.(NotifierEvents).OnUpdatedNotifier(n) + comm.Select().Hits.OnUpdatedNotifier++ } } } diff --git a/types/notifications/methods.go b/types/notifications/methods.go index 5530a950..e8afc824 100644 --- a/types/notifications/methods.go +++ b/types/notifications/methods.go @@ -8,6 +8,12 @@ import ( "time" ) +func (n *Notification) Name() string { + newName := strings.ToLower(n.Method) + newName = strings.ReplaceAll(newName, " ", "_") + return newName +} + // AfterFind for Notification will set the timezone func (n *Notification) AfterFind() (err error) { n.CreatedAt = utils.Now() @@ -97,6 +103,7 @@ func Init(n Notifier) (*Notification, error) { if err != nil { return nil, errors.Wrap(err, "error selecting notification") } + notify.CreatedAt = time.Now().UTC() notify.UpdatedAt = time.Now().UTC() if notify.Delay.Seconds() == 0 { diff --git a/types/notifications/struct.go b/types/notifications/struct.go index b102d501..4a958644 100644 --- a/types/notifications/struct.go +++ b/types/notifications/struct.go @@ -68,8 +68,17 @@ type Notification struct { } type notificationHits struct { - onSuccess int64 `gorm:"-" json:"-"` - onFailure int64 `gorm:"-" json:"-"` + OnSuccess int64 `gorm:"-" json:"-"` + OnFailure int64 `gorm:"-" json:"-"` + OnSave int64 `gorm:"-" json:"-"` + OnNewService int64 `gorm:"-" json:"-"` + OnUpdatedService int64 `gorm:"-" json:"-"` + OnDeletedService int64 `gorm:"-" json:"-"` + OnNewUser int64 `gorm:"-" json:"-"` + OnUpdatedUser int64 `gorm:"-" json:"-"` + OnDeletedUser int64 `gorm:"-" json:"-"` + OnNewNotifier int64 `gorm:"-" json:"-"` + OnUpdatedNotifier int64 `gorm:"-" json:"-"` } // QueueData is the struct for the messaging queue with service @@ -155,7 +164,7 @@ func reverseLogs(input []*NotificationLog) []*NotificationLog { // SelectNotification returns the Notification struct from the database func SelectNotification(n Notifier) (*Notification, error) { notifier := n.Select() - err := DB().Where("method = ?", notifier.Method).Scan(¬ifier) + err := DB().Where("method = ?", notifier.Method).Find(¬ifier) return notifier, err.Error() } diff --git a/types/services/database.go b/types/services/database.go index 1621228e..34194249 100644 --- a/types/services/database.go +++ b/types/services/database.go @@ -5,6 +5,7 @@ import ( "fmt" "github.com/hunterlong/statping/database" "github.com/hunterlong/statping/utils" + "sort" ) var log = utils.Log @@ -31,8 +32,17 @@ func All() map[int64]*Service { return allServices } +func AllInOrder() []Service { + var services []Service + for _, service := range allServices { + services = append(services, *service) + } + sort.Sort(ServiceOrder(services)) + return services +} + func (s *Service) Create() error { - err := DB().Create(&s) + err := DB().Create(s) if err.Error() != nil { log.Errorln(fmt.Sprintf("Failed to create service %v #%v: %v", s.Name, s.Id, err)) return err.Error() @@ -40,14 +50,11 @@ func (s *Service) Create() error { allServices[s.Id] = s go ServiceCheckQueue(allServices[s.Id], true) - reorderServices() - //notifications.OnNewService(s) - return nil } func (s *Service) Update() error { - db := DB().Update(&s) + db := DB().Update(s) allServices[s.Id] = s @@ -61,18 +68,16 @@ func (s *Service) Update() error { s.SleepDuration = s.Duration() go ServiceCheckQueue(allServices[s.Id], true) - reorderServices() //notifier.OnUpdatedService(s.Service) return db.Error() } func (s *Service) Delete() error { - db := database.DB().Delete(&s) + db := database.DB().Delete(s) s.Close() delete(allServices, s.Id) - reorderServices() //notifier.OnDeletedService(s.Service) return db.Error() diff --git a/types/services/methods.go b/types/services/methods.go index 87dfa087..4c4b131d 100644 --- a/types/services/methods.go +++ b/types/services/methods.go @@ -7,7 +7,6 @@ import ( "github.com/hunterlong/statping/types/null" "github.com/hunterlong/statping/utils" "net/url" - "sort" "strconv" "strings" "time" @@ -54,11 +53,6 @@ func (s Service) Hash() string { return hex.EncodeToString(h.Sum(nil)) } -// reorderServices will sort the services based on 'order_id' -func reorderServices() { - sort.Sort(ServiceOrder(allServices)) -} - // SelectAllServices returns a slice of *core.Service to be store on []*core.Services // should only be called once on startup. func SelectAllServices(start bool) (map[int64]*Service, error) { @@ -85,8 +79,6 @@ func SelectAllServices(start bool) (map[int64]*Service, error) { s.UpdateStats() } - reorderServices() - return allServices, nil } diff --git a/types/services/struct.go b/types/services/struct.go index 64dfed48..c1eafa27 100644 --- a/types/services/struct.go +++ b/types/services/struct.go @@ -85,17 +85,9 @@ func (s *Service) BeforeCreate() (err error) { } // ServiceOrder will reorder the services based on 'order_id' (Order) -type ServiceOrder map[int64]*Service +type ServiceOrder []Service // Sort interface for resroting the Services in order -func (c ServiceOrder) Len() int { return len(c) } -func (c ServiceOrder) Swap(i, j int) { c[int64(i)], c[int64(j)] = c[int64(j)], c[int64(i)] } -func (c ServiceOrder) Less(i, j int) bool { - if c[int64(i)] == nil { - return false - } - if c[int64(j)] == nil { - return false - } - return c[int64(i)].Order < c[int64(j)].Order -} +func (c ServiceOrder) Len() int { return len(c) } +func (c ServiceOrder) Swap(i, j int) { c[int64(i)], c[int64(j)] = c[int64(j)], c[int64(i)] } +func (c ServiceOrder) Less(i, j int) bool { return c[i].Order < c[j].Order } diff --git a/types/users/database.go b/types/users/database.go index 2a71118b..42d16838 100644 --- a/types/users/database.go +++ b/types/users/database.go @@ -12,9 +12,9 @@ func DB() database.Database { } func Find(id int64) (*User, error) { - var user *User + var user User db := DB().Where("id = ?", id).Find(user) - return user, db.Error() + return &user, db.Error() } func FindByUsername(username string) (*User, error) { @@ -38,7 +38,7 @@ func (u *User) Create() error { u.ApiKey = utils.NewSHA1Hash(5) u.ApiSecret = utils.NewSHA1Hash(10) - db := DB().Create(&u) + db := DB().Create(u) return db.Error() } @@ -50,6 +50,6 @@ func (u *User) Update() error { } func (u *User) Delete() error { - db := DB().Delete(&u) + db := DB().Delete(u) return db.Error() }