mirror of https://github.com/statping/statping
notifications!!!
parent
d8a02b31a2
commit
12275f7522
|
@ -1,13 +1,13 @@
|
||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/statping/statping/notifiers"
|
|
||||||
"github.com/statping/statping/types/checkins"
|
"github.com/statping/statping/types/checkins"
|
||||||
"github.com/statping/statping/types/failures"
|
"github.com/statping/statping/types/failures"
|
||||||
"github.com/statping/statping/types/groups"
|
"github.com/statping/statping/types/groups"
|
||||||
"github.com/statping/statping/types/hits"
|
"github.com/statping/statping/types/hits"
|
||||||
"github.com/statping/statping/types/incidents"
|
"github.com/statping/statping/types/incidents"
|
||||||
"github.com/statping/statping/types/messages"
|
"github.com/statping/statping/types/messages"
|
||||||
|
"github.com/statping/statping/types/notifications"
|
||||||
"github.com/statping/statping/types/services"
|
"github.com/statping/statping/types/services"
|
||||||
"github.com/statping/statping/types/users"
|
"github.com/statping/statping/types/users"
|
||||||
)
|
)
|
||||||
|
@ -18,5 +18,5 @@ var (
|
||||||
)
|
)
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
DbModels = []interface{}{&services.Service{}, &users.User{}, &hits.Hit{}, &failures.Failure{}, &messages.Message{}, &groups.Group{}, &checkins.Checkin{}, &checkins.CheckinHit{}, ¬ifiers.Notification{}, &incidents.Incident{}, &incidents.IncidentUpdate{}}
|
DbModels = []interface{}{&services.Service{}, &users.User{}, &hits.Hit{}, &failures.Failure{}, &messages.Message{}, &groups.Group{}, &checkins.Checkin{}, &checkins.CheckinHit{}, ¬ifications.Notification{}, &incidents.Incident{}, &incidents.IncidentUpdate{}}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,12 +1,14 @@
|
||||||
package core
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/statping/statping/database"
|
"github.com/statping/statping/database"
|
||||||
|
"github.com/statping/statping/notifiers"
|
||||||
|
"github.com/statping/statping/types/core"
|
||||||
"github.com/statping/statping/types/services"
|
"github.com/statping/statping/types/services"
|
||||||
)
|
)
|
||||||
|
|
||||||
func InitApp() error {
|
func InitApp() error {
|
||||||
if _, err := Select(); err != nil {
|
if _, err := core.Select(); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -16,7 +18,9 @@ func InitApp() error {
|
||||||
|
|
||||||
go services.CheckServices()
|
go services.CheckServices()
|
||||||
|
|
||||||
|
notifiers.InitNotifiers()
|
||||||
|
|
||||||
database.StartMaintenceRoutine()
|
database.StartMaintenceRoutine()
|
||||||
App.Setup = true
|
core.App.Setup = true
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
14
cmd/main.go
14
cmd/main.go
|
@ -19,7 +19,6 @@ import (
|
||||||
"flag"
|
"flag"
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/getsentry/sentry-go"
|
"github.com/getsentry/sentry-go"
|
||||||
"github.com/statping/statping/notifiers"
|
|
||||||
"os"
|
"os"
|
||||||
"os/signal"
|
"os/signal"
|
||||||
"syscall"
|
"syscall"
|
||||||
|
@ -30,7 +29,6 @@ import (
|
||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
"github.com/statping/statping/handlers"
|
"github.com/statping/statping/handlers"
|
||||||
"github.com/statping/statping/types/configs"
|
"github.com/statping/statping/types/configs"
|
||||||
"github.com/statping/statping/types/core"
|
|
||||||
"github.com/statping/statping/types/services"
|
"github.com/statping/statping/types/services"
|
||||||
"github.com/statping/statping/utils"
|
"github.com/statping/statping/utils"
|
||||||
)
|
)
|
||||||
|
@ -165,11 +163,11 @@ func main() {
|
||||||
exit(err)
|
exit(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
log.Infoln("Migrating Notifiers...")
|
//log.Infoln("Migrating Notifiers...")
|
||||||
if err := notifiers.Migrate(); err != nil {
|
//if err := notifier.Migrate(); err != nil {
|
||||||
exit(errors.Wrap(err, "error migrating notifiers"))
|
// exit(errors.Wrap(err, "error migrating notifiers"))
|
||||||
}
|
//}
|
||||||
log.Infoln("Notifiers Migrated")
|
//log.Infoln("Notifiers Migrated")
|
||||||
|
|
||||||
if err := mainProcess(); err != nil {
|
if err := mainProcess(); err != nil {
|
||||||
exit(err)
|
exit(err)
|
||||||
|
@ -205,7 +203,7 @@ func mainProcess() error {
|
||||||
return errors.Wrap(err, errStr)
|
return errors.Wrap(err, errStr)
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := core.InitApp(); err != nil {
|
if err := InitApp(); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -18,7 +18,7 @@
|
||||||
{{if USING_ASSETS}}
|
{{if USING_ASSETS}}
|
||||||
<link href="css/vendor.css" rel="stylesheet">
|
<link href="css/vendor.css" rel="stylesheet">
|
||||||
<link href="css/style.css" rel="stylesheet">
|
<link href="css/style.css" rel="stylesheet">
|
||||||
<link href="css/base.css" rel="stylesheet">
|
<link href="css/main.css" rel="stylesheet">
|
||||||
{{else}}
|
{{else}}
|
||||||
<% _.each(htmlWebpackPlugin.tags.headTags, function(headTag) { %>
|
<% _.each(htmlWebpackPlugin.tags.headTags, function(headTag) { %>
|
||||||
<%= headTag %> <% }) %>
|
<%= headTag %> <% }) %>
|
||||||
|
|
|
@ -94,8 +94,8 @@ export default {
|
||||||
this.form[field] = this.notifier[field]
|
this.form[field] = this.notifier[field]
|
||||||
});
|
});
|
||||||
await Api.notifier_save(this.form)
|
await Api.notifier_save(this.form)
|
||||||
const notifiers = await Api.notifiers()
|
// const notifiers = await Api.notifiers()
|
||||||
await this.$store.commit('setNotifiers', notifiers)
|
// await this.$store.commit('setNotifiers', notifiers)
|
||||||
this.saved = true
|
this.saved = true
|
||||||
this.loading = false
|
this.loading = false
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
|
|
|
@ -19,12 +19,12 @@ import (
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/statping/statping/notifiers"
|
|
||||||
"github.com/statping/statping/types/checkins"
|
"github.com/statping/statping/types/checkins"
|
||||||
"github.com/statping/statping/types/core"
|
"github.com/statping/statping/types/core"
|
||||||
"github.com/statping/statping/types/groups"
|
"github.com/statping/statping/types/groups"
|
||||||
"github.com/statping/statping/types/incidents"
|
"github.com/statping/statping/types/incidents"
|
||||||
"github.com/statping/statping/types/messages"
|
"github.com/statping/statping/types/messages"
|
||||||
|
"github.com/statping/statping/types/notifications"
|
||||||
"github.com/statping/statping/types/null"
|
"github.com/statping/statping/types/null"
|
||||||
"github.com/statping/statping/types/services"
|
"github.com/statping/statping/types/services"
|
||||||
"github.com/statping/statping/types/users"
|
"github.com/statping/statping/types/users"
|
||||||
|
@ -143,7 +143,7 @@ func sendJsonAction(obj interface{}, method string, w http.ResponseWriter, r *ht
|
||||||
case *services.Service:
|
case *services.Service:
|
||||||
objName = "service"
|
objName = "service"
|
||||||
objId = v.Id
|
objId = v.Id
|
||||||
case *notifiers.Notification:
|
case *notifications.Notification:
|
||||||
objName = "notifier"
|
objName = "notifier"
|
||||||
objId = v.Id
|
objId = v.Id
|
||||||
case *core.Core:
|
case *core.Core:
|
||||||
|
|
|
@ -1,42 +1,43 @@
|
||||||
// Statping
|
//// Statping
|
||||||
// Copyright (C) 2018. Hunter Long and the project contributors
|
//// Copyright (C) 2018. Hunter Long and the project contributors
|
||||||
// Written by Hunter Long <info@socialeck.com> and the project contributors
|
//// Written by Hunter Long <info@socialeck.com> and the project contributors
|
||||||
|
////
|
||||||
|
//// https://github.com/statping/statping
|
||||||
|
////
|
||||||
|
//// The licenses for most software and other practical works are designed
|
||||||
|
//// to take away your freedom to share and change the works. By contrast,
|
||||||
|
//// the GNU General Public License is intended to guarantee your freedom to
|
||||||
|
//// share and change all versions of a program--to make sure it remains free
|
||||||
|
//// software for all its users.
|
||||||
|
////
|
||||||
|
//// You should have received a copy of the GNU General Public License
|
||||||
|
//// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
//
|
//
|
||||||
// https://github.com/statping/statping
|
|
||||||
//
|
|
||||||
// The licenses for most software and other practical works are designed
|
|
||||||
// to take away your freedom to share and change the works. By contrast,
|
|
||||||
// the GNU General Public License is intended to guarantee your freedom to
|
|
||||||
// share and change all versions of a program--to make sure it remains free
|
|
||||||
// software for all its users.
|
|
||||||
//
|
|
||||||
// You should have received a copy of the GNU General Public License
|
|
||||||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
|
|
||||||
package handlers
|
package handlers
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/gorilla/mux"
|
"github.com/gorilla/mux"
|
||||||
"github.com/statping/statping/notifiers"
|
"github.com/statping/statping/types/notifications"
|
||||||
"github.com/statping/statping/types/null"
|
"github.com/statping/statping/types/null"
|
||||||
|
"github.com/statping/statping/types/services"
|
||||||
"github.com/statping/statping/utils"
|
"github.com/statping/statping/utils"
|
||||||
"net/http"
|
"net/http"
|
||||||
)
|
)
|
||||||
|
|
||||||
func apiNotifiersHandler(w http.ResponseWriter, r *http.Request) {
|
func apiNotifiersHandler(w http.ResponseWriter, r *http.Request) {
|
||||||
var notifs []notifiers.Notifier
|
notifiers := services.AllNotifiers()
|
||||||
all := notifiers.All()
|
var notifs []*notifications.Notification
|
||||||
for _, v := range all {
|
for _, n := range notifiers {
|
||||||
notifs = append(notifs, v)
|
notifs = append(notifs, n.Select())
|
||||||
}
|
}
|
||||||
returnJson(notifs, w, r)
|
returnJson(notifs, w, r)
|
||||||
}
|
}
|
||||||
|
|
||||||
func apiNotifierGetHandler(w http.ResponseWriter, r *http.Request) {
|
func apiNotifierGetHandler(w http.ResponseWriter, r *http.Request) {
|
||||||
vars := mux.Vars(r)
|
vars := mux.Vars(r)
|
||||||
notifier, err := notifiers.Find(vars["notifier"])
|
notifier, err := notifications.Find(vars["notifier"])
|
||||||
if err != nil {
|
if err != nil {
|
||||||
sendErrorJson(err, w, r)
|
sendErrorJson(err, w, r)
|
||||||
return
|
return
|
||||||
|
@ -46,11 +47,12 @@ func apiNotifierGetHandler(w http.ResponseWriter, r *http.Request) {
|
||||||
|
|
||||||
func apiNotifierUpdateHandler(w http.ResponseWriter, r *http.Request) {
|
func apiNotifierUpdateHandler(w http.ResponseWriter, r *http.Request) {
|
||||||
vars := mux.Vars(r)
|
vars := mux.Vars(r)
|
||||||
notifer, err := notifiers.Find(vars["notifier"])
|
notifer, err := notifications.Find(vars["notifier"])
|
||||||
if err != nil {
|
if err != nil {
|
||||||
sendErrorJson(err, w, r)
|
sendErrorJson(err, w, r)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
defer r.Body.Close()
|
||||||
|
|
||||||
decoder := json.NewDecoder(r.Body)
|
decoder := json.NewDecoder(r.Body)
|
||||||
err = decoder.Decode(¬ifer)
|
err = decoder.Decode(¬ifer)
|
||||||
|
@ -83,7 +85,7 @@ func testNotificationHandler(w http.ResponseWriter, r *http.Request) {
|
||||||
apiSecret := form.Get("api_secret")
|
apiSecret := form.Get("api_secret")
|
||||||
limits := int(utils.ToInt(form.Get("limits")))
|
limits := int(utils.ToInt(form.Get("limits")))
|
||||||
|
|
||||||
notifier, err := notifiers.Find(method)
|
notifier, err := notifications.Find(method)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Errorln(fmt.Sprintf("issue saving notifier %v: %v", method, err))
|
log.Errorln(fmt.Sprintf("issue saving notifier %v: %v", method, err))
|
||||||
sendErrorJson(err, w, r)
|
sendErrorJson(err, w, r)
|
||||||
|
|
|
@ -17,7 +17,6 @@ package handlers
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/statping/statping/notifiers"
|
|
||||||
"github.com/statping/statping/types/failures"
|
"github.com/statping/statping/types/failures"
|
||||||
"github.com/statping/statping/types/services"
|
"github.com/statping/statping/types/services"
|
||||||
"github.com/statping/statping/utils"
|
"github.com/statping/statping/utils"
|
||||||
|
@ -104,25 +103,22 @@ func prometheusHandler(w http.ResponseWriter, r *http.Request) {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, n := range notifiers.All() {
|
for _, n := range services.AllNotifiers() {
|
||||||
notif := n.Select()
|
notif := n.Select()
|
||||||
PrometheusComment(fmt.Sprintf("Notifier %s:", notif.Method))
|
PrometheusComment(fmt.Sprintf("Notifier %s:", notif.Method))
|
||||||
enabled := 0
|
|
||||||
if notif.Enabled.Bool {
|
if notif.Enabled.Bool {
|
||||||
enabled = 1
|
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)
|
||||||
}
|
}
|
||||||
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")
|
PrometheusComment("HTTP Metrics")
|
||||||
|
|
|
@ -17,10 +17,10 @@ package handlers
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"errors"
|
"errors"
|
||||||
"github.com/statping/statping/notifiers"
|
|
||||||
"github.com/statping/statping/types/configs"
|
"github.com/statping/statping/types/configs"
|
||||||
"github.com/statping/statping/types/core"
|
"github.com/statping/statping/types/core"
|
||||||
"github.com/statping/statping/types/null"
|
"github.com/statping/statping/types/null"
|
||||||
|
"github.com/statping/statping/types/services"
|
||||||
"github.com/statping/statping/utils"
|
"github.com/statping/statping/utils"
|
||||||
"net/http"
|
"net/http"
|
||||||
"time"
|
"time"
|
||||||
|
@ -89,11 +89,11 @@ func processSetupHandler(w http.ResponseWriter, r *http.Request) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
log.Infoln("Migrating Notifiers...")
|
//log.Infoln("Migrating Notifiers...")
|
||||||
if err := notifiers.Migrate(); err != nil {
|
//if err := notifications.Migrate(); err != nil {
|
||||||
sendErrorJson(err, w, r)
|
// sendErrorJson(err, w, r)
|
||||||
return
|
// return
|
||||||
}
|
//}
|
||||||
|
|
||||||
c := &core.Core{
|
c := &core.Core{
|
||||||
Name: "Statping Sample Data",
|
Name: "Statping Sample Data",
|
||||||
|
@ -117,12 +117,17 @@ func processSetupHandler(w http.ResponseWriter, r *http.Request) {
|
||||||
core.App = c
|
core.App = c
|
||||||
|
|
||||||
log.Infoln("Initializing new Statping instance")
|
log.Infoln("Initializing new Statping instance")
|
||||||
if err := core.InitApp(); err != nil {
|
|
||||||
|
if _, err := services.SelectAllServices(true); err != nil {
|
||||||
log.Errorln(err)
|
log.Errorln(err)
|
||||||
sendErrorJson(err, w, r)
|
sendErrorJson(err, w, r)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
go services.CheckServices()
|
||||||
|
|
||||||
|
core.App.Setup = true
|
||||||
|
|
||||||
CacheStorage.Delete("/")
|
CacheStorage.Delete("/")
|
||||||
resetCookies()
|
resetCookies()
|
||||||
time.Sleep(1 * time.Second)
|
time.Sleep(1 * time.Second)
|
||||||
|
|
|
@ -16,21 +16,26 @@
|
||||||
package notifiers
|
package notifiers
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
|
||||||
"github.com/statping/statping/types/failures"
|
"github.com/statping/statping/types/failures"
|
||||||
|
"github.com/statping/statping/types/notifications"
|
||||||
|
"github.com/statping/statping/types/notifier"
|
||||||
"github.com/statping/statping/types/services"
|
"github.com/statping/statping/types/services"
|
||||||
"github.com/statping/statping/utils"
|
"github.com/statping/statping/utils"
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
var _ Notifier = (*commandLine)(nil)
|
var _ notifier.Notifier = (*commandLine)(nil)
|
||||||
|
|
||||||
type commandLine struct {
|
type commandLine struct {
|
||||||
*Notification
|
*notifications.Notification
|
||||||
}
|
}
|
||||||
|
|
||||||
var Command = &commandLine{&Notification{
|
func (c *commandLine) Select() *notifications.Notification {
|
||||||
|
return c.Notification
|
||||||
|
}
|
||||||
|
|
||||||
|
var Command = &commandLine{¬ifications.Notification{
|
||||||
Method: "command",
|
Method: "command",
|
||||||
Title: "Shell Command",
|
Title: "Shell Command",
|
||||||
Description: "Shell Command allows you to run a customized shell/bash Command on the local machine it's running on.",
|
Description: "Shell Command allows you to run a customized shell/bash Command on the local machine it's running on.",
|
||||||
|
@ -39,7 +44,7 @@ var Command = &commandLine{&Notification{
|
||||||
Delay: time.Duration(1 * time.Second),
|
Delay: time.Duration(1 * time.Second),
|
||||||
Icon: "fas fa-terminal",
|
Icon: "fas fa-terminal",
|
||||||
Host: "/bin/bash",
|
Host: "/bin/bash",
|
||||||
Form: []NotificationForm{{
|
Form: []notifications.NotificationForm{{
|
||||||
Type: "text",
|
Type: "text",
|
||||||
Title: "Shell or Bash",
|
Title: "Shell or Bash",
|
||||||
Placeholder: "/bin/bash",
|
Placeholder: "/bin/bash",
|
||||||
|
@ -65,28 +70,18 @@ func runCommand(app string, cmd ...string) (string, string, error) {
|
||||||
return outStr, errStr, err
|
return outStr, errStr, err
|
||||||
}
|
}
|
||||||
|
|
||||||
func (u *commandLine) Select() *Notification {
|
|
||||||
return u.Notification
|
|
||||||
}
|
|
||||||
|
|
||||||
// OnFailure for commandLine will trigger failing service
|
// OnFailure for commandLine will trigger failing service
|
||||||
func (u *commandLine) OnFailure(s *services.Service, f *failures.Failure) {
|
func (u *commandLine) OnFailure(s *services.Service, f *failures.Failure) error {
|
||||||
u.AddQueue(fmt.Sprintf("service_%v", s.Id), u.Var2)
|
msg := u.GetValue("host")
|
||||||
|
_, _, err := runCommand(u.Host, msg)
|
||||||
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
// OnSuccess for commandLine will trigger successful service
|
// OnSuccess for commandLine will trigger successful service
|
||||||
func (u *commandLine) OnSuccess(s *services.Service) {
|
func (u *commandLine) OnSuccess(s *services.Service) error {
|
||||||
if !s.Online {
|
msg := u.GetValue("host")
|
||||||
u.ResetUniqueQueue(fmt.Sprintf("service_%v", s.Id))
|
_, _, err := runCommand(u.Host, msg)
|
||||||
u.AddQueue(fmt.Sprintf("service_%v", s.Id), u.Var1)
|
return err
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// OnSave for commandLine triggers when this notifier has been saved
|
|
||||||
func (u *commandLine) OnSave() error {
|
|
||||||
u.AddQueue("saved", u.Var1)
|
|
||||||
u.AddQueue("saved", u.Var2)
|
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// OnTest for commandLine triggers when this notifier has been saved
|
// OnTest for commandLine triggers when this notifier has been saved
|
||||||
|
@ -97,10 +92,3 @@ func (u *commandLine) OnTest() error {
|
||||||
utils.Log.Infoln(out)
|
utils.Log.Infoln(out)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
// Send for commandLine will send message to expo Command push notifications endpoint
|
|
||||||
func (u *commandLine) Send(msg interface{}) error {
|
|
||||||
cmd := msg.(string)
|
|
||||||
_, _, err := runCommand(u.Host, cmd)
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
|
@ -21,19 +21,21 @@ import (
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/statping/statping/types/failures"
|
"github.com/statping/statping/types/failures"
|
||||||
|
"github.com/statping/statping/types/notifications"
|
||||||
|
"github.com/statping/statping/types/notifier"
|
||||||
"github.com/statping/statping/types/services"
|
"github.com/statping/statping/types/services"
|
||||||
"github.com/statping/statping/utils"
|
"github.com/statping/statping/utils"
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
var _ Notifier = (*discord)(nil)
|
var _ notifier.Notifier = (*discord)(nil)
|
||||||
|
|
||||||
type discord struct {
|
type discord struct {
|
||||||
*Notification
|
*notifications.Notification
|
||||||
}
|
}
|
||||||
|
|
||||||
var Discorder = &discord{&Notification{
|
var Discorder = &discord{¬ifications.Notification{
|
||||||
Method: "discord",
|
Method: "discord",
|
||||||
Title: "discord",
|
Title: "discord",
|
||||||
Description: "Send notifications to your discord channel using discord webhooks. Insert your discord channel Webhook URL to receive notifications. Based on the <a href=\"https://discordapp.com/developers/docs/resources/Webhook\">discord webhooker API</a>.",
|
Description: "Send notifications to your discord channel using discord webhooks. Insert your discord channel Webhook URL to receive notifications. Based on the <a href=\"https://discordapp.com/developers/docs/resources/Webhook\">discord webhooker API</a>.",
|
||||||
|
@ -42,7 +44,7 @@ var Discorder = &discord{&Notification{
|
||||||
Delay: time.Duration(5 * time.Second),
|
Delay: time.Duration(5 * time.Second),
|
||||||
Host: "https://discordapp.com/api/webhooks/****/*****",
|
Host: "https://discordapp.com/api/webhooks/****/*****",
|
||||||
Icon: "fab fa-discord",
|
Icon: "fab fa-discord",
|
||||||
Form: []NotificationForm{{
|
Form: []notifications.NotificationForm{{
|
||||||
Type: "text",
|
Type: "text",
|
||||||
Title: "discord webhooker URL",
|
Title: "discord webhooker URL",
|
||||||
Placeholder: "Insert your Webhook URL here",
|
Placeholder: "Insert your Webhook URL here",
|
||||||
|
@ -51,38 +53,25 @@ var Discorder = &discord{&Notification{
|
||||||
}
|
}
|
||||||
|
|
||||||
// Send will send a HTTP Post to the discord API. It accepts type: []byte
|
// Send will send a HTTP Post to the discord API. It accepts type: []byte
|
||||||
func (u *discord) Send(msg interface{}) error {
|
func (u *discord) sendRequest(msg string) error {
|
||||||
message := msg.(string)
|
_, _, err := utils.HttpRequest(Discorder.GetValue("host"), "POST", "application/json", nil, strings.NewReader(msg), time.Duration(10*time.Second), true)
|
||||||
_, _, err := utils.HttpRequest(Discorder.GetValue("host"), "POST", "application/json", nil, strings.NewReader(message), time.Duration(10*time.Second), true)
|
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
func (u *discord) Select() *Notification {
|
func (u *discord) Select() *notifications.Notification {
|
||||||
return u.Notification
|
return u.Notification
|
||||||
}
|
}
|
||||||
|
|
||||||
// OnFailure will trigger failing service
|
// OnFailure will trigger failing service
|
||||||
func (u *discord) OnFailure(s *services.Service, f *failures.Failure) {
|
func (u *discord) OnFailure(s *services.Service, f *failures.Failure) error {
|
||||||
msg := fmt.Sprintf(`{"content": "Your service '%v' is currently failing! Reason: %v"}`, s.Name, f.Issue)
|
msg := fmt.Sprintf(`{"content": "Your service '%v' is currently failing! Reason: %v"}`, s.Name, f.Issue)
|
||||||
u.AddQueue(fmt.Sprintf("service_%v", s.Id), msg)
|
return u.sendRequest(msg)
|
||||||
}
|
}
|
||||||
|
|
||||||
// OnSuccess will trigger successful service
|
// OnSuccess will trigger successful service
|
||||||
func (u *discord) OnSuccess(s *services.Service) {
|
func (u *discord) OnSuccess(s *services.Service) error {
|
||||||
if !s.Online || !s.SuccessNotified {
|
msg := fmt.Sprintf(`{"content": "Your service '%s' is currently online!"}`, s.Name)
|
||||||
u.ResetUniqueQueue(fmt.Sprintf("service_%v", s.Id))
|
return u.sendRequest(msg)
|
||||||
var msg interface{}
|
|
||||||
msg = s.DownText
|
|
||||||
|
|
||||||
u.AddQueue(fmt.Sprintf("service_%v", s.Id), msg)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// OnSave triggers when this notifier has been saved
|
|
||||||
func (u *discord) OnSave() error {
|
|
||||||
msg := fmt.Sprintf(`{"content": "The discord notifier on Statping was just updated."}`)
|
|
||||||
u.AddQueue("saved", msg)
|
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// OnSave triggers when this notifier has been saved
|
// OnSave triggers when this notifier has been saved
|
||||||
|
|
|
@ -1,9 +0,0 @@
|
||||||
// Package notifiers holds all the notifiers for Statping, which also includes
|
|
||||||
// user created notifiers that have been accepted in a Push Request. Read the wiki
|
|
||||||
// to see a full example of a notifier with all events, visit Statping's
|
|
||||||
// notifier example code: https://github.com/statping/statping/wiki/Notifier-Example
|
|
||||||
//
|
|
||||||
// This package shouldn't contain any exports, to see how notifiers work
|
|
||||||
// visit the core/notifier package at: https://godoc.org/github.com/statping/statping/core/notifier
|
|
||||||
// and learn how to create your own custom notifier.
|
|
||||||
package notifiers
|
|
|
@ -21,6 +21,8 @@ import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/go-mail/mail"
|
"github.com/go-mail/mail"
|
||||||
"github.com/statping/statping/types/failures"
|
"github.com/statping/statping/types/failures"
|
||||||
|
"github.com/statping/statping/types/notifications"
|
||||||
|
"github.com/statping/statping/types/notifier"
|
||||||
"github.com/statping/statping/types/null"
|
"github.com/statping/statping/types/null"
|
||||||
"github.com/statping/statping/types/services"
|
"github.com/statping/statping/types/services"
|
||||||
"github.com/statping/statping/utils"
|
"github.com/statping/statping/utils"
|
||||||
|
@ -28,7 +30,7 @@ import (
|
||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
var _ Notifier = (*email)(nil)
|
var _ notifier.Notifier = (*emailer)(nil)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
mainEmailTemplate = `<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
|
mainEmailTemplate = `<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
|
||||||
|
@ -110,18 +112,22 @@ var (
|
||||||
mailer *mail.Dialer
|
mailer *mail.Dialer
|
||||||
)
|
)
|
||||||
|
|
||||||
type email struct {
|
type emailer struct {
|
||||||
*Notification
|
*notifications.Notification
|
||||||
}
|
}
|
||||||
|
|
||||||
var Emailer = &email{&Notification{
|
func (e *emailer) Select() *notifications.Notification {
|
||||||
|
return e.Notification
|
||||||
|
}
|
||||||
|
|
||||||
|
var email = &emailer{¬ifications.Notification{
|
||||||
Method: "email",
|
Method: "email",
|
||||||
Title: "email",
|
Title: "email",
|
||||||
Description: "Send emails via SMTP when services are online or offline.",
|
Description: "Send emails via SMTP when services are online or offline.",
|
||||||
Author: "Hunter Long",
|
Author: "Hunter Long",
|
||||||
AuthorUrl: "https://github.com/hunterlong",
|
AuthorUrl: "https://github.com/hunterlong",
|
||||||
Icon: "far fa-envelope",
|
Icon: "far fa-envelope",
|
||||||
Form: []NotificationForm{{
|
Form: []notifications.NotificationForm{{
|
||||||
Type: "text",
|
Type: "text",
|
||||||
Title: "SMTP Host",
|
Title: "SMTP Host",
|
||||||
Placeholder: "Insert your SMTP Host here.",
|
Placeholder: "Insert your SMTP Host here.",
|
||||||
|
@ -157,17 +163,7 @@ var Emailer = &email{&Notification{
|
||||||
Placeholder: "",
|
Placeholder: "",
|
||||||
SmallText: "To Disable TLS/SSL insert 'true'",
|
SmallText: "To Disable TLS/SSL insert 'true'",
|
||||||
DbField: "api_key",
|
DbField: "api_key",
|
||||||
}},
|
}}},
|
||||||
}}
|
|
||||||
|
|
||||||
// Send will send the SMTP email with your authentication It accepts type: *emailOutgoing
|
|
||||||
func (u *email) Send(msg interface{}) error {
|
|
||||||
email := msg.(*emailOutgoing)
|
|
||||||
err := u.dialSend(email)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
type emailOutgoing struct {
|
type emailOutgoing struct {
|
||||||
|
@ -181,7 +177,7 @@ type emailOutgoing struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
// OnFailure will trigger failing service
|
// OnFailure will trigger failing service
|
||||||
func (u *email) OnFailure(s *services.Service, f *failures.Failure) {
|
func (u *emailer) OnFailure(s *services.Service, f *failures.Failure) error {
|
||||||
email := &emailOutgoing{
|
email := &emailOutgoing{
|
||||||
To: u.Var2,
|
To: u.Var2,
|
||||||
Subject: fmt.Sprintf("Service %v is Failing", s.Name),
|
Subject: fmt.Sprintf("Service %v is Failing", s.Name),
|
||||||
|
@ -189,40 +185,24 @@ func (u *email) OnFailure(s *services.Service, f *failures.Failure) {
|
||||||
Data: interface{}(s),
|
Data: interface{}(s),
|
||||||
From: u.Var1,
|
From: u.Var1,
|
||||||
}
|
}
|
||||||
u.AddQueue(fmt.Sprintf("service_%v", s.Id), email)
|
return u.dialSend(email)
|
||||||
}
|
}
|
||||||
|
|
||||||
// OnSuccess will trigger successful service
|
// OnSuccess will trigger successful service
|
||||||
func (u *email) OnSuccess(s *services.Service) {
|
func (u *emailer) OnSuccess(s *services.Service) error {
|
||||||
if !s.Online || !s.SuccessNotified {
|
msg := s.DownText
|
||||||
var msg string
|
email := &emailOutgoing{
|
||||||
msg = s.DownText
|
To: u.Var2,
|
||||||
|
Subject: msg,
|
||||||
u.ResetUniqueQueue(fmt.Sprintf("service_%v", s.Id))
|
Template: mainEmailTemplate,
|
||||||
email := &emailOutgoing{
|
Data: interface{}(s),
|
||||||
To: u.Var2,
|
From: u.Var1,
|
||||||
Subject: msg,
|
|
||||||
Template: mainEmailTemplate,
|
|
||||||
Data: interface{}(s),
|
|
||||||
From: u.Var1,
|
|
||||||
}
|
|
||||||
u.AddQueue(fmt.Sprintf("service_%v", s.Id), email)
|
|
||||||
}
|
}
|
||||||
}
|
return u.dialSend(email)
|
||||||
|
|
||||||
func (u *email) Select() *Notification {
|
|
||||||
return u.Notification
|
|
||||||
}
|
|
||||||
|
|
||||||
// OnSave triggers when this notifier has been saved
|
|
||||||
func (u *email) OnSave() error {
|
|
||||||
utils.Log.Infoln(fmt.Sprintf("Notification %v is receiving updated information.", u.Method))
|
|
||||||
// Do updating stuff here
|
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// OnTest triggers when this notifier has been saved
|
// OnTest triggers when this notifier has been saved
|
||||||
func (u *email) OnTest() error {
|
func (u *emailer) OnTest() error {
|
||||||
testService := &services.Service{
|
testService := &services.Service{
|
||||||
Id: 1,
|
Id: 1,
|
||||||
Name: "Example Service",
|
Name: "Example Service",
|
||||||
|
@ -247,8 +227,8 @@ func (u *email) OnTest() error {
|
||||||
return u.dialSend(email)
|
return u.dialSend(email)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (u *email) dialSend(email *emailOutgoing) error {
|
func (u *emailer) dialSend(email *emailOutgoing) error {
|
||||||
mailer = mail.NewDialer(Emailer.Host, Emailer.Port, Emailer.Username, Emailer.Password)
|
mailer = mail.NewDialer(u.Host, u.Port, u.Username, u.Password)
|
||||||
emailSource(email)
|
emailSource(email)
|
||||||
m := mail.NewMessage()
|
m := mail.NewMessage()
|
||||||
// if email setting TLS is Disabled
|
// if email setting TLS is Disabled
|
||||||
|
|
|
@ -1,203 +0,0 @@
|
||||||
// Statping
|
|
||||||
// Copyright (C) 2018. Hunter Long and the project contributors
|
|
||||||
// Written by Hunter Long <info@socialeck.com> and the project contributors
|
|
||||||
//
|
|
||||||
// https://github.com/statping/statping
|
|
||||||
//
|
|
||||||
// The licenses for most software and other practical works are designed
|
|
||||||
// to take away your freedom to share and change the works. By contrast,
|
|
||||||
// the GNU General Public License is intended to guarantee your freedom to
|
|
||||||
// share and change all versions of a program--to make sure it remains free
|
|
||||||
// software for all its users.
|
|
||||||
//
|
|
||||||
// You should have received a copy of the GNU General Public License
|
|
||||||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
|
|
||||||
package notifiers
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
"github.com/statping/statping/types/failures"
|
|
||||||
"github.com/statping/statping/types/services"
|
|
||||||
"github.com/statping/statping/types/users"
|
|
||||||
"github.com/statping/statping/utils"
|
|
||||||
)
|
|
||||||
|
|
||||||
// OnSave will trigger a notifier when it has been saved - Notifier interface
|
|
||||||
func OnSave(method string) {
|
|
||||||
for _, comm := range allNotifiers {
|
|
||||||
if utils.IsType(comm, new(Notifier)) {
|
|
||||||
notifier := comm.Select()
|
|
||||||
if notifier.Method == method {
|
|
||||||
comm.OnSave()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// OnFailure will be triggered when a service is failing - BasicEvents interface
|
|
||||||
func OnFailure(s *services.Service, f *failures.Failure) {
|
|
||||||
if !s.AllowNotifications.Bool {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// check if User wants to receive every Status Change
|
|
||||||
if s.UpdateNotify.Bool {
|
|
||||||
// send only if User hasn't been already notified about the Downtime
|
|
||||||
if !s.UserNotified {
|
|
||||||
s.UserNotified = true
|
|
||||||
goto sendMessages
|
|
||||||
} else {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
sendMessages:
|
|
||||||
for _, comm := range allNotifiers {
|
|
||||||
if utils.IsType(comm, new(BasicEvents)) && isEnabled(comm) && (s.Online || inLimits(comm)) {
|
|
||||||
notifier := comm.(*Notification)
|
|
||||||
log.
|
|
||||||
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++
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// OnSuccess will be triggered when a service is successful - BasicEvents interface
|
|
||||||
func OnSuccess(s *services.Service) {
|
|
||||||
if !s.AllowNotifications.Bool {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// check if User wants to receive every Status Change
|
|
||||||
if s.UpdateNotify.Bool && s.UserNotified {
|
|
||||||
s.UserNotified = false
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, comm := range allNotifiers {
|
|
||||||
if utils.IsType(comm, new(BasicEvents)) && isEnabled(comm) && (!s.Online || inLimits(comm)) {
|
|
||||||
notifier := comm.(*Notification)
|
|
||||||
log.
|
|
||||||
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++
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// OnNewService is triggered when a new service is created - ServiceEvents interface
|
|
||||||
func OnNewService(s *services.Service) {
|
|
||||||
for _, comm := range allNotifiers {
|
|
||||||
if utils.IsType(comm, new(ServiceEvents)) && isEnabled(comm) && inLimits(comm) {
|
|
||||||
log.
|
|
||||||
WithField("trigger", "OnNewService").
|
|
||||||
Debugln(fmt.Sprintf("Sending new service notification for service %v", s.Name))
|
|
||||||
comm.(ServiceEvents).OnNewService(s)
|
|
||||||
comm.Select().Hits.OnNewService++
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// OnUpdatedService is triggered when a service is updated - ServiceEvents interface
|
|
||||||
func OnUpdatedService(s *services.Service) {
|
|
||||||
if !s.AllowNotifications.Bool {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
for _, comm := range allNotifiers {
|
|
||||||
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++
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// OnDeletedService is triggered when a service is deleted - ServiceEvents interface
|
|
||||||
func OnDeletedService(s *services.Service) {
|
|
||||||
if !s.AllowNotifications.Bool {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
for _, comm := range allNotifiers {
|
|
||||||
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++
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// OnNewUser is triggered when a new user is created - UserEvents interface
|
|
||||||
func OnNewUser(u *users.User) {
|
|
||||||
for _, comm := range allNotifiers {
|
|
||||||
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++
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// OnUpdatedUser is triggered when a new user is updated - UserEvents interface
|
|
||||||
func OnUpdatedUser(u *users.User) {
|
|
||||||
for _, comm := range allNotifiers {
|
|
||||||
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++
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// OnDeletedUser is triggered when a new user is deleted - UserEvents interface
|
|
||||||
func OnDeletedUser(u *users.User) {
|
|
||||||
for _, comm := range allNotifiers {
|
|
||||||
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++
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//// OnUpdatedCore is triggered when the CoreApp settings are saved - CoreEvents interface
|
|
||||||
//func OnUpdatedCore(c *core.Core) {
|
|
||||||
// for _, comm := range allNotifiers {
|
|
||||||
// if utils.IsType(comm, new(CoreEvents)) && isEnabled(comm) && inLimits(comm) {
|
|
||||||
// log.Debugln(fmt.Sprintf("Sending updated core notification"))
|
|
||||||
// comm.(CoreEvents).OnUpdatedCore(c)
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
//}
|
|
||||||
//
|
|
||||||
//// OnStart is triggered when the Statping service has started
|
|
||||||
//func OnStart(c *core.Core) {
|
|
||||||
// for _, comm := range allNotifiers {
|
|
||||||
// if utils.IsType(comm, new(CoreEvents)) && isEnabled(comm) && inLimits(comm) {
|
|
||||||
// comm.(CoreEvents).OnUpdatedCore(c)
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
//}
|
|
||||||
|
|
||||||
// OnNewNotifier is triggered when a new notifier is loaded
|
|
||||||
func OnNewNotifier(n *Notification) {
|
|
||||||
for _, comm := range allNotifiers {
|
|
||||||
if utils.IsType(comm, new(NotifierEvents)) && isEnabled(comm) && inLimits(comm) {
|
|
||||||
comm.(NotifierEvents).OnNewNotifier(n)
|
|
||||||
comm.Select().Hits.OnNewNotifier++
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// OnUpdatedNotifier is triggered when a notifier has been updated
|
|
||||||
func OnUpdatedNotifier(n *Notification) {
|
|
||||||
for _, comm := range allNotifiers {
|
|
||||||
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++
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,120 +0,0 @@
|
||||||
// Package notifier contains the main functionality for the Statping Notification system
|
|
||||||
//
|
|
||||||
// Example Notifier
|
|
||||||
//
|
|
||||||
// Below is an example of a Notifier with multiple Form values to custom your inputs. Place your notifier go file
|
|
||||||
// into the /notifiers/ directory and follow the example below.
|
|
||||||
//
|
|
||||||
// type ExampleNotifier struct {
|
|
||||||
// *Notification
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// var example = &ExampleNotifier{&Notification{
|
|
||||||
// Method: "example",
|
|
||||||
// Title: "Example Notifier",
|
|
||||||
// Description: "This is an example of a notifier for Statping!",
|
|
||||||
// Author: "Hunter Long",
|
|
||||||
// AuthorUrl: "https://github.com/hunterlong",
|
|
||||||
// Delay: time.Duration(3 * time.Second),
|
|
||||||
// Limits: 7,
|
|
||||||
// Form: []NotificationForm{{
|
|
||||||
// Type: "text",
|
|
||||||
// Title: "Host",
|
|
||||||
// Placeholder: "Insert your Host here.",
|
|
||||||
// DbField: "host",
|
|
||||||
// SmallText: "this is where you would put the host",
|
|
||||||
// }, {
|
|
||||||
// Type: "text",
|
|
||||||
// Title: "Username",
|
|
||||||
// Placeholder: "Insert your Username here.",
|
|
||||||
// DbField: "username",
|
|
||||||
// }, {
|
|
||||||
// Type: "password",
|
|
||||||
// Title: "Password",
|
|
||||||
// Placeholder: "Insert your Password here.",
|
|
||||||
// DbField: "password",
|
|
||||||
// }, {
|
|
||||||
// Type: "number",
|
|
||||||
// Title: "Port",
|
|
||||||
// Placeholder: "Insert your Port here.",
|
|
||||||
// DbField: "port",
|
|
||||||
// }, {
|
|
||||||
// Type: "text",
|
|
||||||
// Title: "API Key",
|
|
||||||
// Placeholder: "Insert your API Key here",
|
|
||||||
// DbField: "api_key",
|
|
||||||
// }, {
|
|
||||||
// Type: "text",
|
|
||||||
// Title: "API Secret",
|
|
||||||
// Placeholder: "Insert your API Secret here",
|
|
||||||
// DbField: "api_secret",
|
|
||||||
// }, {
|
|
||||||
// Type: "text",
|
|
||||||
// Title: "Var 1",
|
|
||||||
// Placeholder: "Insert your Var1 here",
|
|
||||||
// DbField: "var1",
|
|
||||||
// }, {
|
|
||||||
// Type: "text",
|
|
||||||
// Title: "Var2",
|
|
||||||
// Placeholder: "Var2 goes here",
|
|
||||||
// DbField: "var2",
|
|
||||||
// }},
|
|
||||||
// }}
|
|
||||||
//
|
|
||||||
// Load the Notifier
|
|
||||||
//
|
|
||||||
// Include the init() function with AddNotifier and your notification struct. This is ran on start of Statping
|
|
||||||
// and will automatically create a new row in the database so the end user can save their own values.
|
|
||||||
//
|
|
||||||
// func init() {
|
|
||||||
// AddNotifier(example)
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// Required Methods for Notifier Interface
|
|
||||||
//
|
|
||||||
// Below are the required methods to have your notifier implement the Notifier interface. The Send method
|
|
||||||
// will be where you would include the logic for your notification.
|
|
||||||
//
|
|
||||||
// // REQUIRED
|
|
||||||
// func (n *ExampleNotifier) Send(msg interface{}) error {
|
|
||||||
// message := msg.(string)
|
|
||||||
// fmt.Printf("i received this string: %v\n", message)
|
|
||||||
// return nil
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// // REQUIRED
|
|
||||||
// func (n *ExampleNotifier) Select() *Notification {
|
|
||||||
// return n.Notification
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// // REQUIRED
|
|
||||||
// func (n *ExampleNotifier) OnSave() error {
|
|
||||||
// msg := fmt.Sprintf("received on save trigger")
|
|
||||||
// n.AddQueue(msg)
|
|
||||||
// return errors.New("onsave triggered")
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// Basic Events for Notifier
|
|
||||||
//
|
|
||||||
// You must include OnSuccess and OnFailure methods for your notifier. Anytime a service is online or offline
|
|
||||||
// these methods will be ran with the service corresponding to it.
|
|
||||||
//
|
|
||||||
// // REQUIRED - BASIC EVENT
|
|
||||||
// func (n *ExampleNotifier) OnSuccess(s *services.Service) {
|
|
||||||
// msg := fmt.Sprintf("received a count trigger for service: %v\n", s.Name)
|
|
||||||
// n.AddQueue(msg)
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// // REQUIRED - BASIC EVENT
|
|
||||||
// func (n *ExampleNotifier) OnFailure(s *services.Service, f *types.Failure) {
|
|
||||||
// msg := fmt.Sprintf("received a failure trigger for service: %v\n", s.Name)
|
|
||||||
// n.AddQueue(msg)
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// Additional Events
|
|
||||||
//
|
|
||||||
// You can implement your notifier to different types of events that are triggered. Checkout the wiki to
|
|
||||||
// see more details and examples of how to build your own notifier.
|
|
||||||
//
|
|
||||||
// More info on: https://github.com/statping/statping/wiki/Notifiers
|
|
||||||
package _interface
|
|
|
@ -1,72 +0,0 @@
|
||||||
// Statping
|
|
||||||
// Copyright (C) 2018. Hunter Long and the project contributors
|
|
||||||
// Written by Hunter Long <info@socialeck.com> and the project contributors
|
|
||||||
//
|
|
||||||
// https://github.com/statping/statping
|
|
||||||
//
|
|
||||||
// The licenses for most software and other practical works are designed
|
|
||||||
// to take away your freedom to share and change the works. By contrast,
|
|
||||||
// the GNU General Public License is intended to guarantee your freedom to
|
|
||||||
// share and change all versions of a program--to make sure it remains free
|
|
||||||
// software for all its users.
|
|
||||||
//
|
|
||||||
// You should have received a copy of the GNU General Public License
|
|
||||||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
|
|
||||||
package notifiers
|
|
||||||
|
|
||||||
import (
|
|
||||||
"github.com/statping/statping/types/failures"
|
|
||||||
"github.com/statping/statping/types/services"
|
|
||||||
"github.com/statping/statping/types/users"
|
|
||||||
)
|
|
||||||
|
|
||||||
// Notifier interface is required to create a new Notifier
|
|
||||||
type Notifier interface {
|
|
||||||
OnSave() error // OnSave is triggered when the notifier is saved
|
|
||||||
Send(interface{}) error // OnSave is triggered when the notifier is saved
|
|
||||||
Select() *Notification // Select returns the *Notification for a notifier
|
|
||||||
}
|
|
||||||
|
|
||||||
// BasicEvents includes the most minimal events, failing and successful service triggers
|
|
||||||
type BasicEvents interface {
|
|
||||||
OnSuccess(*services.Service) // OnSuccess is triggered when a service is successful
|
|
||||||
OnFailure(*services.Service, *failures.Failure) // OnFailure is triggered when a service is failing
|
|
||||||
}
|
|
||||||
|
|
||||||
// Tester interface will include a function to Test users settings before saving
|
|
||||||
type Tester interface {
|
|
||||||
OnTest() error
|
|
||||||
}
|
|
||||||
|
|
||||||
// ServiceEvents are events for Services
|
|
||||||
type ServiceEvents interface {
|
|
||||||
OnNewService(*services.Service)
|
|
||||||
OnUpdatedService(*services.Service)
|
|
||||||
OnDeletedService(*services.Service)
|
|
||||||
}
|
|
||||||
|
|
||||||
// UserEvents are events for Users
|
|
||||||
type UserEvents interface {
|
|
||||||
OnNewUser(*users.User)
|
|
||||||
OnUpdatedUser(*users.User)
|
|
||||||
OnDeletedUser(*users.User)
|
|
||||||
}
|
|
||||||
|
|
||||||
// CoreEvents are events for the main Core app
|
|
||||||
//type CoreEvents interface {
|
|
||||||
// OnUpdatedCore(*core.Core)
|
|
||||||
// OnStart(*core.Core)
|
|
||||||
//}
|
|
||||||
|
|
||||||
// NotifierEvents are events for other Notifiers
|
|
||||||
type NotifierEvents interface {
|
|
||||||
OnNewNotifier(*Notification)
|
|
||||||
OnUpdatedNotifier(*Notification)
|
|
||||||
}
|
|
||||||
|
|
||||||
// HTTPRouter interface will allow your notifier to accept http GET/POST requests
|
|
||||||
type HTTPRouter interface {
|
|
||||||
OnGET() error
|
|
||||||
OnPOST() error
|
|
||||||
}
|
|
|
@ -18,6 +18,8 @@ package notifiers
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/statping/statping/types/failures"
|
"github.com/statping/statping/types/failures"
|
||||||
|
"github.com/statping/statping/types/notifications"
|
||||||
|
"github.com/statping/statping/types/notifier"
|
||||||
"github.com/statping/statping/types/services"
|
"github.com/statping/statping/types/services"
|
||||||
"github.com/statping/statping/utils"
|
"github.com/statping/statping/utils"
|
||||||
"net/url"
|
"net/url"
|
||||||
|
@ -25,24 +27,28 @@ import (
|
||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
var _ Notifier = (*lineNotifier)(nil)
|
var _ notifier.Notifier = (*lineNotifier)(nil)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
lineNotifyMethod = "line_notify"
|
lineNotifyMethod = "line_notify"
|
||||||
)
|
)
|
||||||
|
|
||||||
type lineNotifier struct {
|
type lineNotifier struct {
|
||||||
*Notification
|
*notifications.Notification
|
||||||
}
|
}
|
||||||
|
|
||||||
var LineNotify = &lineNotifier{&Notification{
|
func (l *lineNotifier) Select() *notifications.Notification {
|
||||||
|
return l.Notification
|
||||||
|
}
|
||||||
|
|
||||||
|
var LineNotify = &lineNotifier{¬ifications.Notification{
|
||||||
Method: lineNotifyMethod,
|
Method: lineNotifyMethod,
|
||||||
Title: "LINE Notify",
|
Title: "LINE Notify",
|
||||||
Description: "LINE Notify will send notifications to your LINE Notify account when services are offline or online. Based on the <a href=\"https://notify-bot.line.me/doc/en/\">LINE Notify API</a>.",
|
Description: "LINE Notify will send notifications to your LINE Notify account when services are offline or online. Based on the <a href=\"https://notify-bot.line.me/doc/en/\">LINE Notify API</a>.",
|
||||||
Author: "Kanin Peanviriyakulkit",
|
Author: "Kanin Peanviriyakulkit",
|
||||||
AuthorUrl: "https://github.com/dogrocker",
|
AuthorUrl: "https://github.com/dogrocker",
|
||||||
Icon: "far fa-bell",
|
Icon: "far fa-bell",
|
||||||
Form: []NotificationForm{{
|
Form: []notifications.NotificationForm{{
|
||||||
Type: "text",
|
Type: "text",
|
||||||
Title: "Access Token",
|
Title: "Access Token",
|
||||||
Placeholder: "Insert your Line Notify Access Token here.",
|
Placeholder: "Insert your Line Notify Access Token here.",
|
||||||
|
@ -51,8 +57,7 @@ var LineNotify = &lineNotifier{&Notification{
|
||||||
}
|
}
|
||||||
|
|
||||||
// Send will send a HTTP Post with the Authorization to the notify-api.line.me server. It accepts type: string
|
// Send will send a HTTP Post with the Authorization to the notify-api.line.me server. It accepts type: string
|
||||||
func (u *lineNotifier) Send(msg interface{}) error {
|
func (u *lineNotifier) sendMessage(message string) error {
|
||||||
message := msg.(string)
|
|
||||||
v := url.Values{}
|
v := url.Values{}
|
||||||
v.Set("message", message)
|
v.Set("message", message)
|
||||||
headers := []string{fmt.Sprintf("Authorization=Bearer %v", u.ApiSecret)}
|
headers := []string{fmt.Sprintf("Authorization=Bearer %v", u.ApiSecret)}
|
||||||
|
@ -60,31 +65,20 @@ func (u *lineNotifier) Send(msg interface{}) error {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
func (u *lineNotifier) Select() *Notification {
|
|
||||||
return u.Notification
|
|
||||||
}
|
|
||||||
|
|
||||||
// OnFailure will trigger failing service
|
// OnFailure will trigger failing service
|
||||||
func (u *lineNotifier) OnFailure(s *services.Service, f *failures.Failure) {
|
func (u *lineNotifier) OnFailure(s *services.Service, f *failures.Failure) error {
|
||||||
msg := fmt.Sprintf("Your service '%v' is currently offline!", s.Name)
|
msg := fmt.Sprintf("Your service '%v' is currently offline!", s.Name)
|
||||||
u.AddQueue(fmt.Sprintf("service_%v", s.Id), msg)
|
return u.sendMessage(msg)
|
||||||
}
|
}
|
||||||
|
|
||||||
// OnSuccess will trigger successful service
|
// OnSuccess will trigger successful service
|
||||||
func (u *lineNotifier) OnSuccess(s *services.Service) {
|
func (u *lineNotifier) OnSuccess(s *services.Service) error {
|
||||||
if !s.Online || !s.SuccessNotified {
|
msg := fmt.Sprintf("Service %s is online!", s.Name)
|
||||||
var msg string
|
return u.sendMessage(msg)
|
||||||
msg = s.DownText
|
|
||||||
|
|
||||||
u.ResetUniqueQueue(fmt.Sprintf("service_%v", s.Id))
|
|
||||||
u.AddQueue(fmt.Sprintf("service_%v", s.Id), msg)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// OnSave triggers when this notifier has been saved
|
// OnTest triggers when this notifier has been saved
|
||||||
func (u *lineNotifier) OnSave() error {
|
func (u *lineNotifier) OnTest() error {
|
||||||
msg := fmt.Sprintf("Notification %v is receiving updated information.", u.Method)
|
msg := fmt.Sprintf("Testing if Line Notifier is working!")
|
||||||
utils.Log.Infoln(msg)
|
return u.sendMessage(msg)
|
||||||
u.AddQueue("saved", msg)
|
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,20 +20,26 @@ import (
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/statping/statping/types/failures"
|
"github.com/statping/statping/types/failures"
|
||||||
|
"github.com/statping/statping/types/notifications"
|
||||||
|
"github.com/statping/statping/types/notifier"
|
||||||
"github.com/statping/statping/types/services"
|
"github.com/statping/statping/types/services"
|
||||||
"github.com/statping/statping/utils"
|
"github.com/statping/statping/utils"
|
||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
var _ Notifier = (*mobilePush)(nil)
|
var _ notifier.Notifier = (*mobilePush)(nil)
|
||||||
|
|
||||||
const mobileIdentifier = "com.statping"
|
const mobileIdentifier = "com.statping"
|
||||||
|
|
||||||
type mobilePush struct {
|
type mobilePush struct {
|
||||||
*Notification
|
*notifications.Notification
|
||||||
}
|
}
|
||||||
|
|
||||||
var Mobile = &mobilePush{&Notification{
|
func (m *mobilePush) Select() *notifications.Notification {
|
||||||
|
return m.Notification
|
||||||
|
}
|
||||||
|
|
||||||
|
var Mobile = &mobilePush{¬ifications.Notification{
|
||||||
Method: "mobile",
|
Method: "mobile",
|
||||||
Title: "Mobile Notifications",
|
Title: "Mobile Notifications",
|
||||||
Description: `Receive push notifications on your Mobile device using the Statping App. You can scan the Authentication QR Code found in Settings to get the Mobile app setup in seconds.
|
Description: `Receive push notifications on your Mobile device using the Statping App. You can scan the Authentication QR Code found in Settings to get the Mobile app setup in seconds.
|
||||||
|
@ -42,7 +48,7 @@ var Mobile = &mobilePush{&Notification{
|
||||||
AuthorUrl: "https://github.com/hunterlong",
|
AuthorUrl: "https://github.com/hunterlong",
|
||||||
Delay: time.Duration(5 * time.Second),
|
Delay: time.Duration(5 * time.Second),
|
||||||
Icon: "fas fa-mobile-alt",
|
Icon: "fas fa-mobile-alt",
|
||||||
Form: []NotificationForm{{
|
Form: []notifications.NotificationForm{{
|
||||||
Type: "text",
|
Type: "text",
|
||||||
Title: "Device Identifiers",
|
Title: "Device Identifiers",
|
||||||
Placeholder: "A list of your Mobile device push notification ID's.",
|
Placeholder: "A list of your Mobile device push notification ID's.",
|
||||||
|
@ -57,10 +63,6 @@ var Mobile = &mobilePush{&Notification{
|
||||||
}}},
|
}}},
|
||||||
}
|
}
|
||||||
|
|
||||||
func (u *mobilePush) Select() *Notification {
|
|
||||||
return u.Notification
|
|
||||||
}
|
|
||||||
|
|
||||||
func dataJson(s *services.Service, f *failures.Failure) map[string]interface{} {
|
func dataJson(s *services.Service, f *failures.Failure) map[string]interface{} {
|
||||||
serviceId := "0"
|
serviceId := "0"
|
||||||
if s != nil {
|
if s != nil {
|
||||||
|
@ -85,7 +87,7 @@ func dataJson(s *services.Service, f *failures.Failure) map[string]interface{} {
|
||||||
}
|
}
|
||||||
|
|
||||||
// OnFailure will trigger failing service
|
// OnFailure will trigger failing service
|
||||||
func (u *mobilePush) OnFailure(s *services.Service, f *failures.Failure) {
|
func (u *mobilePush) OnFailure(s *services.Service, f *failures.Failure) error {
|
||||||
data := dataJson(s, f)
|
data := dataJson(s, f)
|
||||||
msg := &pushArray{
|
msg := &pushArray{
|
||||||
Message: fmt.Sprintf("Your service '%v' is currently failing! Reason: %v", s.Name, f.Issue),
|
Message: fmt.Sprintf("Your service '%v' is currently failing! Reason: %v", s.Name, f.Issue),
|
||||||
|
@ -93,30 +95,19 @@ func (u *mobilePush) OnFailure(s *services.Service, f *failures.Failure) {
|
||||||
Topic: mobileIdentifier,
|
Topic: mobileIdentifier,
|
||||||
Data: data,
|
Data: data,
|
||||||
}
|
}
|
||||||
u.AddQueue(fmt.Sprintf("service_%v", s.Id), msg)
|
return u.Send(msg)
|
||||||
}
|
}
|
||||||
|
|
||||||
// OnSuccess will trigger successful service
|
// OnSuccess will trigger successful service
|
||||||
func (u *mobilePush) OnSuccess(s *services.Service) {
|
func (u *mobilePush) OnSuccess(s *services.Service) error {
|
||||||
data := dataJson(s, nil)
|
data := dataJson(s, nil)
|
||||||
if !s.Online || !s.SuccessNotified {
|
msg := &pushArray{
|
||||||
var msgStr string
|
Message: "Service is Online!",
|
||||||
msgStr = s.DownText
|
Title: "Service Online",
|
||||||
|
Topic: mobileIdentifier,
|
||||||
u.ResetUniqueQueue(fmt.Sprintf("service_%v", s.Id))
|
Data: data,
|
||||||
msg := &pushArray{
|
|
||||||
Message: msgStr,
|
|
||||||
Title: "Service Online",
|
|
||||||
Topic: mobileIdentifier,
|
|
||||||
Data: data,
|
|
||||||
}
|
|
||||||
u.AddQueue(fmt.Sprintf("service_%v", s.Id), msg)
|
|
||||||
}
|
}
|
||||||
}
|
return u.Send(msg)
|
||||||
|
|
||||||
// OnSave triggers when this notifier has been saved
|
|
||||||
func (u *mobilePush) OnSave() error {
|
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// OnTest triggers when this notifier has been saved
|
// OnTest triggers when this notifier has been saved
|
||||||
|
@ -143,12 +134,10 @@ func (u *mobilePush) OnTest() error {
|
||||||
firstLog := output.Logs[0].Error
|
firstLog := output.Logs[0].Error
|
||||||
return fmt.Errorf("Mobile Notification error: %v", firstLog)
|
return fmt.Errorf("Mobile Notification error: %v", firstLog)
|
||||||
}
|
}
|
||||||
return err
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Send will send message to Statping push notifications endpoint
|
// Send will send message to Statping push notifications endpoint
|
||||||
func (u *mobilePush) Send(msg interface{}) error {
|
func (u *mobilePush) Send(pushMessage *pushArray) error {
|
||||||
pushMessage := msg.(*pushArray)
|
|
||||||
pushMessage.Tokens = []string{u.Var1}
|
pushMessage.Tokens = []string{u.Var1}
|
||||||
pushMessage.Platform = utils.ToInt(u.Var2)
|
pushMessage.Platform = utils.ToInt(u.Var2)
|
||||||
_, err := pushRequest(pushMessage)
|
_, err := pushRequest(pushMessage)
|
||||||
|
|
|
@ -1,135 +0,0 @@
|
||||||
package notifiers
|
|
||||||
|
|
||||||
import (
|
|
||||||
"github.com/statping/statping/database"
|
|
||||||
"github.com/statping/statping/types/null"
|
|
||||||
"github.com/stretchr/testify/assert"
|
|
||||||
"github.com/stretchr/testify/require"
|
|
||||||
"testing"
|
|
||||||
)
|
|
||||||
|
|
||||||
var form1 = NotificationForm{
|
|
||||||
Type: "text",
|
|
||||||
Title: "Example Input",
|
|
||||||
DbField: "Host",
|
|
||||||
Required: true,
|
|
||||||
IsHidden: false,
|
|
||||||
IsList: false,
|
|
||||||
IsSwitch: false,
|
|
||||||
}
|
|
||||||
|
|
||||||
var form2 = NotificationForm{
|
|
||||||
Type: "text",
|
|
||||||
Title: "Example Input 2",
|
|
||||||
DbField: "ApiKey",
|
|
||||||
Required: true,
|
|
||||||
IsHidden: false,
|
|
||||||
IsList: false,
|
|
||||||
IsSwitch: false,
|
|
||||||
}
|
|
||||||
|
|
||||||
var example = &exampleNotif{&Notification{
|
|
||||||
Method: "example",
|
|
||||||
Enabled: null.NewNullBool(true),
|
|
||||||
Limits: 3,
|
|
||||||
Removable: false,
|
|
||||||
Form: []NotificationForm{form1, form2},
|
|
||||||
Delay: 30,
|
|
||||||
}}
|
|
||||||
|
|
||||||
type exampleNotif struct {
|
|
||||||
*Notification
|
|
||||||
}
|
|
||||||
|
|
||||||
func (e *exampleNotif) OnSave() error {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (e *exampleNotif) Select() *Notification {
|
|
||||||
return e.Notification
|
|
||||||
}
|
|
||||||
|
|
||||||
func (e *exampleNotif) Send(data interface{}) error {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestInit(t *testing.T) {
|
|
||||||
db, err := database.OpenTester()
|
|
||||||
require.Nil(t, err)
|
|
||||||
db.CreateTable(&Notification{})
|
|
||||||
db.Create(example.Select())
|
|
||||||
SetDB(db)
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestFind(t *testing.T) {
|
|
||||||
appendList(example)
|
|
||||||
itemer, err := Find(example.Method)
|
|
||||||
require.Nil(t, err)
|
|
||||||
|
|
||||||
item := itemer.Select()
|
|
||||||
require.NotNil(t, item)
|
|
||||||
|
|
||||||
assert.Equal(t, "example", item.Method)
|
|
||||||
assert.Len(t, allNotifiers, 1)
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestAll(t *testing.T) {
|
|
||||||
items := All()
|
|
||||||
assert.Len(t, items, 1)
|
|
||||||
assert.Len(t, allNotifiers, 1)
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestCreate(t *testing.T) {
|
|
||||||
assert.Len(t, allNotifiers, 1)
|
|
||||||
|
|
||||||
example := &Notification{
|
|
||||||
Method: "anotherexample",
|
|
||||||
Title: "Example 2",
|
|
||||||
Description: "New Message here",
|
|
||||||
}
|
|
||||||
err := example.Create()
|
|
||||||
require.Nil(t, err)
|
|
||||||
assert.NotZero(t, example.Id)
|
|
||||||
assert.Equal(t, "anotherexample", example.Method)
|
|
||||||
assert.Equal(t, "Example 2", example.Title)
|
|
||||||
assert.NotZero(t, example.CreatedAt)
|
|
||||||
|
|
||||||
items := All()
|
|
||||||
assert.Len(t, items, 2)
|
|
||||||
assert.Len(t, allNotifiers, 2)
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestUpdate(t *testing.T) {
|
|
||||||
itemer, err := Find("anotherexample")
|
|
||||||
require.Nil(t, err)
|
|
||||||
require.NotNil(t, itemer)
|
|
||||||
|
|
||||||
item := itemer.Select()
|
|
||||||
require.NotNil(t, item)
|
|
||||||
|
|
||||||
item.Host = "Updated Host Var"
|
|
||||||
err = item.Update()
|
|
||||||
require.Nil(t, err)
|
|
||||||
assert.Equal(t, "Updated Host Var", item.Host)
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestDelete(t *testing.T) {
|
|
||||||
all := All()
|
|
||||||
assert.Len(t, all, 2)
|
|
||||||
|
|
||||||
itemer, err := Find("example2")
|
|
||||||
require.Nil(t, err)
|
|
||||||
|
|
||||||
item := itemer.Select()
|
|
||||||
require.NotNil(t, item)
|
|
||||||
|
|
||||||
err = item.Delete()
|
|
||||||
require.Nil(t, err)
|
|
||||||
|
|
||||||
all = All()
|
|
||||||
assert.Len(t, all, 2)
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestClose(t *testing.T) {
|
|
||||||
assert.Nil(t, db.Close())
|
|
||||||
}
|
|
|
@ -2,105 +2,28 @@ package notifiers
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/statping/statping/types/failures"
|
|
||||||
"github.com/statping/statping/types/services"
|
"github.com/statping/statping/types/services"
|
||||||
"github.com/statping/statping/utils"
|
|
||||||
"strings"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
func InitNotifiers() {
|
||||||
allowedVars = []string{"host", "username", "password", "port", "api_key", "api_secret", "var1", "var2"}
|
Add(
|
||||||
)
|
slacker,
|
||||||
|
|
||||||
func SendEvent(data ...interface{}) {
|
|
||||||
d1 := data[0]
|
|
||||||
service, ok := d1.(*services.Service)
|
|
||||||
if !ok {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
d2 := data[1]
|
|
||||||
if d2 == nil {
|
|
||||||
OnSuccess(service)
|
|
||||||
}
|
|
||||||
fail, ok := d2.(*failures.Failure)
|
|
||||||
if !ok {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
OnFailure(service, fail)
|
|
||||||
}
|
|
||||||
|
|
||||||
func checkNotifierForm(n *Notification) error {
|
|
||||||
for _, f := range n.Form {
|
|
||||||
contains := contains(f.DbField, allowedVars)
|
|
||||||
if !contains {
|
|
||||||
return fmt.Errorf("the DbField '%v' is not allowed, allowed vars: %v", f.DbField, allowedVars)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func contains(s string, arr []string) bool {
|
|
||||||
for _, v := range arr {
|
|
||||||
if strings.ToLower(s) == v {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
// AddNotifier accept a Notifier interface to be added into the array
|
|
||||||
func AddNotifiers(notifiers ...Notifier) error {
|
|
||||||
log.Infof("Initiating %d Notifiers\n", len(notifiers))
|
|
||||||
|
|
||||||
for _, n := range notifiers {
|
|
||||||
notif := n.Select()
|
|
||||||
log.Infof("Initiating %s Notifier\n", notif.Method)
|
|
||||||
|
|
||||||
if err := checkNotifierForm(notif); err != nil {
|
|
||||||
log.Errorf(err.Error())
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
log.Infof("Creating %s Notifier\n", notif.Method)
|
|
||||||
if err := notif.Create(); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
if notif.Enabled.Bool {
|
|
||||||
notif.Close()
|
|
||||||
notif.Start()
|
|
||||||
go Queue(notif)
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// startAllNotifiers will start the go routine for each loaded notifier
|
|
||||||
func startAllNotifiers() {
|
|
||||||
for _, notify := range All() {
|
|
||||||
n := notify.Select()
|
|
||||||
log.Infof("Initiating %s Notifier\n", n.Method)
|
|
||||||
if utils.IsType(notify, new(Notifier)) {
|
|
||||||
if n.Enabled.Bool {
|
|
||||||
n.Close()
|
|
||||||
n.Start()
|
|
||||||
go Queue(notify)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func Migrate() error {
|
|
||||||
return AddNotifiers(
|
|
||||||
Command,
|
Command,
|
||||||
Discorder,
|
Discorder,
|
||||||
Emailer,
|
email,
|
||||||
LineNotify,
|
LineNotify,
|
||||||
Mobile,
|
|
||||||
Slacker,
|
|
||||||
Telegram,
|
Telegram,
|
||||||
Twilio,
|
Twilio,
|
||||||
Webhook,
|
Webhook,
|
||||||
|
Mobile,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func Add(notifs ...services.ServiceNotifier) {
|
||||||
|
for _, n := range notifs {
|
||||||
|
services.AddNotifier(n)
|
||||||
|
if err := n.Select().Create(); err != nil {
|
||||||
|
fmt.Println(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -20,6 +20,8 @@ import (
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/statping/statping/types/failures"
|
"github.com/statping/statping/types/failures"
|
||||||
|
"github.com/statping/statping/types/notifications"
|
||||||
|
"github.com/statping/statping/types/notifier"
|
||||||
"github.com/statping/statping/types/services"
|
"github.com/statping/statping/types/services"
|
||||||
"github.com/statping/statping/utils"
|
"github.com/statping/statping/utils"
|
||||||
"strings"
|
"strings"
|
||||||
|
@ -27,7 +29,7 @@ import (
|
||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
var _ Notifier = (*slack)(nil)
|
var _ notifier.Notifier = (*slack)(nil)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
slackMethod = "slack"
|
slackMethod = "slack"
|
||||||
|
@ -37,10 +39,14 @@ const (
|
||||||
)
|
)
|
||||||
|
|
||||||
type slack struct {
|
type slack struct {
|
||||||
*Notification
|
*notifications.Notification
|
||||||
}
|
}
|
||||||
|
|
||||||
var Slacker = &slack{&Notification{
|
func (s *slack) Select() *notifications.Notification {
|
||||||
|
return s.Notification
|
||||||
|
}
|
||||||
|
|
||||||
|
var slacker = &slack{¬ifications.Notification{
|
||||||
Method: slackMethod,
|
Method: slackMethod,
|
||||||
Title: "slack",
|
Title: "slack",
|
||||||
Description: "Send notifications to your slack channel when a service is offline. Insert your Incoming webhooker URL for your channel to receive notifications. Based on the <a href=\"https://api.slack.com/incoming-webhooks\">slack API</a>.",
|
Description: "Send notifications to your slack channel when a service is offline. Insert your Incoming webhooker URL for your channel to receive notifications. Based on the <a href=\"https://api.slack.com/incoming-webhooks\">slack API</a>.",
|
||||||
|
@ -49,7 +55,7 @@ var Slacker = &slack{&Notification{
|
||||||
Delay: time.Duration(10 * time.Second),
|
Delay: time.Duration(10 * time.Second),
|
||||||
Host: "https://webhooksurl.slack.com/***",
|
Host: "https://webhooksurl.slack.com/***",
|
||||||
Icon: "fab fa-slack",
|
Icon: "fab fa-slack",
|
||||||
Form: []NotificationForm{{
|
Form: []notifications.NotificationForm{{
|
||||||
Type: "text",
|
Type: "text",
|
||||||
Title: "Incoming webhooker Url",
|
Title: "Incoming webhooker Url",
|
||||||
Placeholder: "Insert your slack Webhook URL here.",
|
Placeholder: "Insert your slack Webhook URL here.",
|
||||||
|
@ -59,15 +65,14 @@ var Slacker = &slack{&Notification{
|
||||||
}}},
|
}}},
|
||||||
}
|
}
|
||||||
|
|
||||||
func parseSlackMessage(id int64, temp string, data interface{}) error {
|
func parseSlackMessage(id int64, temp string, data interface{}) string {
|
||||||
buf := new(bytes.Buffer)
|
buf := new(bytes.Buffer)
|
||||||
slackTemp, _ := template.New("slack").Parse(temp)
|
slackTemp, _ := template.New("slack").Parse(temp)
|
||||||
err := slackTemp.Execute(buf, data)
|
err := slackTemp.Execute(buf, data)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err.Error()
|
||||||
}
|
}
|
||||||
Slacker.AddQueue(fmt.Sprintf("service_%v", id), buf.String())
|
return buf.String()
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
type slackMessage struct {
|
type slackMessage struct {
|
||||||
|
@ -78,51 +83,44 @@ type slackMessage struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Send will send a HTTP Post to the slack webhooker API. It accepts type: string
|
// Send will send a HTTP Post to the slack webhooker API. It accepts type: string
|
||||||
func (u *slack) Send(msg interface{}) error {
|
func (u *slack) sendSlack(msg string) error {
|
||||||
message := msg.(string)
|
contents, resp, err := utils.HttpRequest(u.Host, "POST", "application/json", nil, strings.NewReader(msg), time.Duration(10*time.Second), true)
|
||||||
_, _, err := utils.HttpRequest(u.Host, "POST", "application/json", nil, strings.NewReader(message), time.Duration(10*time.Second), true)
|
defer resp.Body.Close()
|
||||||
|
fmt.Println("CONTENTS: ", string(contents))
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
func (u *slack) Select() *Notification {
|
|
||||||
return u.Notification
|
|
||||||
}
|
|
||||||
|
|
||||||
func (u *slack) OnTest() error {
|
func (u *slack) OnTest() error {
|
||||||
contents, _, err := utils.HttpRequest(u.Host, "POST", "application/json", nil, bytes.NewBuffer([]byte(`{"text":"testing message"}`)), time.Duration(10*time.Second), true)
|
contents, resp, err := utils.HttpRequest(u.Host, "POST", "application/json", nil, bytes.NewBuffer([]byte(`{"text":"testing message"}`)), time.Duration(10*time.Second), true)
|
||||||
|
defer resp.Body.Close()
|
||||||
if string(contents) != "ok" {
|
if string(contents) != "ok" {
|
||||||
return errors.New("The slack response was incorrect, check the URL")
|
return errors.New("the slack response was incorrect, check the URL")
|
||||||
}
|
}
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
// OnFailure will trigger failing service
|
// OnFailure will trigger failing service
|
||||||
func (u *slack) OnFailure(s *services.Service, f *failures.Failure) {
|
func (u *slack) OnFailure(s *services.Service, f *failures.Failure) error {
|
||||||
message := slackMessage{
|
message := slackMessage{
|
||||||
Service: s,
|
Service: s,
|
||||||
Template: failingTemplate,
|
Template: failingTemplate,
|
||||||
Time: utils.Now().Unix(),
|
Time: utils.Now().Unix(),
|
||||||
Issue: f.Issue,
|
|
||||||
}
|
}
|
||||||
parseSlackMessage(s.Id, failingTemplate, message)
|
msg := parseSlackMessage(s.Id, failingTemplate, message)
|
||||||
|
return u.sendSlack(msg)
|
||||||
}
|
}
|
||||||
|
|
||||||
// OnSuccess will trigger successful service
|
// OnSuccess will trigger successful service
|
||||||
func (u *slack) OnSuccess(s *services.Service) {
|
func (u *slack) OnSuccess(s *services.Service) error {
|
||||||
if !s.Online {
|
message := slackMessage{
|
||||||
u.ResetUniqueQueue(fmt.Sprintf("service_%v", s.Id))
|
Service: s,
|
||||||
message := slackMessage{
|
Template: successTemplate,
|
||||||
Service: s,
|
Time: utils.Now().Unix(),
|
||||||
Template: successTemplate,
|
|
||||||
Time: utils.Now().Unix(),
|
|
||||||
}
|
|
||||||
parseSlackMessage(s.Id, successTemplate, message)
|
|
||||||
}
|
}
|
||||||
}
|
msg := parseSlackMessage(s.Id, successTemplate, message)
|
||||||
|
|
||||||
// OnSave triggers when this notifier has been saved
|
fmt.Println("Sending OnSuccess message!")
|
||||||
func (u *slack) OnSave() error {
|
fmt.Println(msg)
|
||||||
message := fmt.Sprintf("Notification %v is receiving updated information.", u.Method)
|
fmt.Printf("%s\n", u.Host)
|
||||||
u.AddQueue("saved", message)
|
return u.sendSlack(msg)
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,273 +0,0 @@
|
||||||
// Statping
|
|
||||||
// Copyright (C) 2018. Hunter Long and the project contributors
|
|
||||||
// Written by Hunter Long <info@socialeck.com> and the project contributors
|
|
||||||
//
|
|
||||||
// https://github.com/statping/statping
|
|
||||||
//
|
|
||||||
// The licenses for most software and other practical works are designed
|
|
||||||
// to take away your freedom to share and change the works. By contrast,
|
|
||||||
// the GNU General Public License is intended to guarantee your freedom to
|
|
||||||
// share and change all versions of a program--to make sure it remains free
|
|
||||||
// software for all its users.
|
|
||||||
//
|
|
||||||
// You should have received a copy of the GNU General Public License
|
|
||||||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
|
|
||||||
package notifiers
|
|
||||||
|
|
||||||
import (
|
|
||||||
"encoding/json"
|
|
||||||
"errors"
|
|
||||||
"fmt"
|
|
||||||
"github.com/statping/statping/types/null"
|
|
||||||
"github.com/statping/statping/types/services"
|
|
||||||
"github.com/statping/statping/utils"
|
|
||||||
"reflect"
|
|
||||||
"time"
|
|
||||||
)
|
|
||||||
|
|
||||||
var (
|
|
||||||
// db holds the Statping database connection
|
|
||||||
log = utils.Log.WithField("type", "notifier")
|
|
||||||
allNotifiers []Notifier
|
|
||||||
)
|
|
||||||
|
|
||||||
// Notification contains all the fields for a Statping Notifier.
|
|
||||||
type Notification struct {
|
|
||||||
Id int64 `gorm:"primary_key;column:id" json:"id"`
|
|
||||||
Method string `gorm:"column:method" json:"method"`
|
|
||||||
Host string `gorm:"not null;column:host" json:"host,omitempty"`
|
|
||||||
Port int `gorm:"not null;column:port" json:"port,omitempty"`
|
|
||||||
Username string `gorm:"not null;column:username" json:"username,omitempty"`
|
|
||||||
Password string `gorm:"not null;column:password" json:"password,omitempty"`
|
|
||||||
Var1 string `gorm:"not null;column:var1" json:"var1,omitempty"`
|
|
||||||
Var2 string `gorm:"not null;column:var2" json:"var2,omitempty"`
|
|
||||||
ApiKey string `gorm:"not null;column:api_key" json:"api_key,omitempty"`
|
|
||||||
ApiSecret string `gorm:"not null;column:api_secret" json:"api_secret,omitempty"`
|
|
||||||
Enabled null.NullBool `gorm:"column:enabled;type:boolean;default:false" json:"enabled"`
|
|
||||||
Limits int `gorm:"not null;column:limits" json:"limits"`
|
|
||||||
Removable bool `gorm:"column:removable" json:"removeable"`
|
|
||||||
CreatedAt time.Time `gorm:"column:created_at" json:"created_at"`
|
|
||||||
UpdatedAt time.Time `gorm:"column:updated_at" json:"updated_at"`
|
|
||||||
Form []NotificationForm `gorm:"-" json:"form"`
|
|
||||||
logs []*NotificationLog `gorm:"-" json:"logs"`
|
|
||||||
Title string `gorm:"-" json:"title"`
|
|
||||||
Description string `gorm:"-" json:"description"`
|
|
||||||
Author string `gorm:"-" json:"author"`
|
|
||||||
AuthorUrl string `gorm:"-" json:"author_url"`
|
|
||||||
Icon string `gorm:"-" json:"icon"`
|
|
||||||
Delay time.Duration `gorm:"-" json:"delay,string"`
|
|
||||||
Queue []*QueueData `gorm:"-" json:"-"`
|
|
||||||
Running chan bool `gorm:"-" json:"-"`
|
|
||||||
testable bool `gorm:"-" json:"testable"`
|
|
||||||
|
|
||||||
Hits notificationHits
|
|
||||||
Notifier
|
|
||||||
}
|
|
||||||
|
|
||||||
type notificationHits struct {
|
|
||||||
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
|
|
||||||
type QueueData struct {
|
|
||||||
Id string
|
|
||||||
Data interface{}
|
|
||||||
}
|
|
||||||
|
|
||||||
// NotificationForm contains the HTML fields for each variable/input you want the notifier to accept.
|
|
||||||
type NotificationForm struct {
|
|
||||||
Type string `json:"type"` // the html input type (text, password, email)
|
|
||||||
Title string `json:"title"` // include a title for ease of use
|
|
||||||
Placeholder string `json:"placeholder"` // add a placeholder for the input
|
|
||||||
DbField string `json:"field"` // true variable key for input
|
|
||||||
SmallText string `json:"small_text"` // insert small text under a html input
|
|
||||||
Required bool `json:"required"` // require this input on the html form
|
|
||||||
IsHidden bool `json:"hidden"` // hide this form element from end user
|
|
||||||
IsList bool `json:"list"` // make this form element a comma separated list
|
|
||||||
IsSwitch bool `json:"switch"` // make the notifier a boolean true/false switch
|
|
||||||
}
|
|
||||||
|
|
||||||
// NotificationLog contains the normalized message from previously sent notifications
|
|
||||||
type NotificationLog struct {
|
|
||||||
Message string `json:"message"`
|
|
||||||
Time utils.Timestamp `json:"time"`
|
|
||||||
Timestamp time.Time `json:"timestamp"`
|
|
||||||
}
|
|
||||||
|
|
||||||
// normalizeType will accept multiple interfaces and converts it into a string for logging
|
|
||||||
func normalizeType(ty interface{}) string {
|
|
||||||
switch v := ty.(type) {
|
|
||||||
case int, int32, int64:
|
|
||||||
return fmt.Sprintf("%v", v)
|
|
||||||
case float32, float64:
|
|
||||||
return fmt.Sprintf("%v", v)
|
|
||||||
case string:
|
|
||||||
return v
|
|
||||||
case []byte:
|
|
||||||
return string(v)
|
|
||||||
case []string:
|
|
||||||
return fmt.Sprintf("%v", v)
|
|
||||||
case interface{}, map[string]interface{}:
|
|
||||||
j, _ := json.Marshal(v)
|
|
||||||
return string(j)
|
|
||||||
default:
|
|
||||||
return fmt.Sprintf("%v", v)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Log will record a new notification into memory and will show the logs on the settings page
|
|
||||||
func (n *Notification) makeLog(msg interface{}) {
|
|
||||||
log := &NotificationLog{
|
|
||||||
Message: normalizeType(msg),
|
|
||||||
Time: utils.Timestamp(utils.Now()),
|
|
||||||
Timestamp: utils.Now(),
|
|
||||||
}
|
|
||||||
n.logs = append(n.logs, log)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Logs returns an array of the notifiers logs
|
|
||||||
func (n *Notification) Logs() []*NotificationLog {
|
|
||||||
return reverseLogs(n.logs)
|
|
||||||
}
|
|
||||||
|
|
||||||
// reverseLogs will reverse the notifier's logs to be time desc
|
|
||||||
func reverseLogs(input []*NotificationLog) []*NotificationLog {
|
|
||||||
if len(input) == 0 {
|
|
||||||
return input
|
|
||||||
}
|
|
||||||
return append(reverseLogs(input[1:]), input[0])
|
|
||||||
}
|
|
||||||
|
|
||||||
// SelectNotification returns the Notification struct from the database
|
|
||||||
func SelectNotification(n Notifier) (*Notification, error) {
|
|
||||||
notifier := n.Select()
|
|
||||||
err := db.Where("method = ?", notifier.Method).Find(¬ifier)
|
|
||||||
return notifier, err.Error()
|
|
||||||
}
|
|
||||||
|
|
||||||
// SelectNotifier returns the Notification struct from the database
|
|
||||||
func SelectNotifier(method string) (*Notification, Notifier, error) {
|
|
||||||
for _, comm := range allNotifiers {
|
|
||||||
n, ok := comm.(Notifier)
|
|
||||||
if !ok {
|
|
||||||
return nil, nil, fmt.Errorf("incorrect notification type: %v", reflect.TypeOf(n).String())
|
|
||||||
}
|
|
||||||
notifier := n.Select()
|
|
||||||
if notifier.Method == method {
|
|
||||||
return notifier, comm.(Notifier), nil
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return nil, nil, errors.New("cannot find notifier")
|
|
||||||
}
|
|
||||||
|
|
||||||
// Queue is the FIFO go routine to send notifications when objects are triggered
|
|
||||||
func Queue(notifer Notifier) {
|
|
||||||
n := notifer.(*Notification)
|
|
||||||
rateLimit := n.Delay
|
|
||||||
|
|
||||||
CheckNotifier:
|
|
||||||
for {
|
|
||||||
select {
|
|
||||||
case <-n.Running:
|
|
||||||
break CheckNotifier
|
|
||||||
case <-time.After(rateLimit):
|
|
||||||
n := notifer.(*Notification)
|
|
||||||
fmt.Printf("checking %s %d\n", n.Method, len(n.Queue))
|
|
||||||
if len(n.Queue) > 0 {
|
|
||||||
ok, _ := n.WithinLimits()
|
|
||||||
if ok {
|
|
||||||
msg := n.Queue[0]
|
|
||||||
err := notifer.Send(msg.Data)
|
|
||||||
if err != nil {
|
|
||||||
log.WithFields(utils.ToFields(n, msg)).Error(fmt.Sprintf("Notifier '%v' had an error: %v", n.Method, err))
|
|
||||||
} else {
|
|
||||||
log.WithFields(utils.ToFields(n, msg)).Debug(fmt.Sprintf("Notifier '%v' sent outgoing message (%v) %v left in queue.", n.Method, msg.Id, len(n.Queue)))
|
|
||||||
}
|
|
||||||
n.makeLog(msg.Data)
|
|
||||||
if len(n.Queue) > 1 {
|
|
||||||
n.Queue = n.Queue[1:]
|
|
||||||
} else {
|
|
||||||
n.Queue = nil
|
|
||||||
}
|
|
||||||
rateLimit = n.Delay
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// install will check the database for the notification, if its not inserted it will insert a new record for it
|
|
||||||
//func install(n Notifier) error {
|
|
||||||
// log.WithFields(utils.ToFields(n)).
|
|
||||||
// Debugln(fmt.Sprintf("Checking if notifier '%v' is installed", n.Select().Method))
|
|
||||||
//
|
|
||||||
// if Exists(n.Select().Method) {
|
|
||||||
// AllCommunications = append(AllCommunications, n)
|
|
||||||
// } else {
|
|
||||||
// _, err := insertDatabase(n)
|
|
||||||
// if err != nil {
|
|
||||||
// log.Errorln(err)
|
|
||||||
// return err
|
|
||||||
// }
|
|
||||||
// AllCommunications = append(AllCommunications, n)
|
|
||||||
// }
|
|
||||||
// return nil
|
|
||||||
//}
|
|
||||||
|
|
||||||
// isEnabled returns true if the notifier is enabled
|
|
||||||
func isEnabled(n interface{}) bool {
|
|
||||||
notifier := n.(Notifier).Select()
|
|
||||||
return notifier.Enabled.Bool
|
|
||||||
}
|
|
||||||
|
|
||||||
// inLimits will return true if the notifier is within sending limits
|
|
||||||
func inLimits(n interface{}) bool {
|
|
||||||
notifier := n.(Notifier).Select()
|
|
||||||
ok, _ := notifier.WithinLimits()
|
|
||||||
return ok
|
|
||||||
}
|
|
||||||
|
|
||||||
// WithinLimits returns true if the notifier is within its sending limits
|
|
||||||
func (n *Notification) WithinLimits() (bool, error) {
|
|
||||||
if n.SentLastMinute() == 0 {
|
|
||||||
return true, nil
|
|
||||||
}
|
|
||||||
if n.SentLastMinute() >= n.Limits {
|
|
||||||
return false, fmt.Errorf("notifier sent %v out of %v in last minute", n.SentLastMinute(), n.Limits)
|
|
||||||
}
|
|
||||||
if n.LastSent().Seconds() == 0 {
|
|
||||||
return true, nil
|
|
||||||
}
|
|
||||||
if n.Delay.Seconds() >= n.LastSent().Seconds() {
|
|
||||||
return false, fmt.Errorf("notifiers delay (%v) is greater than last message sent (%v)", n.Delay.Seconds(), n.LastSent().Seconds())
|
|
||||||
}
|
|
||||||
return true, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// ExampleService can be used for the OnTest() method for notifiers
|
|
||||||
var ExampleService = &services.Service{
|
|
||||||
Id: 1,
|
|
||||||
Name: "Interpol - All The Rage Back Home",
|
|
||||||
Domain: "https://www.youtube.com/watch?v=-u6DvRyyKGU",
|
|
||||||
ExpectedStatus: 200,
|
|
||||||
Interval: 30,
|
|
||||||
Type: "http",
|
|
||||||
Method: "GET",
|
|
||||||
Timeout: 20,
|
|
||||||
LastStatusCode: 404,
|
|
||||||
Expected: null.NewNullString("test example"),
|
|
||||||
LastResponse: "<html>this is an example response</html>",
|
|
||||||
CreatedAt: utils.Now().Add(-24 * time.Hour),
|
|
||||||
}
|
|
|
@ -20,6 +20,8 @@ import (
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/statping/statping/types/failures"
|
"github.com/statping/statping/types/failures"
|
||||||
|
"github.com/statping/statping/types/notifications"
|
||||||
|
"github.com/statping/statping/types/notifier"
|
||||||
"github.com/statping/statping/types/services"
|
"github.com/statping/statping/types/services"
|
||||||
"github.com/statping/statping/utils"
|
"github.com/statping/statping/utils"
|
||||||
"net/url"
|
"net/url"
|
||||||
|
@ -27,13 +29,17 @@ import (
|
||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
var _ Notifier = (*telegram)(nil)
|
var _ notifier.Notifier = (*telegram)(nil)
|
||||||
|
|
||||||
type telegram struct {
|
type telegram struct {
|
||||||
*Notification
|
*notifications.Notification
|
||||||
}
|
}
|
||||||
|
|
||||||
var Telegram = &telegram{&Notification{
|
func (t *telegram) Select() *notifications.Notification {
|
||||||
|
return t.Notification
|
||||||
|
}
|
||||||
|
|
||||||
|
var Telegram = &telegram{¬ifications.Notification{
|
||||||
Method: "telegram",
|
Method: "telegram",
|
||||||
Title: "Telegram",
|
Title: "Telegram",
|
||||||
Description: "Receive notifications on your Telegram channel when a service has an issue. You must get a Telegram API token from the /botfather. Review the <a target=\"_blank\" href=\"http://techthoughts.info/how-to-create-a-telegram-bot-and-send-messages-via-api\">Telegram API Tutorial</a> to learn how to generate a new API Token.",
|
Description: "Receive notifications on your Telegram channel when a service has an issue. You must get a Telegram API token from the /botfather. Review the <a target=\"_blank\" href=\"http://techthoughts.info/how-to-create-a-telegram-bot-and-send-messages-via-api\">Telegram API Tutorial</a> to learn how to generate a new API Token.",
|
||||||
|
@ -41,7 +47,7 @@ var Telegram = &telegram{&Notification{
|
||||||
AuthorUrl: "https://github.com/hunterlong",
|
AuthorUrl: "https://github.com/hunterlong",
|
||||||
Icon: "fab fa-telegram-plane",
|
Icon: "fab fa-telegram-plane",
|
||||||
Delay: time.Duration(5 * time.Second),
|
Delay: time.Duration(5 * time.Second),
|
||||||
Form: []NotificationForm{{
|
Form: []notifications.NotificationForm{{
|
||||||
Type: "text",
|
Type: "text",
|
||||||
Title: "Telegram API Token",
|
Title: "Telegram API Token",
|
||||||
Placeholder: "383810182:EEx829dtCeufeQYXG7CUdiQopqdmmxBPO7-s",
|
Placeholder: "383810182:EEx829dtCeufeQYXG7CUdiQopqdmmxBPO7-s",
|
||||||
|
@ -58,13 +64,8 @@ var Telegram = &telegram{&Notification{
|
||||||
}}},
|
}}},
|
||||||
}
|
}
|
||||||
|
|
||||||
func (u *telegram) Select() *Notification {
|
|
||||||
return u.Notification
|
|
||||||
}
|
|
||||||
|
|
||||||
// Send will send a HTTP Post to the Telegram API. It accepts type: string
|
// Send will send a HTTP Post to the Telegram API. It accepts type: string
|
||||||
func (u *telegram) Send(msg interface{}) error {
|
func (u *telegram) sendMessage(message string) error {
|
||||||
message := msg.(string)
|
|
||||||
apiEndpoint := fmt.Sprintf("https://api.telegram.org/bot%v/sendMessage", u.ApiSecret)
|
apiEndpoint := fmt.Sprintf("https://api.telegram.org/bot%v/sendMessage", u.ApiSecret)
|
||||||
|
|
||||||
v := url.Values{}
|
v := url.Values{}
|
||||||
|
@ -84,35 +85,21 @@ func (u *telegram) Send(msg interface{}) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
// OnFailure will trigger failing service
|
// OnFailure will trigger failing service
|
||||||
func (u *telegram) OnFailure(s *services.Service, f *failures.Failure) {
|
func (u *telegram) OnFailure(s *services.Service, f *failures.Failure) error {
|
||||||
msg := fmt.Sprintf("Your service '%v' is currently offline!", s.Name)
|
msg := fmt.Sprintf("Your service '%v' is currently offline!", s.Name)
|
||||||
u.AddQueue(fmt.Sprintf("service_%v", s.Id), msg)
|
return u.sendMessage(msg)
|
||||||
}
|
}
|
||||||
|
|
||||||
// OnSuccess will trigger successful service
|
// OnSuccess will trigger successful service
|
||||||
func (u *telegram) OnSuccess(s *services.Service) {
|
func (u *telegram) OnSuccess(s *services.Service) error {
|
||||||
if !s.Online || !s.SuccessNotified {
|
msg := fmt.Sprintf("Your service '%v' is currently online!", s.Name)
|
||||||
u.ResetUniqueQueue(fmt.Sprintf("service_%v", s.Id))
|
return u.sendMessage(msg)
|
||||||
var msg interface{}
|
|
||||||
msg = s.DownText
|
|
||||||
|
|
||||||
u.AddQueue(fmt.Sprintf("service_%v", s.Id), msg)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// OnSave triggers when this notifier has been saved
|
|
||||||
func (u *telegram) OnSave() error {
|
|
||||||
utils.Log.Infoln(fmt.Sprintf("Notification %v is receiving updated information.", u.Method))
|
|
||||||
|
|
||||||
// Do updating stuff here
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// OnTest will test the Twilio SMS messaging
|
// OnTest will test the Twilio SMS messaging
|
||||||
func (u *telegram) OnTest() error {
|
func (u *telegram) OnTest() error {
|
||||||
msg := fmt.Sprintf("Testing the Twilio SMS Notifier on your Statping server")
|
msg := fmt.Sprintf("Testing the Twilio SMS Notifier on your Statping server")
|
||||||
return u.Send(msg)
|
return u.sendMessage(msg)
|
||||||
}
|
}
|
||||||
|
|
||||||
func telegramSuccess(res []byte) (bool, telegramResponse) {
|
func telegramSuccess(res []byte) (bool, telegramResponse) {
|
||||||
|
|
|
@ -20,6 +20,8 @@ import (
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/statping/statping/types/failures"
|
"github.com/statping/statping/types/failures"
|
||||||
|
"github.com/statping/statping/types/notifications"
|
||||||
|
"github.com/statping/statping/types/notifier"
|
||||||
"github.com/statping/statping/types/services"
|
"github.com/statping/statping/types/services"
|
||||||
"github.com/statping/statping/utils"
|
"github.com/statping/statping/utils"
|
||||||
"net/url"
|
"net/url"
|
||||||
|
@ -27,13 +29,17 @@ import (
|
||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
var _ Notifier = (*twilio)(nil)
|
var _ notifier.Notifier = (*twilio)(nil)
|
||||||
|
|
||||||
type twilio struct {
|
type twilio struct {
|
||||||
*Notification
|
*notifications.Notification
|
||||||
}
|
}
|
||||||
|
|
||||||
var Twilio = &twilio{&Notification{
|
func (t *twilio) Select() *notifications.Notification {
|
||||||
|
return t.Notification
|
||||||
|
}
|
||||||
|
|
||||||
|
var Twilio = &twilio{¬ifications.Notification{
|
||||||
Method: "twilio",
|
Method: "twilio",
|
||||||
Title: "Twilio",
|
Title: "Twilio",
|
||||||
Description: "Receive SMS text messages directly to your cellphone when a service is offline. You can use a Twilio test account with limits. This notifier uses the <a href=\"https://www.twilio.com/docs/usage/api\">Twilio API</a>.",
|
Description: "Receive SMS text messages directly to your cellphone when a service is offline. You can use a Twilio test account with limits. This notifier uses the <a href=\"https://www.twilio.com/docs/usage/api\">Twilio API</a>.",
|
||||||
|
@ -41,7 +47,7 @@ var Twilio = &twilio{&Notification{
|
||||||
AuthorUrl: "https://github.com/hunterlong",
|
AuthorUrl: "https://github.com/hunterlong",
|
||||||
Icon: "far fa-comment-alt",
|
Icon: "far fa-comment-alt",
|
||||||
Delay: time.Duration(10 * time.Second),
|
Delay: time.Duration(10 * time.Second),
|
||||||
Form: []NotificationForm{{
|
Form: []notifications.NotificationForm{{
|
||||||
Type: "text",
|
Type: "text",
|
||||||
Title: "Account SID",
|
Title: "Account SID",
|
||||||
Placeholder: "Insert your Twilio Account SID",
|
Placeholder: "Insert your Twilio Account SID",
|
||||||
|
@ -68,13 +74,8 @@ var Twilio = &twilio{&Notification{
|
||||||
}}},
|
}}},
|
||||||
}
|
}
|
||||||
|
|
||||||
func (u *twilio) Select() *Notification {
|
|
||||||
return u.Notification
|
|
||||||
}
|
|
||||||
|
|
||||||
// Send will send a HTTP Post to the Twilio SMS API. It accepts type: string
|
// Send will send a HTTP Post to the Twilio SMS API. It accepts type: string
|
||||||
func (u *twilio) Send(msg interface{}) error {
|
func (u *twilio) sendMessage(message string) error {
|
||||||
message := msg.(string)
|
|
||||||
twilioUrl := fmt.Sprintf("https://api.twilio.com/2010-04-01/Accounts/%v/Messages.json", u.GetValue("api_key"))
|
twilioUrl := fmt.Sprintf("https://api.twilio.com/2010-04-01/Accounts/%v/Messages.json", u.GetValue("api_key"))
|
||||||
|
|
||||||
v := url.Values{}
|
v := url.Values{}
|
||||||
|
@ -94,35 +95,21 @@ func (u *twilio) Send(msg interface{}) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
// OnFailure will trigger failing service
|
// OnFailure will trigger failing service
|
||||||
func (u *twilio) OnFailure(s *services.Service, f *failures.Failure) {
|
func (u *twilio) OnFailure(s *services.Service, f *failures.Failure) error {
|
||||||
msg := fmt.Sprintf("Your service '%v' is currently offline!", s.Name)
|
msg := fmt.Sprintf("Your service '%v' is currently offline!", s.Name)
|
||||||
u.AddQueue(fmt.Sprintf("service_%v", s.Id), msg)
|
return u.sendMessage(msg)
|
||||||
}
|
}
|
||||||
|
|
||||||
// OnSuccess will trigger successful service
|
// OnSuccess will trigger successful service
|
||||||
func (u *twilio) OnSuccess(s *services.Service) {
|
func (u *twilio) OnSuccess(s *services.Service) error {
|
||||||
if !s.Online || !s.SuccessNotified {
|
msg := fmt.Sprintf("Your service '%v' is currently online!", s.Name)
|
||||||
u.ResetUniqueQueue(fmt.Sprintf("service_%v", s.Id))
|
return u.sendMessage(msg)
|
||||||
var msg string
|
|
||||||
msg = s.DownText
|
|
||||||
|
|
||||||
u.AddQueue(fmt.Sprintf("service_%v", s.Id), msg)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// OnSave triggers when this notifier has been saved
|
|
||||||
func (u *twilio) OnSave() error {
|
|
||||||
utils.Log.Infoln(fmt.Sprintf("Notification %v is receiving updated information.", u.Method))
|
|
||||||
|
|
||||||
// Do updating stuff here
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// OnTest will test the Twilio SMS messaging
|
// OnTest will test the Twilio SMS messaging
|
||||||
func (u *twilio) OnTest() error {
|
func (u *twilio) OnTest() error {
|
||||||
msg := fmt.Sprintf("Testing the Twilio SMS Notifier")
|
msg := fmt.Sprintf("Testing the Twilio SMS Notifier")
|
||||||
return u.Send(msg)
|
return u.sendMessage(msg)
|
||||||
}
|
}
|
||||||
|
|
||||||
func twilioSuccess(res []byte) (bool, twilioResponse) {
|
func twilioSuccess(res []byte) (bool, twilioResponse) {
|
||||||
|
|
|
@ -19,6 +19,8 @@ import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/statping/statping/types/failures"
|
"github.com/statping/statping/types/failures"
|
||||||
|
"github.com/statping/statping/types/notifications"
|
||||||
|
"github.com/statping/statping/types/notifier"
|
||||||
"github.com/statping/statping/types/services"
|
"github.com/statping/statping/types/services"
|
||||||
"github.com/statping/statping/utils"
|
"github.com/statping/statping/utils"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
|
@ -27,17 +29,17 @@ import (
|
||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
var _ Notifier = (*webhooker)(nil)
|
var _ notifier.Notifier = (*webhooker)(nil)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
webhookMethod = "webhook"
|
webhookMethod = "webhook"
|
||||||
)
|
)
|
||||||
|
|
||||||
type webhooker struct {
|
type webhooker struct {
|
||||||
*Notification
|
*notifications.Notification
|
||||||
}
|
}
|
||||||
|
|
||||||
var Webhook = &webhooker{&Notification{
|
var Webhook = &webhooker{¬ifications.Notification{
|
||||||
Method: webhookMethod,
|
Method: webhookMethod,
|
||||||
Title: "HTTP webhooker",
|
Title: "HTTP webhooker",
|
||||||
Description: "Send a custom HTTP request to a specific URL with your own body, headers, and parameters.",
|
Description: "Send a custom HTTP request to a specific URL with your own body, headers, and parameters.",
|
||||||
|
@ -45,7 +47,7 @@ var Webhook = &webhooker{&Notification{
|
||||||
AuthorUrl: "https://github.com/hunterlong",
|
AuthorUrl: "https://github.com/hunterlong",
|
||||||
Icon: "fas fa-code-branch",
|
Icon: "fas fa-code-branch",
|
||||||
Delay: time.Duration(1 * time.Second),
|
Delay: time.Duration(1 * time.Second),
|
||||||
Form: []NotificationForm{{
|
Form: []notifications.NotificationForm{{
|
||||||
Type: "text",
|
Type: "text",
|
||||||
Title: "HTTP Endpoint",
|
Title: "HTTP Endpoint",
|
||||||
Placeholder: "http://webhookurl.com/JW2MCP4SKQP",
|
Placeholder: "http://webhookurl.com/JW2MCP4SKQP",
|
||||||
|
@ -89,7 +91,7 @@ func (w *webhooker) Send(msg interface{}) error {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
func (w *webhooker) Select() *Notification {
|
func (w *webhooker) Select() *notifications.Notification {
|
||||||
return w.Notification
|
return w.Notification
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -131,7 +133,7 @@ func (w *webhooker) sendHttpWebhook(body string) (*http.Response, error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (w *webhooker) OnTest() error {
|
func (w *webhooker) OnTest() error {
|
||||||
body := replaceBodyText(w.Var2, ExampleService, nil)
|
body := replaceBodyText(w.Var2, nil, nil)
|
||||||
resp, err := w.sendHttpWebhook(body)
|
resp, err := w.sendHttpWebhook(body)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
|
@ -143,21 +145,17 @@ func (w *webhooker) OnTest() error {
|
||||||
}
|
}
|
||||||
|
|
||||||
// OnFailure will trigger failing service
|
// OnFailure will trigger failing service
|
||||||
func (w *webhooker) OnFailure(s *services.Service, f *failures.Failure) {
|
func (w *webhooker) OnFailure(s *services.Service, f *failures.Failure) error {
|
||||||
msg := replaceBodyText(w.Var2, s, f)
|
msg := replaceBodyText(w.Var2, s, f)
|
||||||
w.AddQueue(fmt.Sprintf("service_%v", s.Id), msg)
|
resp, err := w.sendHttpWebhook(msg)
|
||||||
|
defer resp.Body.Close()
|
||||||
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
// OnSuccess will trigger successful service
|
// OnSuccess will trigger successful service
|
||||||
func (w *webhooker) OnSuccess(s *services.Service) {
|
func (w *webhooker) OnSuccess(s *services.Service) error {
|
||||||
if !s.Online {
|
msg := replaceBodyText(w.Var2, s, nil)
|
||||||
w.ResetUniqueQueue(fmt.Sprintf("service_%v", s.Id))
|
resp, err := w.sendHttpWebhook(msg)
|
||||||
msg := replaceBodyText(w.Var2, s, nil)
|
defer resp.Body.Close()
|
||||||
w.AddQueue(fmt.Sprintf("service_%v", s.Id), msg)
|
return err
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// OnSave triggers when this notifier has been saved
|
|
||||||
func (w *webhooker) OnSave() error {
|
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,7 +5,6 @@ import (
|
||||||
"github.com/jinzhu/gorm"
|
"github.com/jinzhu/gorm"
|
||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
"github.com/statping/statping/database"
|
"github.com/statping/statping/database"
|
||||||
"github.com/statping/statping/notifiers"
|
|
||||||
"github.com/statping/statping/types/checkins"
|
"github.com/statping/statping/types/checkins"
|
||||||
"github.com/statping/statping/types/core"
|
"github.com/statping/statping/types/core"
|
||||||
"github.com/statping/statping/types/failures"
|
"github.com/statping/statping/types/failures"
|
||||||
|
@ -13,6 +12,7 @@ import (
|
||||||
"github.com/statping/statping/types/hits"
|
"github.com/statping/statping/types/hits"
|
||||||
"github.com/statping/statping/types/incidents"
|
"github.com/statping/statping/types/incidents"
|
||||||
"github.com/statping/statping/types/messages"
|
"github.com/statping/statping/types/messages"
|
||||||
|
"github.com/statping/statping/types/notifications"
|
||||||
"github.com/statping/statping/types/null"
|
"github.com/statping/statping/types/null"
|
||||||
"github.com/statping/statping/types/services"
|
"github.com/statping/statping/types/services"
|
||||||
"github.com/statping/statping/types/users"
|
"github.com/statping/statping/types/users"
|
||||||
|
@ -100,7 +100,7 @@ func initModels(db database.Database) {
|
||||||
hits.SetDB(db)
|
hits.SetDB(db)
|
||||||
failures.SetDB(db)
|
failures.SetDB(db)
|
||||||
checkins.SetDB(db)
|
checkins.SetDB(db)
|
||||||
notifiers.SetDB(db)
|
notifications.SetDB(db)
|
||||||
incidents.SetDB(db)
|
incidents.SetDB(db)
|
||||||
users.SetDB(db)
|
users.SetDB(db)
|
||||||
messages.SetDB(db)
|
messages.SetDB(db)
|
||||||
|
|
|
@ -2,7 +2,6 @@ package configs
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/statping/statping/database"
|
"github.com/statping/statping/database"
|
||||||
"github.com/statping/statping/notifiers"
|
|
||||||
"github.com/statping/statping/types/checkins"
|
"github.com/statping/statping/types/checkins"
|
||||||
"github.com/statping/statping/types/core"
|
"github.com/statping/statping/types/core"
|
||||||
"github.com/statping/statping/types/failures"
|
"github.com/statping/statping/types/failures"
|
||||||
|
@ -10,6 +9,7 @@ import (
|
||||||
"github.com/statping/statping/types/hits"
|
"github.com/statping/statping/types/hits"
|
||||||
"github.com/statping/statping/types/incidents"
|
"github.com/statping/statping/types/incidents"
|
||||||
"github.com/statping/statping/types/messages"
|
"github.com/statping/statping/types/messages"
|
||||||
|
"github.com/statping/statping/types/notifications"
|
||||||
"github.com/statping/statping/types/services"
|
"github.com/statping/statping/types/services"
|
||||||
"github.com/statping/statping/types/users"
|
"github.com/statping/statping/types/users"
|
||||||
"github.com/statping/statping/utils"
|
"github.com/statping/statping/utils"
|
||||||
|
@ -73,7 +73,7 @@ func (d *DbConfig) Delete() error {
|
||||||
|
|
||||||
// DropDatabase will DROP each table Statping created
|
// DropDatabase will DROP each table Statping created
|
||||||
func (d *DbConfig) DropDatabase() error {
|
func (d *DbConfig) DropDatabase() error {
|
||||||
var DbModels = []interface{}{&services.Service{}, &users.User{}, &hits.Hit{}, &failures.Failure{}, &messages.Message{}, &groups.Group{}, &checkins.Checkin{}, &checkins.CheckinHit{}, ¬ifiers.Notification{}, &incidents.Incident{}, &incidents.IncidentUpdate{}}
|
var DbModels = []interface{}{&services.Service{}, &users.User{}, &hits.Hit{}, &failures.Failure{}, &messages.Message{}, &groups.Group{}, &checkins.Checkin{}, &checkins.CheckinHit{}, ¬ifications.Notification{}, &incidents.Incident{}, &incidents.IncidentUpdate{}}
|
||||||
log.Infoln("Dropping Database Tables...")
|
log.Infoln("Dropping Database Tables...")
|
||||||
for _, t := range DbModels {
|
for _, t := range DbModels {
|
||||||
if err := d.Db.DropTableIfExists(t); err != nil {
|
if err := d.Db.DropTableIfExists(t); err != nil {
|
||||||
|
@ -94,7 +94,7 @@ func (d *DbConfig) Close() {
|
||||||
func (d *DbConfig) CreateDatabase() error {
|
func (d *DbConfig) CreateDatabase() error {
|
||||||
var err error
|
var err error
|
||||||
|
|
||||||
var DbModels = []interface{}{&services.Service{}, &users.User{}, &hits.Hit{}, &failures.Failure{}, &messages.Message{}, &groups.Group{}, &checkins.Checkin{}, &checkins.CheckinHit{}, ¬ifiers.Notification{}, &incidents.Incident{}, &incidents.IncidentUpdate{}}
|
var DbModels = []interface{}{&services.Service{}, &users.User{}, &hits.Hit{}, &failures.Failure{}, &messages.Message{}, &groups.Group{}, &checkins.Checkin{}, &checkins.CheckinHit{}, ¬ifications.Notification{}, &incidents.Incident{}, &incidents.IncidentUpdate{}}
|
||||||
|
|
||||||
log.Infoln("Creating Database Tables...")
|
log.Infoln("Creating Database Tables...")
|
||||||
for _, table := range DbModels {
|
for _, table := range DbModels {
|
||||||
|
|
|
@ -5,7 +5,8 @@ import (
|
||||||
_ "github.com/jinzhu/gorm/dialects/mysql"
|
_ "github.com/jinzhu/gorm/dialects/mysql"
|
||||||
_ "github.com/jinzhu/gorm/dialects/postgres"
|
_ "github.com/jinzhu/gorm/dialects/postgres"
|
||||||
_ "github.com/jinzhu/gorm/dialects/sqlite"
|
_ "github.com/jinzhu/gorm/dialects/sqlite"
|
||||||
"github.com/statping/statping/notifiers"
|
"github.com/statping/statping/types/notifications"
|
||||||
|
|
||||||
"github.com/statping/statping/types/checkins"
|
"github.com/statping/statping/types/checkins"
|
||||||
"github.com/statping/statping/types/core"
|
"github.com/statping/statping/types/core"
|
||||||
"github.com/statping/statping/types/failures"
|
"github.com/statping/statping/types/failures"
|
||||||
|
@ -52,7 +53,7 @@ func (c *DbConfig) DatabaseChanges() error {
|
||||||
//If this function has an issue, it will ROLLBACK to the previous state.
|
//If this function has an issue, it will ROLLBACK to the previous state.
|
||||||
func (c *DbConfig) MigrateDatabase() error {
|
func (c *DbConfig) MigrateDatabase() error {
|
||||||
|
|
||||||
var DbModels = []interface{}{&services.Service{}, &users.User{}, &hits.Hit{}, &failures.Failure{}, &messages.Message{}, &groups.Group{}, &checkins.Checkin{}, &checkins.CheckinHit{}, ¬ifiers.Notification{}, &incidents.Incident{}, &incidents.IncidentUpdate{}}
|
var DbModels = []interface{}{&services.Service{}, &users.User{}, &hits.Hit{}, &failures.Failure{}, &messages.Message{}, &groups.Group{}, &checkins.Checkin{}, &checkins.CheckinHit{}, ¬ifications.Notification{}, &incidents.Incident{}, &incidents.IncidentUpdate{}}
|
||||||
|
|
||||||
log.Infoln("Migrating Database Tables...")
|
log.Infoln("Migrating Database Tables...")
|
||||||
tx := c.Db.Begin()
|
tx := c.Db.Begin()
|
||||||
|
|
|
@ -1,32 +1,21 @@
|
||||||
package notifiers
|
package notifications
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"errors"
|
|
||||||
"github.com/statping/statping/database"
|
"github.com/statping/statping/database"
|
||||||
)
|
)
|
||||||
|
|
||||||
var db database.Database
|
var (
|
||||||
|
db database.Database
|
||||||
|
)
|
||||||
|
|
||||||
func SetDB(database database.Database) {
|
func SetDB(database database.Database) {
|
||||||
db = database.Model(&Notification{})
|
db = database.Model(&Notification{})
|
||||||
}
|
}
|
||||||
|
|
||||||
func appendList(n Notifier) {
|
func Find(method string) (*Notification, error) {
|
||||||
allNotifiers = append(allNotifiers, n)
|
var notification Notification
|
||||||
}
|
q := db.Where("method = ?", method).Find(¬ification)
|
||||||
|
return ¬ification, q.Error()
|
||||||
func Find(name string) (*Notification, error) {
|
|
||||||
for _, n := range allNotifiers {
|
|
||||||
notif := n.(*Notification)
|
|
||||||
if notif.Method == name {
|
|
||||||
return notif, nil
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return nil, errors.New("notifier not found")
|
|
||||||
}
|
|
||||||
|
|
||||||
func All() []Notifier {
|
|
||||||
return allNotifiers
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (n *Notification) Create() error {
|
func (n *Notification) Create() error {
|
||||||
|
@ -36,7 +25,6 @@ func (n *Notification) Create() error {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
appendList(n)
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -45,7 +33,6 @@ func (n *Notification) Update() error {
|
||||||
if n.Enabled.Bool {
|
if n.Enabled.Bool {
|
||||||
n.Close()
|
n.Close()
|
||||||
n.Start()
|
n.Start()
|
||||||
go Queue(n)
|
|
||||||
} else {
|
} else {
|
||||||
n.Close()
|
n.Close()
|
||||||
}
|
}
|
||||||
|
@ -53,6 +40,8 @@ func (n *Notification) Update() error {
|
||||||
return err.Error()
|
return err.Error()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (n *Notification) Delete() error {
|
func loadAll() []*Notification {
|
||||||
return nil
|
var notifications []*Notification
|
||||||
|
db.Find(¬ifications)
|
||||||
|
return notifications
|
||||||
}
|
}
|
|
@ -1,4 +1,4 @@
|
||||||
package notifiers
|
package notifications
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
@ -21,49 +21,48 @@ func (n *Notification) AfterFind() (err error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// AddQueue will add any type of interface (json, string, struct, etc) into the Notifiers queue
|
// AddQueue will add any type of interface (json, string, struct, etc) into the Notifiers queue
|
||||||
func (n *Notification) AddQueue(uid string, msg interface{}) {
|
//func (n *Notification) AddQueue(uid string, msg interface{}) {
|
||||||
data := &QueueData{uid, msg}
|
// data := &QueueData{uid, msg}
|
||||||
n.Queue = append(n.Queue, data)
|
// n.Queue = append(n.Queue, data)
|
||||||
log.WithFields(utils.ToFields(data, n)).Debug(fmt.Sprintf("Notifier '%v' added new item (%v) to the queue. (%v queued)", n.Method, uid, len(n.Queue)))
|
// log.WithFields(utils.ToFields(data, n)).Debug(fmt.Sprintf("Notifier '%v' added new item (%v) to the queue. (%v queued)", n.Method, uid, len(n.Queue)))
|
||||||
}
|
//}
|
||||||
|
|
||||||
// CanTest returns true if the notifier implements the OnTest interface
|
// CanTest returns true if the notifier implements the OnTest interface
|
||||||
func (n *Notification) CanTest() bool {
|
//func (n *Notification) CanTest() bool {
|
||||||
return n.testable
|
// return n.testable
|
||||||
}
|
//}
|
||||||
|
|
||||||
// LastSent returns a time.Duration of the last sent notification for the notifier
|
// LastSent returns a time.Duration of the last sent notification for the notifier
|
||||||
func (n *Notification) LastSent() time.Duration {
|
func (n *Notification) LastSent() time.Duration {
|
||||||
if len(n.logs) == 0 {
|
since := time.Since(n.lastSent)
|
||||||
return time.Duration(0)
|
|
||||||
}
|
|
||||||
last := n.Logs()[0]
|
|
||||||
since := time.Since(last.Timestamp)
|
|
||||||
return since
|
return since
|
||||||
}
|
}
|
||||||
|
|
||||||
// SentLastHour returns the total amount of notifications sent in last 1 hour
|
func (n *Notification) CanSend() bool {
|
||||||
func (n *Notification) SentLastHour() int {
|
if !n.Enabled.Bool {
|
||||||
since := utils.Now().Add(-1 * time.Hour)
|
return false
|
||||||
return n.SentLast(since)
|
}
|
||||||
}
|
|
||||||
|
|
||||||
// SentLastMinute returns the total amount of notifications sent in last 1 minute
|
fmt.Println("Last sent: ", n.lastSent.String())
|
||||||
func (n *Notification) SentLastMinute() int {
|
fmt.Println("Last count: ", n.lastSentCount)
|
||||||
since := utils.Now().Add(-1 * time.Minute)
|
fmt.Println("Last sent before now: ", n.lastSent.Add(60*time.Second).Before(utils.Now()))
|
||||||
return n.SentLast(since)
|
|
||||||
}
|
|
||||||
|
|
||||||
// SentLast accept a time.Time and returns the amount of sent notifications within your time to current
|
// the last sent notification was past 1 minute (limit per minute)
|
||||||
func (n *Notification) SentLast(since time.Time) int {
|
if n.lastSent.Add(60 * time.Second).Before(utils.Now()) {
|
||||||
sent := 0
|
if n.lastSentCount != 0 {
|
||||||
for _, v := range n.Logs() {
|
n.lastSentCount--
|
||||||
lastTime := time.Time(v.Time).UTC()
|
|
||||||
if lastTime.After(since) {
|
|
||||||
sent++
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return sent
|
|
||||||
|
// dont send if already beyond the notifier's limit
|
||||||
|
if n.lastSentCount >= n.Limits {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
// action to do since notifier is able to send
|
||||||
|
n.lastSentCount++
|
||||||
|
n.lastSent = utils.Now()
|
||||||
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetValue returns the database value of a accept DbField value.
|
// GetValue returns the database value of a accept DbField value.
|
||||||
|
@ -130,18 +129,6 @@ func (n *Notification) ResetQueue() {
|
||||||
n.Queue = nil
|
n.Queue = nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// ResetQueue will clear the notifiers Queue for a service
|
|
||||||
func (n *Notification) ResetUniqueQueue(uid string) []*QueueData {
|
|
||||||
var queue []*QueueData
|
|
||||||
for _, v := range n.Queue {
|
|
||||||
if v.Id != uid {
|
|
||||||
queue = append(queue, v)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
n.Queue = queue
|
|
||||||
return queue
|
|
||||||
}
|
|
||||||
|
|
||||||
// start will start the go routine for the notifier queue
|
// start will start the go routine for the notifier queue
|
||||||
func (n *Notification) Start() {
|
func (n *Notification) Start() {
|
||||||
n.Running = make(chan bool)
|
n.Running = make(chan bool)
|
|
@ -0,0 +1,74 @@
|
||||||
|
package notifications
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/statping/statping/types/null"
|
||||||
|
"github.com/statping/statping/utils"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
log = utils.Log
|
||||||
|
)
|
||||||
|
|
||||||
|
// Notification contains all the fields for a Statping Notifier.
|
||||||
|
type Notification struct {
|
||||||
|
Id int64 `gorm:"primary_key;column:id" json:"id"`
|
||||||
|
Method string `gorm:"column:method" json:"method"`
|
||||||
|
Host string `gorm:"not null;column:host" json:"host,omitempty"`
|
||||||
|
Port int `gorm:"not null;column:port" json:"port,omitempty"`
|
||||||
|
Username string `gorm:"not null;column:username" json:"username,omitempty"`
|
||||||
|
Password string `gorm:"not null;column:password" json:"password,omitempty"`
|
||||||
|
Var1 string `gorm:"not null;column:var1" json:"var1,omitempty"`
|
||||||
|
Var2 string `gorm:"not null;column:var2" json:"var2,omitempty"`
|
||||||
|
ApiKey string `gorm:"not null;column:api_key" json:"api_key,omitempty"`
|
||||||
|
ApiSecret string `gorm:"not null;column:api_secret" json:"api_secret,omitempty"`
|
||||||
|
Enabled null.NullBool `gorm:"column:enabled;type:boolean;default:false" json:"enabled"`
|
||||||
|
Limits int `gorm:"not null;column:limits" json:"limits"`
|
||||||
|
Removable bool `gorm:"column:removable" json:"removeable"`
|
||||||
|
CreatedAt time.Time `gorm:"column:created_at" json:"created_at"`
|
||||||
|
UpdatedAt time.Time `gorm:"column:updated_at" json:"updated_at"`
|
||||||
|
Form []NotificationForm `gorm:"-" json:"form"`
|
||||||
|
Title string `gorm:"-" json:"title"`
|
||||||
|
Description string `gorm:"-" json:"description"`
|
||||||
|
Author string `gorm:"-" json:"author"`
|
||||||
|
AuthorUrl string `gorm:"-" json:"author_url"`
|
||||||
|
Icon string `gorm:"-" json:"icon"`
|
||||||
|
Delay time.Duration `gorm:"-" json:"delay,string"`
|
||||||
|
Running chan bool `gorm:"-" json:"-"`
|
||||||
|
|
||||||
|
Queue []RunFunc `gorm:"-" json:"-"`
|
||||||
|
|
||||||
|
lastSent time.Time `gorm:"-" json:"-"`
|
||||||
|
lastSentCount int `gorm:"-" json:"-"`
|
||||||
|
|
||||||
|
Hits notificationHits `gorm:"-" json:"-"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type RunFunc func(interface{}) error
|
||||||
|
|
||||||
|
// NotificationForm contains the HTML fields for each variable/input you want the notifier to accept.
|
||||||
|
type NotificationForm struct {
|
||||||
|
Type string `json:"type"` // the html input type (text, password, email)
|
||||||
|
Title string `json:"title"` // include a title for ease of use
|
||||||
|
Placeholder string `json:"placeholder"` // add a placeholder for the input
|
||||||
|
DbField string `json:"field"` // true variable key for input
|
||||||
|
SmallText string `json:"small_text"` // insert small text under a html input
|
||||||
|
Required bool `json:"required"` // require this input on the html form
|
||||||
|
IsHidden bool `json:"hidden"` // hide this form element from end user
|
||||||
|
IsList bool `json:"list"` // make this form element a comma separated list
|
||||||
|
IsSwitch bool `json:"switch"` // make the notifier a boolean true/false switch
|
||||||
|
}
|
||||||
|
|
||||||
|
type notificationHits struct {
|
||||||
|
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:"-"`
|
||||||
|
}
|
|
@ -0,0 +1,13 @@
|
||||||
|
package notifier
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/statping/statping/types/failures"
|
||||||
|
"github.com/statping/statping/types/services"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Notifier interface is required to create a new Notifier
|
||||||
|
type Notifier interface {
|
||||||
|
OnSuccess(*services.Service) error // OnSuccess is triggered when a service is successful
|
||||||
|
OnFailure(*services.Service, *failures.Failure) error // OnFailure is triggered when a service is failing
|
||||||
|
OnTest() error // OnTest is triggered for testing
|
||||||
|
}
|
|
@ -0,0 +1,21 @@
|
||||||
|
package services
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/statping/statping/types/failures"
|
||||||
|
"github.com/statping/statping/types/notifications"
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
allNotifiers []ServiceNotifier
|
||||||
|
)
|
||||||
|
|
||||||
|
func AllNotifiers() []ServiceNotifier {
|
||||||
|
return allNotifiers
|
||||||
|
}
|
||||||
|
|
||||||
|
type ServiceNotifier interface {
|
||||||
|
OnSuccess(*Service) error // OnSuccess is triggered when a service is successful
|
||||||
|
OnFailure(*Service, *failures.Failure) error // OnFailure is triggered when a service is failing
|
||||||
|
OnTest() error // OnTest is triggered for testing
|
||||||
|
Select() *notifications.Notification // OnTest is triggered for testing
|
||||||
|
}
|
|
@ -3,16 +3,17 @@ package services
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/statping/statping/types/failures"
|
|
||||||
"github.com/statping/statping/types/hits"
|
|
||||||
"github.com/statping/statping/utils"
|
|
||||||
"github.com/tatsushid/go-fastping"
|
|
||||||
"net"
|
"net"
|
||||||
"net/http"
|
"net/http"
|
||||||
"net/url"
|
"net/url"
|
||||||
"regexp"
|
"regexp"
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"github.com/statping/statping/types/failures"
|
||||||
|
"github.com/statping/statping/types/hits"
|
||||||
|
"github.com/statping/statping/utils"
|
||||||
|
"github.com/tatsushid/go-fastping"
|
||||||
)
|
)
|
||||||
|
|
||||||
// checkServices will start the checking go routine for each service
|
// checkServices will start the checking go routine for each service
|
||||||
|
@ -242,10 +243,36 @@ func recordSuccess(s *Service) {
|
||||||
fmt.Sprintf("Service #%d '%v' Successful Response: %s | Lookup in: %s | Online: %v | Interval: %d seconds", s.Id, s.Name, humanMicro(hit.Latency), humanMicro(hit.PingTime), s.Online, s.Interval))
|
fmt.Sprintf("Service #%d '%v' Successful Response: %s | Lookup in: %s | Online: %v | Interval: %d seconds", s.Id, s.Name, humanMicro(hit.Latency), humanMicro(hit.PingTime), s.Online, s.Interval))
|
||||||
s.LastLookupTime = hit.PingTime
|
s.LastLookupTime = hit.PingTime
|
||||||
s.LastLatency = hit.Latency
|
s.LastLatency = hit.Latency
|
||||||
//notifiers.OnSuccess(s)
|
sendSuccess(s)
|
||||||
s.SuccessNotified = true
|
s.SuccessNotified = true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func AddNotifier(n ServiceNotifier) {
|
||||||
|
allNotifiers = append(allNotifiers, n)
|
||||||
|
}
|
||||||
|
|
||||||
|
func sendSuccess(s *Service) {
|
||||||
|
if !s.AllowNotifications.Bool {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
// dont send notification if server was already previous online
|
||||||
|
if s.SuccessNotified {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
for _, n := range allNotifiers {
|
||||||
|
notif := n.Select()
|
||||||
|
if notif.CanSend() {
|
||||||
|
log.Infof("Sending notification to: %s!", notif.Method)
|
||||||
|
if err := n.OnSuccess(s); err != nil {
|
||||||
|
log.Errorln(err)
|
||||||
|
}
|
||||||
|
s.UserNotified = true
|
||||||
|
s.SuccessNotified = true
|
||||||
|
//s.UpdateNotify.Bool
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// recordFailure will create a new 'Failure' record in the database for a offline service
|
// recordFailure will create a new 'Failure' record in the database for a offline service
|
||||||
func recordFailure(s *Service, issue string) {
|
func recordFailure(s *Service, issue string) {
|
||||||
s.LastOffline = utils.Now()
|
s.LastOffline = utils.Now()
|
||||||
|
@ -266,7 +293,32 @@ func recordFailure(s *Service, issue string) {
|
||||||
s.Online = false
|
s.Online = false
|
||||||
s.SuccessNotified = false
|
s.SuccessNotified = false
|
||||||
s.DownText = s.DowntimeText()
|
s.DownText = s.DowntimeText()
|
||||||
//notifiers.OnFailure(s, fail)
|
sendFailure(s, fail)
|
||||||
|
}
|
||||||
|
|
||||||
|
func sendFailure(s *Service, f *failures.Failure) {
|
||||||
|
if !s.AllowNotifications.Bool {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// ignore failure if user was already notified and
|
||||||
|
// they have "continuous notifications" switched off.
|
||||||
|
if s.UserNotified && !s.UpdateNotify.Bool {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, n := range allNotifiers {
|
||||||
|
notif := n.Select()
|
||||||
|
if notif.CanSend() {
|
||||||
|
log.Infof("Sending Failure notification to: %s!", notif.Method)
|
||||||
|
if err := n.OnFailure(s, f); err != nil {
|
||||||
|
log.Errorln(err)
|
||||||
|
}
|
||||||
|
s.UserNotified = true
|
||||||
|
s.SuccessNotified = true
|
||||||
|
//s.UpdateNotify.Bool
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check will run checkHttp for HTTP services and checkTcp for TCP services
|
// Check will run checkHttp for HTTP services and checkTcp for TCP services
|
||||||
|
|
Loading…
Reference in New Issue