pull/429/head
hunterlong 2020-03-11 21:58:56 -07:00
parent bbf8073315
commit 6958f41997
41 changed files with 243 additions and 162 deletions

View File

@ -1,13 +1,13 @@
package main
import (
"github.com/statping/statping/notifiers"
"github.com/statping/statping/types/checkins"
"github.com/statping/statping/types/failures"
"github.com/statping/statping/types/groups"
"github.com/statping/statping/types/hits"
"github.com/statping/statping/types/incidents"
"github.com/statping/statping/types/messages"
"github.com/statping/statping/types/notifications"
"github.com/statping/statping/types/services"
"github.com/statping/statping/types/users"
)
@ -18,5 +18,5 @@ var (
)
func init() {
DbModels = []interface{}{&services.Service{}, &users.User{}, &hits.Hit{}, &failures.Failure{}, &messages.Message{}, &groups.Group{}, &checkins.Checkin{}, &checkins.CheckinHit{}, &notifications.Notification{}, &incidents.Incident{}, &incidents.IncidentUpdate{}}
DbModels = []interface{}{&services.Service{}, &users.User{}, &hits.Hit{}, &failures.Failure{}, &messages.Message{}, &groups.Group{}, &checkins.Checkin{}, &checkins.CheckinHit{}, &notifiers.Notification{}, &incidents.Incident{}, &incidents.IncidentUpdate{}}
}

View File

@ -19,11 +19,13 @@
"@sentry/integrations": "^5.13.2",
"apexcharts": "^3.15.0",
"axios": "^0.19.1",
"bootstrap": "^4.4.1",
"bootstrap-vue": "^2.6.1",
"codemirror-colorpicker": "^1.9.66",
"core-js": "^3.4.4",
"date-fns": "^2.9.0",
"querystring": "^0.2.0",
"vue": "^2.6.10",
"vue": "^2.6.11",
"vue-apexcharts": "^1.5.2",
"vue-codemirror": "^4.0.6",
"vue-flatpickr-component": "^8.1.5",

View File

@ -18,7 +18,7 @@
{{if USING_ASSETS}}
<link href="css/vendor.css" rel="stylesheet">
<link href="css/style.css" rel="stylesheet">
<link rel="stylesheet" href="css/base.css">
<link href="css/base.css" rel="stylesheet">
{{else}}
<% _.each(htmlWebpackPlugin.tags.headTags, function(headTag) { %>
<%= headTag %> <% }) %>

View File

@ -53,7 +53,5 @@
<style lang="scss">
@import "./assets/css/bootstrap.min.css";
@import "./assets/scss/variables";
@import "./assets/scss/base";
@import "./assets/scss/mobile";
@import "./assets/scss/main";
</style>

Binary file not shown.

After

Width:  |  Height:  |  Size: 96 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.7 KiB

After

Width:  |  Height:  |  Size: 574 KiB

View File

@ -1,6 +1,3 @@
@import 'variables';
HTML,BODY {
background-color: $background-color;
}
@ -32,7 +29,7 @@ HTML,BODY {
}
.service-chart {
bottom: -15px;
bottom: -16px;
position: relative;
}
@ -668,4 +665,4 @@ HTML,BODY {
opacity: 0;
}
@import 'mobile';
@import 'mobile';

View File

@ -0,0 +1,3 @@
@import 'variables';
@import 'base';
@import 'mobile';

View File

@ -1,5 +1,3 @@
@import 'variables';
@media (max-width: 767px) {
HTML,BODY {

View File

@ -12,7 +12,7 @@ $service-title-size: 1.8rem;
$service-stats-color: #4f4f4f;
$service-description-color: #fff;
$service-stats-size: 2.3rem;
$service-card-height: 490px;
$service-card-height: 480px !important;
/* Button Colors */
$success-color: #47d337;

View File

@ -43,9 +43,9 @@
</div>
<div class="col-md-4 col-6 float-right">
<router-link :to="serviceLink(service)" class="d-none btn btn-sm float-right dyn-dark btn-block text-white" :class="{'bg-success': service.online, 'bg-danger': !service.online}">
<router-link :to="serviceLink(service)" class="d-none btn btn-sm float-right dyn-dark text-white" :class="{'bg-success': service.online, 'bg-danger': !service.online}">
View Service</router-link>
<button @click="expanded = !expanded" class="btn btn-sm float-right dyn-dark btn-block text-white" :class="{'bg-success': service.online, 'bg-danger': !service.online}">View Service</button>
<button @click="expanded = !expanded" class="btn btn-sm float-right dyn-dark text-white" :class="{'bg-success': service.online, 'bg-danger': !service.online}">View Service</button>
</div>
<div v-if="expanded" class="row">

View File

@ -12,7 +12,7 @@
<div v-for="(form, index) in notifier.form" v-bind:key="index" class="form-group">
<label class="text-capitalize">{{form.title}}</label>
<input v-if="form.type === 'text' || 'number' || 'password'" v-model="notifier[form.field]" :type="form.type" class="form-control" :placeholder="form.placeholder" >
<input v-if="form.type === 'text' || 'number' || 'password'" v-model="notifier[form.field.toLowerCase()]" :type="form.type" class="form-control" :placeholder="form.placeholder" >
<small class="form-text text-muted" v-html="form.small_text"></small>
</div>
@ -53,6 +53,7 @@
<span class="d-block small text-center mt-5 mb-5">
<span class="text-capitalize">{{notifier.title}}</span> Notifier created by <a :href="notifier.author_url" target="_blank">{{notifier.author}}</a>
</span>
</form>
</template>
@ -73,6 +74,7 @@ export default {
error: null,
saved: false,
ok: false,
form: {},
}
},
mounted() {
@ -81,14 +83,14 @@ export default {
methods: {
async saveNotifier() {
this.loading = true
let form = {}
this.form.enabled = this.notifier.enabled
this.form.limits = parseInt(this.notifier.limits)
this.form.method = this.notifier.method
this.notifier.form.forEach((f) => {
form[f.field] = this.notifier[f.field]
let field = f.field.toLowerCase()
this.form[field] = this.notifier[field]
});
form.enabled = this.notifier.enabled
form.limits = parseInt(this.notifier.limits)
form.method = this.notifier.method
await Api.notifier_save(form)
await Api.notifier_save(this.form)
const notifiers = await Api.notifiers()
await this.$store.commit('setNotifiers', notifiers)
this.saved = true

View File

@ -227,6 +227,8 @@
delete s.last_success
delete s.latency
delete s.online_24_hours
s.check_interval = parseInt(s.check_interval)
if (s.id) {
await this.updateService(s)
} else {

View File

@ -76,6 +76,13 @@ const routes = [
const router = new VueRouter({
mode: 'history',
scrollBehavior (to, from, savedPosition) {
if (savedPosition) {
return savedPosition
} else {
return { x: 0, y: 0 }
}
},
routes
})

View File

@ -1040,6 +1040,15 @@
"@nodelib/fs.scandir" "2.1.3"
fastq "^1.6.0"
"@nuxt/opencollective@^0.3.0":
version "0.3.0"
resolved "https://registry.yarnpkg.com/@nuxt/opencollective/-/opencollective-0.3.0.tgz#11d8944dcf2d526e31660bb69570be03f8fb72b7"
integrity sha512-Vf09BxCdj1iT2IRqVwX5snaY2WCTkvM0O4cWWSO1ThCFuc4if0Q/nNwAgCxRU0FeYHJ7DdyMUNSdswCLKlVqeg==
dependencies:
chalk "^2.4.2"
consola "^2.10.1"
node-fetch "^2.6.0"
"@sentry/browser@^5.13.2":
version "5.13.2"
resolved "https://registry.yarnpkg.com/@sentry/browser/-/browser-5.13.2.tgz#fcca630c8c80447ba8392803d4e4450fd2231b92"
@ -2165,6 +2174,22 @@ boolbase@^1.0.0, boolbase@~1.0.0:
resolved "https://registry.yarnpkg.com/boolbase/-/boolbase-1.0.0.tgz#68dff5fbe60c51eb37725ea9e3ed310dcc1e776e"
integrity sha1-aN/1++YMUes3cl6p4+0xDcwed24=
bootstrap-vue@^2.6.1:
version "2.6.1"
resolved "https://registry.yarnpkg.com/bootstrap-vue/-/bootstrap-vue-2.6.1.tgz#ee96e2e4d277a9044b378e925ef703b2bd9d27c4"
integrity sha512-eOL06T2sjOREUiyN1IZCFYANKrb+tqRqe1pgwjXjbjYa3oclYT6E99v/O12W0Eq9i7+0rQiy+wFOSkFL2yvnng==
dependencies:
"@nuxt/opencollective" "^0.3.0"
bootstrap ">=4.4.1 <5.0.0"
popper.js "^1.16.1"
portal-vue "^2.1.7"
vue-functional-data-merge "^3.1.0"
"bootstrap@>=4.4.1 <5.0.0", bootstrap@^4.4.1:
version "4.4.1"
resolved "https://registry.yarnpkg.com/bootstrap/-/bootstrap-4.4.1.tgz#8582960eea0c5cd2bede84d8b0baf3789c3e8b01"
integrity sha512-tbx5cHubwE6e2ZG7nqM3g/FZ5PQEDMWmMGNrCUBVRPHXTJaH7CBDdsLeu3eCh3B1tzAxTnAbtmrzvWEvT2NNEA==
brace-expansion@^1.1.7:
version "1.1.11"
resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.11.tgz#3c7fcbf529d87226f3d2f52b966ff5271eb441dd"
@ -2954,6 +2979,11 @@ connect-history-api-fallback@^1.3.0, connect-history-api-fallback@^1.6.0:
resolved "https://registry.yarnpkg.com/connect-history-api-fallback/-/connect-history-api-fallback-1.6.0.tgz#8b32089359308d111115d81cad3fceab888f97bc"
integrity sha512-e54B99q/OUoH64zYYRf3HBP5z24G38h5D3qXu23JGRoigpX5Ss4r9ZnDk3g0Z8uQC2x2lPaJ+UlWBc1ZWBWdLg==
consola@^2.10.1:
version "2.11.3"
resolved "https://registry.yarnpkg.com/consola/-/consola-2.11.3.tgz#f7315836224c143ac5094b47fd4c816c2cd1560e"
integrity sha512-aoW0YIIAmeftGR8GSpw6CGQluNdkWMWh3yEFjH/hmynTYnMtibXszii3lxCXmk8YxJtI3FAK5aTiquA5VH68Gw==
console-browserify@^1.1.0:
version "1.2.0"
resolved "https://registry.yarnpkg.com/console-browserify/-/console-browserify-1.2.0.tgz#67063cef57ceb6cf4993a2ab3a55840ae8c49336"
@ -6904,6 +6934,11 @@ node-environment-flags@1.0.6:
object.getownpropertydescriptors "^2.0.3"
semver "^5.7.0"
node-fetch@^2.6.0:
version "2.6.0"
resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.6.0.tgz#e633456386d4aa55863f676a7ab0daa8fdecb0fd"
integrity sha512-8dG4H5ujfvFiqDmVu9fQ5bOHUC15JMjMY/Zumv26oOvvVJjM67KF8koCWIabKQ1GJIa9r2mMZscBq/TbdOcmNA==
node-forge@0.9.0:
version "0.9.0"
resolved "https://registry.yarnpkg.com/node-forge/-/node-forge-0.9.0.tgz#d624050edbb44874adca12bb9a52ec63cb782579"
@ -7701,6 +7736,16 @@ pnp-webpack-plugin@^1.6.0:
dependencies:
ts-pnp "^1.1.6"
popper.js@^1.16.1:
version "1.16.1"
resolved "https://registry.yarnpkg.com/popper.js/-/popper.js-1.16.1.tgz#2a223cb3dc7b6213d740e40372be40de43e65b1b"
integrity sha512-Wb4p1J4zyFTbM+u6WuO4XstYx4Ky9Cewe4DWrel7B0w6VVICvPwdOpotjzcf6eD8TsckVnIMNONQyPIUFOUbCQ==
portal-vue@^2.1.7:
version "2.1.7"
resolved "https://registry.yarnpkg.com/portal-vue/-/portal-vue-2.1.7.tgz#ea08069b25b640ca08a5b86f67c612f15f4e4ad4"
integrity sha512-+yCno2oB3xA7irTt0EU5Ezw22L2J51uKAacE/6hMPMoO/mx3h4rXFkkBkT4GFsMDv/vEe8TNKC3ujJJ0PTwb6g==
portfinder@^1.0.25, portfinder@^1.0.9:
version "1.0.25"
resolved "https://registry.yarnpkg.com/portfinder/-/portfinder-1.0.25.tgz#254fd337ffba869f4b9d37edc298059cb4d35eca"
@ -10138,6 +10183,11 @@ vue-flatpickr-component@^8.1.5:
dependencies:
flatpickr "^4.6.1"
vue-functional-data-merge@^3.1.0:
version "3.1.0"
resolved "https://registry.yarnpkg.com/vue-functional-data-merge/-/vue-functional-data-merge-3.1.0.tgz#08a7797583b7f35680587f8a1d51d729aa1dc657"
integrity sha512-leT4kdJVQyeZNY1kmnS1xiUlQ9z1B/kdBFCILIjYYQDqZgLqCLa0UhjSSeRX6c3mUe6U5qYeM8LrEqkHJ1B4LA==
vue-hot-reload-api@^2.3.0:
version "2.3.4"
resolved "https://registry.yarnpkg.com/vue-hot-reload-api/-/vue-hot-reload-api-2.3.4.tgz#532955cc1eb208a3d990b3a9f9a70574657e08f2"
@ -10203,7 +10253,7 @@ vue-template-es2015-compiler@^1.9.0:
resolved "https://registry.yarnpkg.com/vue-template-es2015-compiler/-/vue-template-es2015-compiler-1.9.1.tgz#1ee3bc9a16ecbf5118be334bb15f9c46f82f5825"
integrity sha512-4gDntzrifFnCEvyoO8PqyJDmguXgVPxKiIxrBKjIowvL9l+N66196+72XVYR8BBf1Uv1Fgt3bGevJ+sEmxfZzw==
vue@^2.6.10:
vue@^2.6.11:
version "2.6.11"
resolved "https://registry.yarnpkg.com/vue/-/vue-2.6.11.tgz#76594d877d4b12234406e84e35275c6d514125c5"
integrity sha512-VfPwgcGABbGAue9+sfrD4PuwFar7gPb1yl1UK1MwXoQPAw0BKSqWfoYCT/ThFrdEVWoI51dBuyCoiNU9bZDZxQ==

View File

@ -19,12 +19,12 @@ import (
"encoding/json"
"errors"
"fmt"
"github.com/statping/statping/notifiers"
"github.com/statping/statping/types/checkins"
"github.com/statping/statping/types/core"
"github.com/statping/statping/types/groups"
"github.com/statping/statping/types/incidents"
"github.com/statping/statping/types/messages"
"github.com/statping/statping/types/notifications"
"github.com/statping/statping/types/null"
"github.com/statping/statping/types/services"
"github.com/statping/statping/types/users"
@ -143,7 +143,7 @@ func sendJsonAction(obj interface{}, method string, w http.ResponseWriter, r *ht
case *services.Service:
objName = "service"
objId = v.Id
case *notifications.Notification:
case *notifiers.Notification:
objName = "notifier"
objId = v.Id
case *core.Core:

View File

@ -19,21 +19,24 @@ import (
"encoding/json"
"fmt"
"github.com/gorilla/mux"
"github.com/statping/statping/types/core"
"github.com/statping/statping/types/notifications"
"github.com/statping/statping/notifiers"
"github.com/statping/statping/types/null"
"github.com/statping/statping/utils"
"net/http"
)
func apiNotifiersHandler(w http.ResponseWriter, r *http.Request) {
all := notifications.All()
returnJson(all, w, r)
var notifs []notifiers.Notifier
all := notifiers.All()
for _, v := range all {
notifs = append(notifs, v)
}
returnJson(notifs, w, r)
}
func apiNotifierGetHandler(w http.ResponseWriter, r *http.Request) {
vars := mux.Vars(r)
notifier, err := notifications.Find(vars["notifier"])
notifier, err := notifiers.Find(vars["notifier"])
if err != nil {
sendErrorJson(err, w, r)
return
@ -43,26 +46,24 @@ func apiNotifierGetHandler(w http.ResponseWriter, r *http.Request) {
func apiNotifierUpdateHandler(w http.ResponseWriter, r *http.Request) {
vars := mux.Vars(r)
notifer, err := notifications.Find(vars["notifier"])
notifer, err := notifiers.Find(vars["notifier"])
if err != nil {
sendErrorJson(err, w, r)
return
}
n := notifer.Select()
decoder := json.NewDecoder(r.Body)
err = decoder.Decode(&n)
err = decoder.Decode(&notifer)
if err != nil {
sendErrorJson(err, w, r)
return
}
err = n.Update()
err = notifer.Update()
if err != nil {
sendErrorJson(err, w, r)
return
}
notifications.OnSave(n.Method)
//notifications.OnSave(notifer.Method)
sendJsonAction(notifer, "update", w, r)
}
@ -82,14 +83,14 @@ func testNotificationHandler(w http.ResponseWriter, r *http.Request) {
apiSecret := form.Get("api_secret")
limits := int(utils.ToInt(form.Get("limits")))
notifier, err := notifications.Find(method)
notifier, err := notifiers.Find(method)
if err != nil {
log.Errorln(fmt.Sprintf("issue saving notifier %v: %v", method, err))
ExecuteResponse(w, r, "settings.gohtml", core.App, "settings")
sendErrorJson(err, w, r)
return
}
n := notifier.Select()
n := notifier
if host != "" {
n.Host = host

View File

@ -17,8 +17,8 @@ package handlers
import (
"fmt"
"github.com/statping/statping/notifiers"
"github.com/statping/statping/types/failures"
"github.com/statping/statping/types/notifications"
"github.com/statping/statping/types/services"
"github.com/statping/statping/utils"
"net/http"
@ -104,7 +104,7 @@ func prometheusHandler(w http.ResponseWriter, r *http.Request) {
}
for _, n := range notifications.All() {
for _, n := range notifiers.All() {
notif := n.Select()
PrometheusComment(fmt.Sprintf("Notifier %s:", notif.Method))
enabled := 0

View File

@ -1,4 +1,4 @@
package notifications
package notifiers
import (
"errors"
@ -11,14 +11,14 @@ func SetDB(database database.Database) {
db = database.Model(&Notification{})
}
func Append(n Notifier) {
func appendList(n Notifier) {
allNotifiers = append(allNotifiers, n)
}
func Find(name string) (*Notification, error) {
for _, n := range allNotifiers {
notif := n.Select()
if notif.Name() == name || notif.Method == name {
notif := n.(*Notification)
if notif.Method == name {
return notif, nil
}
}
@ -30,12 +30,13 @@ func All() []Notifier {
}
func (n *Notification) Create() error {
var notif Notification
if db.Where("method = ?", n.Method).Find(&notif).RecordNotFound() {
Append(n)
return db.Create(n).Error()
q := db.Where("method = ?", n.Method).Find(n)
if q.RecordNotFound() {
if err := db.Create(n).Error(); err != nil {
return err
}
Append(n)
}
appendList(n)
return nil
}
@ -44,7 +45,7 @@ func (n *Notification) Update() error {
if n.Enabled.Bool {
n.Close()
n.Start()
go Queue(Notifier(n))
go Queue(n)
} else {
n.Close()
}

View File

@ -13,7 +13,7 @@
// 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 notifications
package notifiers
import (
"fmt"
@ -27,9 +27,9 @@ import (
func OnSave(method string) {
for _, comm := range allNotifiers {
if utils.IsType(comm, new(Notifier)) {
notifier := comm.(Notifier)
if notifier.Select().Method == method {
notifier.OnSave()
notifier := comm.Select()
if notifier.Method == method {
comm.OnSave()
}
}
}
@ -55,7 +55,7 @@ func OnFailure(s *services.Service, f *failures.Failure) {
sendMessages:
for _, comm := range allNotifiers {
if utils.IsType(comm, new(BasicEvents)) && isEnabled(comm) && (s.Online || inLimits(comm)) {
notifier := comm.(Notifier).Select()
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))
@ -78,7 +78,7 @@ func OnSuccess(s *services.Service) {
for _, comm := range allNotifiers {
if utils.IsType(comm, new(BasicEvents)) && isEnabled(comm) && (!s.Online || inLimits(comm)) {
notifier := comm.(Notifier).Select()
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))

View File

@ -117,4 +117,4 @@
// see more details and examples of how to build your own notifier.
//
// More info on: https://github.com/statping/statping/wiki/Notifiers
package notifications
package _interface

View File

@ -13,7 +13,7 @@
// 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 notifications
package notifiers
import (
"github.com/statping/statping/types/failures"

View File

@ -1,4 +1,4 @@
package notifications
package notifiers
import (
"fmt"

View File

@ -1,4 +1,4 @@
package notifications
package notifiers
import (
"github.com/statping/statping/database"

View File

@ -3,7 +3,9 @@ package notifiers
import (
"fmt"
"github.com/google/martian/log"
"github.com/statping/statping/types/notifications"
"github.com/statping/statping/notifiers/senders"
"github.com/statping/statping/types/failures"
"github.com/statping/statping/types/services"
"github.com/statping/statping/utils"
"strings"
)
@ -12,7 +14,24 @@ var (
allowedVars = []string{"host", "username", "password", "port", "api_key", "api_secret", "var1", "var2"}
)
func checkNotifierForm(n *notifications.Notification) error {
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 {
@ -32,7 +51,7 @@ func contains(s string, arr []string) bool {
}
// AddNotifier accept a Notifier interface to be added into the array
func AddNotifiers(notifiers ...notifications.Notifier) error {
func AddNotifiers(notifiers ...Notifier) error {
log.Infof("Initiating %d Notifiers\n", len(notifiers))
for _, n := range notifiers {
@ -49,12 +68,10 @@ func AddNotifiers(notifiers ...notifications.Notifier) error {
return err
}
notifications.Append(notif)
if notif.Enabled.Bool {
notif.Close()
notif.Start()
go notifications.Queue(notif)
go Queue(notif)
}
}
@ -63,14 +80,14 @@ func AddNotifiers(notifiers ...notifications.Notifier) error {
// startAllNotifiers will start the go routine for each loaded notifier
func startAllNotifiers() {
for _, notify := range notifications.All() {
for _, notify := range All() {
n := notify.Select()
log.Infof("Initiating %s Notifier\n", n.Method)
if utils.IsType(notify, new(notifications.Notifier)) {
if utils.IsType(notify, new(Notifier)) {
if n.Enabled.Bool {
n.Close()
n.Start()
go notifications.Queue(notify)
go Queue(notify)
}
}
}
@ -78,14 +95,14 @@ func startAllNotifiers() {
func Migrate() error {
return AddNotifiers(
Command,
Discorder,
Emailer,
LineNotify,
Mobile,
Slacker,
Telegram,
Twilio,
Webhook,
senders.Command,
senders.Discorder,
senders.Emailer,
senders.LineNotify,
senders.Mobile,
senders.Slacker,
senders.Telegram,
senders.Twilio,
senders.Webhook,
)
}

View File

@ -13,25 +13,25 @@
// 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
package senders
import (
"fmt"
"github.com/statping/statping/notifiers"
"github.com/statping/statping/types/failures"
"github.com/statping/statping/types/notifications"
"github.com/statping/statping/types/services"
"github.com/statping/statping/utils"
"strings"
"time"
)
var _ notifications.Notifier = (*commandLine)(nil)
var _ notifiers.Notifier = (*commandLine)(nil)
type commandLine struct {
*notifications.Notification
*notifiers.Notification
}
var Command = &commandLine{&notifications.Notification{
var Command = &commandLine{&notifiers.Notification{
Method: "command",
Title: "Shell Command",
Description: "Shell Command allows you to run a customized shell/bash Command on the local machine it's running on.",
@ -40,7 +40,7 @@ var Command = &commandLine{&notifications.Notification{
Delay: time.Duration(1 * time.Second),
Icon: "fas fa-terminal",
Host: "/bin/bash",
Form: []notifications.NotificationForm{{
Form: []notifiers.NotificationForm{{
Type: "text",
Title: "Shell or Bash",
Placeholder: "/bin/bash",
@ -66,7 +66,7 @@ func runCommand(app string, cmd ...string) (string, string, error) {
return outStr, errStr, err
}
func (u *commandLine) Select() *notifications.Notification {
func (u *commandLine) Select() *notifiers.Notification {
return u.Notification
}

View File

@ -13,28 +13,28 @@
// 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
package senders
import (
"bytes"
"encoding/json"
"errors"
"fmt"
"github.com/statping/statping/notifiers"
"github.com/statping/statping/types/failures"
"github.com/statping/statping/types/notifications"
"github.com/statping/statping/types/services"
"github.com/statping/statping/utils"
"strings"
"time"
)
var _ notifications.Notifier = (*discord)(nil)
var _ notifiers.Notifier = (*discord)(nil)
type discord struct {
*notifications.Notification
*notifiers.Notification
}
var Discorder = &discord{&notifications.Notification{
var Discorder = &discord{&notifiers.Notification{
Method: "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>.",
@ -43,7 +43,7 @@ var Discorder = &discord{&notifications.Notification{
Delay: time.Duration(5 * time.Second),
Host: "https://discordapp.com/api/webhooks/****/*****",
Icon: "fab fa-discord",
Form: []notifications.NotificationForm{{
Form: []notifiers.NotificationForm{{
Type: "text",
Title: "discord webhooker URL",
Placeholder: "Insert your Webhook URL here",
@ -58,7 +58,7 @@ func (u *discord) Send(msg interface{}) error {
return err
}
func (u *discord) Select() *notifications.Notification {
func (u *discord) Select() *notifiers.Notification {
return u.Notification
}

View File

@ -13,15 +13,15 @@
// 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
package senders
import (
"bytes"
"crypto/tls"
"fmt"
"github.com/go-mail/mail"
"github.com/statping/statping/notifiers"
"github.com/statping/statping/types/failures"
"github.com/statping/statping/types/notifications"
"github.com/statping/statping/types/null"
"github.com/statping/statping/types/services"
"github.com/statping/statping/utils"
@ -29,7 +29,7 @@ import (
"time"
)
var _ notifications.Notifier = (*email)(nil)
var _ notifiers.Notifier = (*email)(nil)
const (
mainEmailTemplate = `<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
@ -112,17 +112,17 @@ var (
)
type email struct {
*notifications.Notification
*notifiers.Notification
}
var Emailer = &email{&notifications.Notification{
var Emailer = &email{&notifiers.Notification{
Method: "email",
Title: "email",
Description: "Send emails via SMTP when services are online or offline.",
Author: "Hunter Long",
AuthorUrl: "https://github.com/hunterlong",
Icon: "far fa-envelope",
Form: []notifications.NotificationForm{{
Form: []notifiers.NotificationForm{{
Type: "text",
Title: "SMTP Host",
Placeholder: "Insert your SMTP Host here.",
@ -211,7 +211,7 @@ func (u *email) OnSuccess(s *services.Service) {
}
}
func (u *email) Select() *notifications.Notification {
func (u *email) Select() *notifiers.Notification {
return u.Notification
}

View File

@ -13,12 +13,12 @@
// 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
package senders
import (
"fmt"
"github.com/statping/statping/notifiers"
"github.com/statping/statping/types/failures"
"github.com/statping/statping/types/notifications"
"github.com/statping/statping/types/services"
"github.com/statping/statping/utils"
"net/url"
@ -26,24 +26,24 @@ import (
"time"
)
var _ notifications.Notifier = (*lineNotifier)(nil)
var _ notifiers.Notifier = (*lineNotifier)(nil)
const (
lineNotifyMethod = "line_notify"
)
type lineNotifier struct {
*notifications.Notification
*notifiers.Notification
}
var LineNotify = &lineNotifier{&notifications.Notification{
var LineNotify = &lineNotifier{&notifiers.Notification{
Method: lineNotifyMethod,
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>.",
Author: "Kanin Peanviriyakulkit",
AuthorUrl: "https://github.com/dogrocker",
Icon: "far fa-bell",
Form: []notifications.NotificationForm{{
Form: []notifiers.NotificationForm{{
Type: "text",
Title: "Access Token",
Placeholder: "Insert your Line Notify Access Token here.",
@ -61,7 +61,7 @@ func (u *lineNotifier) Send(msg interface{}) error {
return err
}
func (u *lineNotifier) Select() *notifications.Notification {
func (u *lineNotifier) Select() *notifiers.Notification {
return u.Notification
}

View File

@ -13,28 +13,28 @@
// 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
package senders
import (
"bytes"
"encoding/json"
"fmt"
"github.com/statping/statping/notifiers"
"github.com/statping/statping/types/failures"
"github.com/statping/statping/types/notifications"
"github.com/statping/statping/types/services"
"github.com/statping/statping/utils"
"time"
)
var _ notifications.Notifier = (*mobilePush)(nil)
var _ notifiers.Notifier = (*mobilePush)(nil)
const mobileIdentifier = "com.statping"
type mobilePush struct {
*notifications.Notification
*notifiers.Notification
}
var Mobile = &mobilePush{&notifications.Notification{
var Mobile = &mobilePush{&notifiers.Notification{
Method: "mobile",
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.
@ -43,7 +43,7 @@ var Mobile = &mobilePush{&notifications.Notification{
AuthorUrl: "https://github.com/hunterlong",
Delay: time.Duration(5 * time.Second),
Icon: "fas fa-mobile-alt",
Form: []notifications.NotificationForm{{
Form: []notifiers.NotificationForm{{
Type: "text",
Title: "Device Identifiers",
Placeholder: "A list of your Mobile device push notification ID's.",
@ -58,7 +58,7 @@ var Mobile = &mobilePush{&notifications.Notification{
}}},
}
func (u *mobilePush) Select() *notifications.Notification {
func (u *mobilePush) Select() *notifiers.Notification {
return u.Notification
}

View File

@ -13,14 +13,14 @@
// 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
package senders
import (
"bytes"
"errors"
"fmt"
"github.com/statping/statping/notifiers"
"github.com/statping/statping/types/failures"
"github.com/statping/statping/types/notifications"
"github.com/statping/statping/types/services"
"github.com/statping/statping/utils"
"strings"
@ -28,7 +28,7 @@ import (
"time"
)
var _ notifications.Notifier = (*slack)(nil)
var _ notifiers.Notifier = (*slack)(nil)
const (
slackMethod = "slack"
@ -38,10 +38,10 @@ const (
)
type slack struct {
*notifications.Notification
*notifiers.Notification
}
var Slacker = &slack{&notifications.Notification{
var Slacker = &slack{&notifiers.Notification{
Method: slackMethod,
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>.",
@ -50,7 +50,7 @@ var Slacker = &slack{&notifications.Notification{
Delay: time.Duration(10 * time.Second),
Host: "https://webhooksurl.slack.com/***",
Icon: "fab fa-slack",
Form: []notifications.NotificationForm{{
Form: []notifiers.NotificationForm{{
Type: "text",
Title: "Incoming webhooker Url",
Placeholder: "Insert your slack Webhook URL here.",
@ -85,7 +85,7 @@ func (u *slack) Send(msg interface{}) error {
return err
}
func (u *slack) Select() *notifications.Notification {
func (u *slack) Select() *notifiers.Notification {
return u.Notification
}

View File

@ -13,14 +13,14 @@
// 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
package senders
import (
"encoding/json"
"errors"
"fmt"
"github.com/statping/statping/notifiers"
"github.com/statping/statping/types/failures"
"github.com/statping/statping/types/notifications"
"github.com/statping/statping/types/services"
"github.com/statping/statping/utils"
"net/url"
@ -28,13 +28,13 @@ import (
"time"
)
var _ notifications.Notifier = (*telegram)(nil)
var _ notifiers.Notifier = (*telegram)(nil)
type telegram struct {
*notifications.Notification
*notifiers.Notification
}
var Telegram = &telegram{&notifications.Notification{
var Telegram = &telegram{&notifiers.Notification{
Method: "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.",
@ -42,7 +42,7 @@ var Telegram = &telegram{&notifications.Notification{
AuthorUrl: "https://github.com/hunterlong",
Icon: "fab fa-telegram-plane",
Delay: time.Duration(5 * time.Second),
Form: []notifications.NotificationForm{{
Form: []notifiers.NotificationForm{{
Type: "text",
Title: "Telegram API Token",
Placeholder: "383810182:EEx829dtCeufeQYXG7CUdiQopqdmmxBPO7-s",
@ -59,7 +59,7 @@ var Telegram = &telegram{&notifications.Notification{
}}},
}
func (u *telegram) Select() *notifications.Notification {
func (u *telegram) Select() *notifiers.Notification {
return u.Notification
}

View File

@ -13,14 +13,14 @@
// 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
package senders
import (
"encoding/json"
"errors"
"fmt"
"github.com/statping/statping/notifiers"
"github.com/statping/statping/types/failures"
"github.com/statping/statping/types/notifications"
"github.com/statping/statping/types/services"
"github.com/statping/statping/utils"
"net/url"
@ -28,13 +28,13 @@ import (
"time"
)
var _ notifications.Notifier = (*twilio)(nil)
var _ notifiers.Notifier = (*twilio)(nil)
type twilio struct {
*notifications.Notification
*notifiers.Notification
}
var Twilio = &twilio{&notifications.Notification{
var Twilio = &twilio{&notifiers.Notification{
Method: "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>.",
@ -42,7 +42,7 @@ var Twilio = &twilio{&notifications.Notification{
AuthorUrl: "https://github.com/hunterlong",
Icon: "far fa-comment-alt",
Delay: time.Duration(10 * time.Second),
Form: []notifications.NotificationForm{{
Form: []notifiers.NotificationForm{{
Type: "text",
Title: "Account SID",
Placeholder: "Insert your Twilio Account SID",
@ -69,7 +69,7 @@ var Twilio = &twilio{&notifications.Notification{
}}},
}
func (u *twilio) Select() *notifications.Notification {
func (u *twilio) Select() *notifiers.Notification {
return u.Notification
}

View File

@ -13,13 +13,13 @@
// 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
package senders
import (
"bytes"
"fmt"
"github.com/statping/statping/notifiers"
"github.com/statping/statping/types/failures"
"github.com/statping/statping/types/notifications"
"github.com/statping/statping/types/services"
"github.com/statping/statping/utils"
"io/ioutil"
@ -28,17 +28,17 @@ import (
"time"
)
var _ notifications.Notifier = (*webhooker)(nil)
var _ notifiers.Notifier = (*webhooker)(nil)
const (
webhookMethod = "webhook"
)
type webhooker struct {
*notifications.Notification
*notifiers.Notification
}
var Webhook = &webhooker{&notifications.Notification{
var Webhook = &webhooker{&notifiers.Notification{
Method: webhookMethod,
Title: "HTTP webhooker",
Description: "Send a custom HTTP request to a specific URL with your own body, headers, and parameters.",
@ -46,7 +46,7 @@ var Webhook = &webhooker{&notifications.Notification{
AuthorUrl: "https://github.com/hunterlong",
Icon: "fas fa-code-branch",
Delay: time.Duration(1 * time.Second),
Form: []notifications.NotificationForm{{
Form: []notifiers.NotificationForm{{
Type: "text",
Title: "HTTP Endpoint",
Placeholder: "http://webhookurl.com/JW2MCP4SKQP",
@ -90,7 +90,7 @@ func (w *webhooker) Send(msg interface{}) error {
return err
}
func (w *webhooker) Select() *notifications.Notification {
func (w *webhooker) Select() *notifiers.Notification {
return w.Notification
}
@ -132,7 +132,7 @@ func (w *webhooker) sendHttpWebhook(body string) (*http.Response, error) {
}
func (w *webhooker) OnTest() error {
body := replaceBodyText(w.Var2, notifications.ExampleService, nil)
body := replaceBodyText(w.Var2, notifiers.ExampleService, nil)
resp, err := w.sendHttpWebhook(body)
if err != nil {
return err

View File

@ -13,7 +13,7 @@
// 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 notifications
package notifiers
import (
"encoding/json"
@ -173,7 +173,7 @@ func SelectNotifier(method string) (*Notification, Notifier, error) {
// Queue is the FIFO go routine to send notifications when objects are triggered
func Queue(notifer Notifier) {
n := notifer.Select()
n := notifer.(*Notification)
rateLimit := n.Delay
CheckNotifier:
@ -182,6 +182,8 @@ CheckNotifier:
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 {

View File

@ -5,6 +5,7 @@ import (
"github.com/jinzhu/gorm"
"github.com/pkg/errors"
"github.com/statping/statping/database"
"github.com/statping/statping/notifiers"
"github.com/statping/statping/types/checkins"
"github.com/statping/statping/types/core"
"github.com/statping/statping/types/failures"
@ -12,7 +13,6 @@ import (
"github.com/statping/statping/types/hits"
"github.com/statping/statping/types/incidents"
"github.com/statping/statping/types/messages"
"github.com/statping/statping/types/notifications"
"github.com/statping/statping/types/null"
"github.com/statping/statping/types/services"
"github.com/statping/statping/types/users"
@ -100,7 +100,7 @@ func initModels(db database.Database) {
hits.SetDB(db)
failures.SetDB(db)
checkins.SetDB(db)
notifications.SetDB(db)
notifiers.SetDB(db)
incidents.SetDB(db)
users.SetDB(db)
messages.SetDB(db)

View File

@ -2,6 +2,7 @@ package configs
import (
"github.com/statping/statping/database"
"github.com/statping/statping/notifiers"
"github.com/statping/statping/types/checkins"
"github.com/statping/statping/types/core"
"github.com/statping/statping/types/failures"
@ -9,7 +10,6 @@ import (
"github.com/statping/statping/types/hits"
"github.com/statping/statping/types/incidents"
"github.com/statping/statping/types/messages"
"github.com/statping/statping/types/notifications"
"github.com/statping/statping/types/services"
"github.com/statping/statping/types/users"
"github.com/statping/statping/utils"
@ -73,7 +73,7 @@ func (d *DbConfig) Delete() error {
// DropDatabase will DROP each table Statping created
func (d *DbConfig) DropDatabase() error {
var DbModels = []interface{}{&services.Service{}, &users.User{}, &hits.Hit{}, &failures.Failure{}, &messages.Message{}, &groups.Group{}, &checkins.Checkin{}, &checkins.CheckinHit{}, &notifications.Notification{}, &incidents.Incident{}, &incidents.IncidentUpdate{}}
var DbModels = []interface{}{&services.Service{}, &users.User{}, &hits.Hit{}, &failures.Failure{}, &messages.Message{}, &groups.Group{}, &checkins.Checkin{}, &checkins.CheckinHit{}, &notifiers.Notification{}, &incidents.Incident{}, &incidents.IncidentUpdate{}}
log.Infoln("Dropping Database Tables...")
for _, t := range DbModels {
if err := d.Db.DropTableIfExists(t); err != nil {
@ -92,7 +92,7 @@ func (d *DbConfig) Close() {
func (d *DbConfig) CreateDatabase() error {
var err error
var DbModels = []interface{}{&services.Service{}, &users.User{}, &hits.Hit{}, &failures.Failure{}, &messages.Message{}, &groups.Group{}, &checkins.Checkin{}, &checkins.CheckinHit{}, &notifications.Notification{}, &incidents.Incident{}, &incidents.IncidentUpdate{}}
var DbModels = []interface{}{&services.Service{}, &users.User{}, &hits.Hit{}, &failures.Failure{}, &messages.Message{}, &groups.Group{}, &checkins.Checkin{}, &checkins.CheckinHit{}, &notifiers.Notification{}, &incidents.Incident{}, &incidents.IncidentUpdate{}}
log.Infoln("Creating Database Tables...")
for _, table := range DbModels {

View File

@ -5,6 +5,7 @@ import (
_ "github.com/jinzhu/gorm/dialects/mysql"
_ "github.com/jinzhu/gorm/dialects/postgres"
_ "github.com/jinzhu/gorm/dialects/sqlite"
"github.com/statping/statping/notifiers"
"github.com/statping/statping/types/checkins"
"github.com/statping/statping/types/core"
"github.com/statping/statping/types/failures"
@ -12,7 +13,6 @@ import (
"github.com/statping/statping/types/hits"
"github.com/statping/statping/types/incidents"
"github.com/statping/statping/types/messages"
"github.com/statping/statping/types/notifications"
"github.com/statping/statping/types/services"
"github.com/statping/statping/types/users"
)
@ -52,7 +52,7 @@ func (c *DbConfig) DatabaseChanges() error {
//If this function has an issue, it will ROLLBACK to the previous state.
func (c *DbConfig) MigrateDatabase() error {
var DbModels = []interface{}{&services.Service{}, &users.User{}, &hits.Hit{}, &failures.Failure{}, &messages.Message{}, &groups.Group{}, &checkins.Checkin{}, &checkins.CheckinHit{}, &notifications.Notification{}, &incidents.Incident{}, &incidents.IncidentUpdate{}}
var DbModels = []interface{}{&services.Service{}, &users.User{}, &hits.Hit{}, &failures.Failure{}, &messages.Message{}, &groups.Group{}, &checkins.Checkin{}, &checkins.CheckinHit{}, &notifiers.Notification{}, &incidents.Incident{}, &incidents.IncidentUpdate{}}
log.Infoln("Migrating Database Tables...")
tx := c.Db.Begin()

View File

@ -118,6 +118,5 @@ func (s *Service) DeleteCheckins() error {
//}
func (s *Service) AfterFind() error {
s.UpdateStats()
return nil
}

View File

@ -38,7 +38,7 @@ func humanMicro(val int64) string {
if val < 10000 {
return fmt.Sprintf("%d μs", val)
}
return fmt.Sprintf("%0.0f ms", float64(val)*0.001)
return fmt.Sprintf("%d ms", float64(val)*0.001)
}
// IsRunning returns true if the service go routine is running

View File

@ -3,6 +3,7 @@ package services
import (
"bytes"
"fmt"
"github.com/statping/statping/notifiers"
"github.com/statping/statping/types/failures"
"github.com/statping/statping/types/hits"
"github.com/statping/statping/utils"
@ -39,6 +40,7 @@ CheckLoop:
break CheckLoop
case <-time.After(s.SleepDuration):
s.CheckService(record)
s.UpdateStats()
s.Checkpoint = s.Checkpoint.Add(s.Duration())
sleep := s.Checkpoint.Sub(time.Now())
if !s.Online {
@ -238,26 +240,26 @@ func recordSuccess(s *Service) {
log.Error(err)
}
log.WithFields(utils.ToFields(hit, s)).Infoln(
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: %v | Online: %v | Interval: %d seconds", s.Id, s.Name, humanMicro(hit.Latency), humanMicro(hit.PingTime), s.Online, s.Interval))
s.LastLookupTime = hit.PingTime
s.LastLatency = hit.Latency
//notifier.OnSuccess(s)
notifiers.OnSuccess(s)
s.SuccessNotified = true
}
// recordFailure will create a new 'Failure' record in the database for a offline service
func recordFailure(s *Service, issue string) {
s.LastOffline = time.Now().UTC()
s.LastOffline = utils.Now()
fail := &failures.Failure{
Service: s.Id,
Issue: issue,
PingTime: s.PingTime,
CreatedAt: time.Now().UTC(),
CreatedAt: utils.Now(),
ErrorCode: s.LastStatusCode,
}
log.WithFields(utils.ToFields(fail, s)).
Warnln(fmt.Sprintf("Service %v Failing: %v | Lookup in: %0.2f ms", s.Name, issue, fail.PingTime*1000))
Warnln(fmt.Sprintf("Service %v Failing: %v | Lookup in: %v", s.Name, issue, humanMicro(fail.PingTime)))
if err := fail.Create(); err != nil {
log.Error(err)
@ -265,7 +267,7 @@ func recordFailure(s *Service, issue string) {
s.Online = false
s.SuccessNotified = false
s.DownText = s.DowntimeText()
//notifier.OnFailure(s, fail)
notifiers.OnFailure(s, fail)
}
// Check will run checkHttp for HTTP services and checkTcp for TCP services