mirror of https://github.com/statping/statping
code cleanup, debug mode (pprof), new env vars: DISABLE_HTTP, LOGS_MAX_COUNT, LOGS_MAX_AGE, LOGS_MAX_SIZE, DISABLE_COLORS, fixed DISABLE_LOGS bool env, mobile notifier update to fit the next mobile app update,
parent
29bda29874
commit
c06eba3bc8
|
@ -59,6 +59,7 @@ func Router() *mux.Router {
|
|||
r.HandleFunc("/debug/pprof/symbol", pprof.Symbol)
|
||||
r.HandleFunc("/debug/pprof/trace", pprof.Trace)
|
||||
http.ListenAndServe(":9090", r)
|
||||
// pprof -http=:9000 http://localhost:9090/debug/pprof/heap?debug=1
|
||||
}()
|
||||
}
|
||||
|
||||
|
|
|
@ -14,8 +14,6 @@ import (
|
|||
|
||||
var _ notifier.Notifier = (*mobilePush)(nil)
|
||||
|
||||
const mobileIdentifier = "com.statping"
|
||||
|
||||
type mobilePush struct {
|
||||
*notifications.Notification
|
||||
}
|
||||
|
@ -78,7 +76,6 @@ func (m *mobilePush) OnFailure(s *services.Service, f *failures.Failure) error {
|
|||
msg := &pushArray{
|
||||
Message: fmt.Sprintf("Your service '%v' is currently failing! Reason: %v", s.Name, f.Issue),
|
||||
Title: "Service Offline",
|
||||
Topic: mobileIdentifier,
|
||||
Data: data,
|
||||
}
|
||||
return m.Send(msg)
|
||||
|
@ -88,10 +85,10 @@ func (m *mobilePush) OnFailure(s *services.Service, f *failures.Failure) error {
|
|||
func (m *mobilePush) OnSuccess(s *services.Service) error {
|
||||
data := dataJson(s, nil)
|
||||
msg := &pushArray{
|
||||
Message: "Service is Online!",
|
||||
Title: "Service Online",
|
||||
Topic: mobileIdentifier,
|
||||
Data: data,
|
||||
Message: "Service is Online!",
|
||||
Title: "Service Online",
|
||||
Data: data,
|
||||
Platform: 2,
|
||||
}
|
||||
return m.Send(msg)
|
||||
}
|
||||
|
@ -101,9 +98,8 @@ func (m *mobilePush) OnTest() (string, error) {
|
|||
msg := &pushArray{
|
||||
Message: "Testing the Mobile Notifier",
|
||||
Title: "Testing Notifications",
|
||||
Topic: mobileIdentifier,
|
||||
Tokens: []string{m.Var1},
|
||||
Platform: utils.ToInt(m.Var2),
|
||||
Platform: 2,
|
||||
}
|
||||
body, err := pushRequest(msg)
|
||||
if err != nil {
|
||||
|
@ -134,9 +130,6 @@ func (m *mobilePush) Send(pushMessage *pushArray) error {
|
|||
}
|
||||
|
||||
func pushRequest(msg *pushArray) ([]byte, error) {
|
||||
if msg.Platform == 1 {
|
||||
msg.Title = ""
|
||||
}
|
||||
body, err := json.Marshal(&PushNotification{[]*pushArray{msg}})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
|
|
@ -7,14 +7,12 @@ import (
|
|||
"github.com/statping/statping/utils"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
"os"
|
||||
"testing"
|
||||
"time"
|
||||
)
|
||||
|
||||
var (
|
||||
MOBILE_ID string
|
||||
MOBILE_NUMBER string
|
||||
mobileToken string
|
||||
)
|
||||
|
||||
func TestMobileNotifier(t *testing.T) {
|
||||
|
@ -22,25 +20,22 @@ func TestMobileNotifier(t *testing.T) {
|
|||
err := utils.InitLogs()
|
||||
require.Nil(t, err)
|
||||
|
||||
MOBILE_ID = utils.Params.GetString("MOBILE_ID")
|
||||
MOBILE_NUMBER = utils.Params.GetString("MOBILE_NUMBER")
|
||||
Mobile.Var1 = MOBILE_ID
|
||||
mobileToken = utils.Params.GetString("MOBILE_TOKEN")
|
||||
Mobile.Var1 = mobileToken
|
||||
|
||||
db, err := database.OpenTester()
|
||||
require.Nil(t, err)
|
||||
db.AutoMigrate(¬ifications.Notification{})
|
||||
notifications.SetDB(db)
|
||||
|
||||
Mobile.Var1 = MOBILE_ID
|
||||
Mobile.Var2 = os.Getenv("MOBILE_NUMBER")
|
||||
if MOBILE_ID == "" {
|
||||
Mobile.Var1 = mobileToken
|
||||
if mobileToken == "" {
|
||||
t.Log("Mobile notifier testing skipped, missing MOBILE_ID environment variable")
|
||||
t.SkipNow()
|
||||
}
|
||||
|
||||
t.Run("Load Mobile", func(t *testing.T) {
|
||||
Mobile.Var1 = MOBILE_ID
|
||||
Mobile.Var2 = MOBILE_NUMBER
|
||||
Mobile.Var1 = mobileToken
|
||||
Mobile.Delay = time.Duration(100 * time.Millisecond)
|
||||
Mobile.Limits = 10
|
||||
Mobile.Enabled = null.NewNullBool(true)
|
||||
|
@ -48,8 +43,7 @@ func TestMobileNotifier(t *testing.T) {
|
|||
Add(Mobile)
|
||||
|
||||
assert.Equal(t, "Hunter Long", Mobile.Author)
|
||||
assert.Equal(t, MOBILE_ID, Mobile.Var1)
|
||||
assert.Equal(t, MOBILE_NUMBER, Mobile.Var2)
|
||||
assert.Equal(t, mobileToken, Mobile.Var1)
|
||||
})
|
||||
|
||||
t.Run("Mobile Notifier Tester", func(t *testing.T) {
|
||||
|
@ -67,7 +61,6 @@ func TestMobileNotifier(t *testing.T) {
|
|||
})
|
||||
|
||||
t.Run("Mobile Test", func(t *testing.T) {
|
||||
t.SkipNow()
|
||||
_, err := Mobile.OnTest()
|
||||
assert.Nil(t, err)
|
||||
})
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
package notifiers
|
||||
|
||||
import (
|
||||
"encoding/base64"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
|
@ -70,7 +71,7 @@ func (t *twilio) sendMessage(message string) (string, error) {
|
|||
v.Set("Body", message)
|
||||
rb := strings.NewReader(v.Encode())
|
||||
|
||||
authHeader := utils.Base64(fmt.Sprintf("%s:%s", t.ApiKey, t.ApiSecret))
|
||||
authHeader := base64.StdEncoding.EncodeToString([]byte(fmt.Sprintf("%s:%s", t.ApiKey, t.ApiSecret)))
|
||||
|
||||
contents, _, err := utils.HttpRequest(twilioUrl, "POST", "application/x-www-form-urlencoded", []string{"Authorization=Basic " + authHeader}, rb, 10*time.Second, true, nil)
|
||||
success, _ := twilioSuccess(contents)
|
||||
|
|
|
@ -2,7 +2,6 @@ package checkins
|
|||
|
||||
import (
|
||||
"github.com/statping/statping/database"
|
||||
"github.com/statping/statping/utils"
|
||||
)
|
||||
|
||||
var db database.Database
|
||||
|
@ -32,13 +31,7 @@ func All() []*Checkin {
|
|||
}
|
||||
|
||||
func (c *Checkin) Create() error {
|
||||
if c.ApiKey == "" {
|
||||
c.ApiKey = utils.RandomString(32)
|
||||
}
|
||||
q := db.Create(c)
|
||||
|
||||
c.Start()
|
||||
go c.CheckinRoutine()
|
||||
return q.Error()
|
||||
}
|
||||
|
||||
|
@ -48,11 +41,6 @@ func (c *Checkin) Update() error {
|
|||
}
|
||||
|
||||
func (c *Checkin) Delete() error {
|
||||
c.Close()
|
||||
q := dbHits.Where("checkin = ?", c.Id).Delete(&CheckinHit{})
|
||||
if err := q.Error(); err != nil {
|
||||
return err
|
||||
}
|
||||
q = db.Model(&Checkin{}).Delete(c)
|
||||
q := db.Delete(c)
|
||||
return q.Error()
|
||||
}
|
||||
|
|
|
@ -0,0 +1,25 @@
|
|||
package checkins
|
||||
|
||||
import "github.com/statping/statping/utils"
|
||||
|
||||
func (c *Checkin) BeforeCreate() error {
|
||||
if c.ApiKey == "" {
|
||||
c.ApiKey = utils.RandomString(32)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c *Checkin) AfterCreate() error {
|
||||
c.Start()
|
||||
go c.CheckinRoutine()
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c *Checkin) BeforeDelete() error {
|
||||
c.Close()
|
||||
q := dbHits.Where("checkin = ?", c.Id).Delete(&CheckinHit{})
|
||||
if err := q.Error(); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
|
@ -2,7 +2,6 @@ package checkins
|
|||
|
||||
import (
|
||||
"github.com/statping/statping/types/failures"
|
||||
"github.com/statping/statping/utils"
|
||||
"time"
|
||||
)
|
||||
|
||||
|
@ -30,10 +29,3 @@ type CheckinHit struct {
|
|||
From string `gorm:"column:from_location" json:"from"`
|
||||
CreatedAt time.Time `gorm:"column:created_at" json:"created_at"`
|
||||
}
|
||||
|
||||
func (c *Checkin) BeforeCreate() (err error) {
|
||||
if c.ApiKey == "" {
|
||||
c.ApiKey = utils.RandomString(7)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
|
|
@ -23,8 +23,6 @@ import (
|
|||
// Connect will attempt to connect to the sqlite, postgres, or mysql database
|
||||
func Connect(configs *DbConfig, retry bool) error {
|
||||
conn := configs.ConnectionString()
|
||||
p := utils.Params
|
||||
var err error
|
||||
|
||||
log.WithFields(utils.ToFields(configs, conn)).Debugln("attempting to connect to database")
|
||||
|
||||
|
@ -40,20 +38,16 @@ func Connect(configs *DbConfig, retry bool) error {
|
|||
}
|
||||
}
|
||||
|
||||
apiSecret := p.GetString("API_SECRET")
|
||||
configs.ApiSecret = apiSecret
|
||||
configs.ApiSecret = utils.Params.GetString("API_SECRET")
|
||||
|
||||
log.WithFields(utils.ToFields(dbSession)).Debugln("connected to database")
|
||||
|
||||
maxOpenConn := p.GetInt("MAX_OPEN_CONN")
|
||||
maxIdleConn := p.GetInt("MAX_IDLE_CONN")
|
||||
maxLifeConn := p.GetDuration("MAX_LIFE_CONN")
|
||||
db := dbSession.DB()
|
||||
db.SetMaxOpenConns(utils.Params.GetInt("MAX_OPEN_CONN"))
|
||||
db.SetMaxIdleConns(utils.Params.GetInt("MAX_IDLE_CONN"))
|
||||
db.SetConnMaxLifetime(utils.Params.GetDuration("MAX_LIFE_CONN"))
|
||||
|
||||
dbSession.DB().SetMaxOpenConns(maxOpenConn)
|
||||
dbSession.DB().SetMaxIdleConns(maxIdleConn)
|
||||
dbSession.DB().SetConnMaxLifetime(maxLifeConn)
|
||||
|
||||
if dbSession.DB().Ping() == nil {
|
||||
if db.Ping() == nil {
|
||||
if utils.VerboseMode >= 4 {
|
||||
dbSession.LogMode(true).Debug().SetLogger(gorm.Logger{log})
|
||||
}
|
||||
|
|
|
@ -66,11 +66,6 @@ func (d *DbConfig) Update() error {
|
|||
return nil
|
||||
}
|
||||
|
||||
// Save will initially create the config.yml file
|
||||
func (d *DbConfig) Delete() error {
|
||||
return os.Remove(d.filename)
|
||||
}
|
||||
|
||||
// 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{}, ¬ifications.Notification{}, &incidents.Incident{}, &incidents.IncidentUpdate{}}
|
||||
|
|
|
@ -70,7 +70,6 @@ func (d *DbConfig) BackupAssets() error {
|
|||
//This function will NOT remove previous records, tables or columns from the database.
|
||||
//If this function has an issue, it will ROLLBACK to the previous state.
|
||||
func (d *DbConfig) MigrateDatabase() error {
|
||||
|
||||
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...")
|
||||
|
|
|
@ -1,11 +0,0 @@
|
|||
package configs
|
||||
|
||||
//func preparePostgresDB(t *testing.T) (database.Database, error) {
|
||||
// dbName := fmt.Sprintf("db_%d", time.Now().UnixNano())
|
||||
// db, err := database.Openw("sqlite3", dbName)
|
||||
// if err != nil {
|
||||
// t.Fatalf("open connection: %s", err)
|
||||
// }
|
||||
//
|
||||
// return db, db.Error()
|
||||
//}
|
|
@ -22,14 +22,18 @@ func Samples() error {
|
|||
Issue: "Server failure",
|
||||
CreatedAt: utils.Now().Add(-time.Duration(3*i) * 86400),
|
||||
}
|
||||
f1.Create()
|
||||
if err := f1.Create(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
f2 := &Failure{
|
||||
Service: i,
|
||||
Issue: "Server failure",
|
||||
CreatedAt: utils.Now().Add(-time.Duration(5*i) * 12400),
|
||||
}
|
||||
f2.Create()
|
||||
if err := f2.Create(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
log.Infoln(fmt.Sprintf("Adding %v Failure records to service", 400))
|
||||
|
||||
|
|
|
@ -0,0 +1,14 @@
|
|||
package messages
|
||||
|
||||
import (
|
||||
"github.com/statping/statping/utils"
|
||||
)
|
||||
|
||||
// BeforeCreate for Message will set CreatedAt to UTC
|
||||
func (m *Message) BeforeCreate() (err error) {
|
||||
if m.CreatedAt.IsZero() {
|
||||
m.CreatedAt = utils.Now()
|
||||
m.UpdatedAt = utils.Now()
|
||||
}
|
||||
return
|
||||
}
|
|
@ -20,12 +20,3 @@ type Message struct {
|
|||
CreatedAt time.Time `gorm:"column:created_at" json:"created_at" json:"created_at"`
|
||||
UpdatedAt time.Time `gorm:"column:updated_at" json:"updated_at" json:"updated_at"`
|
||||
}
|
||||
|
||||
// BeforeCreate for Message will set CreatedAt to UTC
|
||||
func (m *Message) BeforeCreate() (err error) {
|
||||
if m.CreatedAt.IsZero() {
|
||||
m.CreatedAt = time.Now().UTC()
|
||||
m.UpdatedAt = time.Now().UTC()
|
||||
}
|
||||
return
|
||||
}
|
||||
|
|
|
@ -0,0 +1,10 @@
|
|||
package notifications
|
||||
|
||||
import "github.com/statping/statping/utils"
|
||||
|
||||
// AfterFind for Notification will set the timezone
|
||||
func (n *Notification) AfterFind() (err error) {
|
||||
n.CreatedAt = utils.Now()
|
||||
n.UpdatedAt = utils.Now()
|
||||
return
|
||||
}
|
|
@ -13,25 +13,6 @@ func (n *Notification) Name() string {
|
|||
return newName
|
||||
}
|
||||
|
||||
// AfterFind for Notification will set the timezone
|
||||
func (n *Notification) AfterFind() (err error) {
|
||||
n.CreatedAt = utils.Now()
|
||||
n.UpdatedAt = utils.Now()
|
||||
return
|
||||
}
|
||||
|
||||
// AddQueue will add any type of interface (json, string, struct, etc) into the Notifiers queue
|
||||
//func (n *Notification) AddQueue(uid string, msg interface{}) {
|
||||
// data := &QueueData{uid, msg}
|
||||
// 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)))
|
||||
//}
|
||||
|
||||
// CanTest returns true if the notifier implements the OnTest interface
|
||||
//func (n *Notification) CanTest() bool {
|
||||
// return n.testable
|
||||
//}
|
||||
|
||||
// LastSent returns a time.Duration of the last sent notification for the notifier
|
||||
func (n *Notification) LastSent() time.Duration {
|
||||
since := time.Since(n.lastSent)
|
||||
|
@ -43,11 +24,6 @@ func (n *Notification) CanSend() bool {
|
|||
return false
|
||||
}
|
||||
|
||||
//fmt.Println("Last sent: ", n.lastSent.String())
|
||||
//fmt.Println("Last count: ", n.lastSentCount)
|
||||
//fmt.Println("Limits: ", n.Limits)
|
||||
//fmt.Println("Last sent before now: ", n.lastSent.Add(60*time.Second).Before(utils.Now()))
|
||||
|
||||
// the last sent notification was past 1 minute (limit per minute)
|
||||
if n.lastSent.Add(60 * time.Minute).Before(utils.Now()) {
|
||||
if n.lastSentCount != 0 {
|
||||
|
@ -86,7 +62,7 @@ func (n *Notification) GetValue(dbField string) string {
|
|||
case "api_secret":
|
||||
return n.ApiSecret
|
||||
case "limits":
|
||||
return utils.ToString(int(n.Limits))
|
||||
return utils.ToString(n.Limits)
|
||||
default:
|
||||
return ""
|
||||
}
|
||||
|
@ -116,34 +92,3 @@ func (n *Notification) IsRunning() bool {
|
|||
return true
|
||||
}
|
||||
}
|
||||
|
||||
// Init accepts the Notifier interface to initialize the notifier
|
||||
//func Init(n Notifier) (*Notification, error) {
|
||||
// if Exists(n.Select().Method) {
|
||||
// AllCommunications = append(AllCommunications, n)
|
||||
// } else {
|
||||
// _, err := insertDatabase(n)
|
||||
// if err != nil {
|
||||
// log.Errorln(err)
|
||||
// return nil, err
|
||||
// }
|
||||
// AllCommunications = append(AllCommunications, n)
|
||||
// }
|
||||
//
|
||||
// notify, err := SelectNotification(n)
|
||||
// if err != nil {
|
||||
// return nil, errors.Wrap(err, "error selecting notification")
|
||||
// }
|
||||
//
|
||||
// notify.CreatedAt = time.Now().UTC()
|
||||
// notify.UpdatedAt = time.Now().UTC()
|
||||
// if notify.Delay.Seconds() == 0 {
|
||||
// notify.Delay = 1 * time.Second
|
||||
// }
|
||||
// notify.testable = utils.IsType(n, new(Tester))
|
||||
// notify.Form = n.Select().Form
|
||||
//
|
||||
// AllCommunications = append(AllCommunications, n)
|
||||
//
|
||||
// return nil, err
|
||||
//}
|
||||
|
|
|
@ -9,10 +9,19 @@ import (
|
|||
)
|
||||
|
||||
var (
|
||||
db database.Database
|
||||
log = utils.Log.WithField("type", "service")
|
||||
db database.Database
|
||||
log = utils.Log.WithField("type", "service")
|
||||
allServices map[int64]*Service
|
||||
)
|
||||
|
||||
func init() {
|
||||
allServices = make(map[int64]*Service)
|
||||
}
|
||||
|
||||
func Services() map[int64]*Service {
|
||||
return allServices
|
||||
}
|
||||
|
||||
func SetDB(database database.Database) {
|
||||
db = database.Model(&Service{})
|
||||
}
|
||||
|
@ -54,30 +63,13 @@ func (s *Service) Create() error {
|
|||
return nil
|
||||
}
|
||||
|
||||
func (s *Service) AfterCreate() error {
|
||||
allServices[s.Id] = s
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *Service) Update() error {
|
||||
q := db.Update(s)
|
||||
allServices[s.Id] = s
|
||||
s.Close()
|
||||
s.SleepDuration = s.Duration()
|
||||
go ServiceCheckQueue(allServices[s.Id], true)
|
||||
return q.Error()
|
||||
}
|
||||
|
||||
func (s *Service) Delete() error {
|
||||
s.Close()
|
||||
if err := s.DeleteFailures(); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := s.DeleteHits(); err != nil {
|
||||
return err
|
||||
}
|
||||
delete(allServices, s.Id)
|
||||
q := db.Model(&Service{}).Delete(s)
|
||||
q := db.Delete(s)
|
||||
return q.Error()
|
||||
}
|
||||
|
||||
|
|
|
@ -17,8 +17,7 @@ func (s *Service) AllFailures() failures.Failurer {
|
|||
}
|
||||
|
||||
func (s *Service) FailuresSince(t time.Time) failures.Failurer {
|
||||
fails := failures.Since(t, s)
|
||||
return fails
|
||||
return failures.Since(t, s)
|
||||
}
|
||||
|
||||
func (s *Service) DowntimeAgo() string {
|
||||
|
|
|
@ -0,0 +1,37 @@
|
|||
package services
|
||||
|
||||
import "github.com/statping/statping/utils"
|
||||
|
||||
// BeforeCreate for Service will set CreatedAt to UTC
|
||||
func (s *Service) BeforeCreate() (err error) {
|
||||
if s.CreatedAt.IsZero() {
|
||||
s.CreatedAt = utils.Now()
|
||||
s.UpdatedAt = utils.Now()
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func (s *Service) AfterCreate() error {
|
||||
allServices[s.Id] = s
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *Service) AfterUpdate() error {
|
||||
allServices[s.Id] = s
|
||||
s.Close()
|
||||
s.SleepDuration = s.Duration()
|
||||
go ServiceCheckQueue(allServices[s.Id], true)
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *Service) BeforeDelete() error {
|
||||
s.Close()
|
||||
if err := s.DeleteFailures(); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := s.DeleteHits(); err != nil {
|
||||
return err
|
||||
}
|
||||
delete(allServices, s.Id)
|
||||
return nil
|
||||
}
|
|
@ -252,26 +252,18 @@ func SelectAllServices(start bool) (map[int64]*Service, error) {
|
|||
if len(allServices) > 0 {
|
||||
return allServices, nil
|
||||
}
|
||||
|
||||
for _, s := range all() {
|
||||
|
||||
if start {
|
||||
CheckinProcess(s)
|
||||
}
|
||||
|
||||
fails := s.AllFailures().LastAmount(limitedFailures)
|
||||
s.Failures = fails
|
||||
|
||||
s.Failures = s.AllFailures().LastAmount(limitedFailures)
|
||||
for _, c := range s.Checkins() {
|
||||
s.AllCheckins = append(s.AllCheckins, c)
|
||||
}
|
||||
|
||||
// collect initial service stats
|
||||
s.UpdateStats()
|
||||
|
||||
allServices[s.Id] = s
|
||||
}
|
||||
|
||||
return allServices, nil
|
||||
}
|
||||
|
||||
|
@ -281,15 +273,16 @@ func (s *Service) UpdateStats() *Service {
|
|||
s.AvgResponse = s.AvgTime()
|
||||
s.FailuresLast24Hours = s.FailuresSince(utils.Now().Add(-time.Hour * 24)).Count()
|
||||
|
||||
allFails := s.AllFailures()
|
||||
if s.LastOffline.IsZero() {
|
||||
lastFail := s.AllFailures().Last()
|
||||
lastFail := allFails.Last()
|
||||
if lastFail != nil {
|
||||
s.LastOffline = lastFail.CreatedAt
|
||||
}
|
||||
}
|
||||
|
||||
s.Stats = &Stats{
|
||||
Failures: s.AllFailures().Count(),
|
||||
Failures: allFails.Count(),
|
||||
Hits: s.AllHits().Count(),
|
||||
FirstHit: s.FirstHit().CreatedAt,
|
||||
}
|
||||
|
@ -309,11 +302,8 @@ func (s *Service) OnlineDaysPercent(days int) float32 {
|
|||
|
||||
// OnlineSince accepts a time since parameter to return the percent of a service's uptime.
|
||||
func (s *Service) OnlineSince(ago time.Time) float32 {
|
||||
failed := s.FailuresSince(ago)
|
||||
failsList := failed.Count()
|
||||
|
||||
total := s.HitsSince(ago)
|
||||
hitsList := total.Count()
|
||||
failsList := s.FailuresSince(ago).Count()
|
||||
hitsList := s.HitsSince(ago).Count()
|
||||
|
||||
if failsList == 0 {
|
||||
s.Online24Hours = 100.00
|
||||
|
@ -348,3 +338,11 @@ func (s *Service) Downtime() time.Duration {
|
|||
|
||||
return fail.CreatedAt.Sub(hit.CreatedAt)
|
||||
}
|
||||
|
||||
// ServiceOrder will reorder the services based on 'order_id' (Order)
|
||||
type ServiceOrder []Service
|
||||
|
||||
// Sort interface for resroting the Services in order
|
||||
func (c ServiceOrder) Len() int { return len(c) }
|
||||
func (c ServiceOrder) Swap(i, j int) { c[int64(i)], c[int64(j)] = c[int64(j)], c[int64(i)] }
|
||||
func (c ServiceOrder) Less(i, j int) bool { return c[i].Order < c[j].Order }
|
||||
|
|
|
@ -21,7 +21,6 @@ import (
|
|||
func CheckServices() {
|
||||
log.Infoln(fmt.Sprintf("Starting monitoring process for %v Services", len(allServices)))
|
||||
for _, s := range allServices {
|
||||
//go CheckinRoutine()
|
||||
time.Sleep(250 * time.Millisecond)
|
||||
go ServiceCheckQueue(s, true)
|
||||
}
|
||||
|
@ -43,14 +42,14 @@ CheckLoop:
|
|||
s.CheckService(record)
|
||||
s.UpdateStats()
|
||||
s.Checkpoint = s.Checkpoint.Add(s.Duration())
|
||||
sleep := s.Checkpoint.Sub(time.Now())
|
||||
if !s.Online {
|
||||
s.SleepDuration = s.Duration()
|
||||
} else {
|
||||
s.SleepDuration = sleep
|
||||
s.SleepDuration = s.Checkpoint.Sub(time.Now())
|
||||
}
|
||||
default:
|
||||
|
||||
}
|
||||
continue
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -79,9 +78,7 @@ func dnsCheck(s *Service) (int64, error) {
|
|||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
t2 := utils.Now()
|
||||
subTime := t2.Sub(t1).Microseconds()
|
||||
return subTime, err
|
||||
return utils.Now().Sub(t1).Microseconds(), err
|
||||
}
|
||||
|
||||
func isIPv6(address string) bool {
|
||||
|
@ -92,8 +89,7 @@ func isIPv6(address string) bool {
|
|||
func CheckIcmp(s *Service, record bool) (*Service, error) {
|
||||
defer s.updateLastCheck()
|
||||
|
||||
err := utils.Ping(s.Domain, s.Timeout)
|
||||
if err != nil {
|
||||
if err := utils.Ping(s.Domain, s.Timeout); err != nil {
|
||||
if record {
|
||||
recordFailure(s, fmt.Sprintf("Could not send ICMP to service %v, %v", s.Domain, err))
|
||||
}
|
||||
|
@ -140,8 +136,7 @@ func CheckGrpc(s *Service, record bool) (*Service, error) {
|
|||
}
|
||||
return s, err
|
||||
}
|
||||
t2 := utils.Now()
|
||||
s.Latency = t2.Sub(t1).Microseconds()
|
||||
s.Latency = utils.Now().Sub(t1).Microseconds()
|
||||
s.LastResponse = ""
|
||||
s.Online = true
|
||||
if record {
|
||||
|
@ -202,8 +197,7 @@ func CheckTcp(s *Service, record bool) (*Service, error) {
|
|||
defer conn.Close()
|
||||
}
|
||||
|
||||
t2 := utils.Now()
|
||||
s.Latency = t2.Sub(t1).Microseconds()
|
||||
s.Latency = utils.Now().Sub(t1).Microseconds()
|
||||
s.LastResponse = ""
|
||||
s.Online = true
|
||||
if record {
|
||||
|
@ -279,8 +273,7 @@ func CheckHttp(s *Service, record bool) (*Service, error) {
|
|||
}
|
||||
return s, err
|
||||
}
|
||||
t2 := utils.Now()
|
||||
s.Latency = t2.Sub(t1).Microseconds()
|
||||
s.Latency = utils.Now().Sub(t1).Microseconds()
|
||||
s.LastResponse = string(content)
|
||||
s.LastStatusCode = res.StatusCode
|
||||
|
||||
|
|
|
@ -4,22 +4,9 @@ import (
|
|||
"github.com/statping/statping/types/checkins"
|
||||
"github.com/statping/statping/types/failures"
|
||||
"github.com/statping/statping/types/null"
|
||||
"github.com/statping/statping/utils"
|
||||
"time"
|
||||
)
|
||||
|
||||
var (
|
||||
allServices map[int64]*Service
|
||||
)
|
||||
|
||||
func init() {
|
||||
allServices = make(map[int64]*Service)
|
||||
}
|
||||
|
||||
func Services() map[int64]*Service {
|
||||
return allServices
|
||||
}
|
||||
|
||||
// Service is the main struct for Services
|
||||
type Service struct {
|
||||
Id int64 `gorm:"primary_key;column:id" json:"id" yaml:"id"`
|
||||
|
@ -82,20 +69,3 @@ type Stats struct {
|
|||
Hits int `gorm:"-" json:"hits"`
|
||||
FirstHit time.Time `gorm:"-" json:"first_hit"`
|
||||
}
|
||||
|
||||
// BeforeCreate for Service will set CreatedAt to UTC
|
||||
func (s *Service) BeforeCreate() (err error) {
|
||||
if s.CreatedAt.IsZero() {
|
||||
s.CreatedAt = utils.Now()
|
||||
s.UpdatedAt = utils.Now()
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// ServiceOrder will reorder the services based on 'order_id' (Order)
|
||||
type ServiceOrder []Service
|
||||
|
||||
// Sort interface for resroting the Services in order
|
||||
func (c ServiceOrder) Len() int { return len(c) }
|
||||
func (c ServiceOrder) Swap(i, j int) { c[int64(i)], c[int64(j)] = c[int64(j)], c[int64(i)] }
|
||||
func (c ServiceOrder) Less(i, j int) bool { return c[i].Order < c[j].Order }
|
||||
|
|
|
@ -12,6 +12,10 @@ type yamlFile struct {
|
|||
|
||||
// LoadServicesYaml will attempt to load the 'services.yml' file for Service Auto Creation on startup.
|
||||
func LoadServicesYaml() (*yamlFile, error) {
|
||||
if !utils.FileExists(utils.Directory + "/services.yml") {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
f, err := utils.OpenFile(utils.Directory + "/services.yml")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
|
|
@ -2,7 +2,7 @@ package users
|
|||
|
||||
import (
|
||||
"fmt"
|
||||
"golang.org/x/crypto/bcrypt"
|
||||
"github.com/statping/statping/utils"
|
||||
"time"
|
||||
)
|
||||
|
||||
|
@ -14,16 +14,10 @@ func AuthUser(username, password string) (*User, bool) {
|
|||
log.Warnln(fmt.Errorf("user %v not found", username))
|
||||
return nil, false
|
||||
}
|
||||
if checkHash(password, user.Password) {
|
||||
if utils.CheckHash(password, user.Password) {
|
||||
user.UpdatedAt = time.Now().UTC()
|
||||
user.Update()
|
||||
return user, true
|
||||
}
|
||||
return nil, false
|
||||
}
|
||||
|
||||
// checkHash returns true if the password matches with a hashed bcrypt password
|
||||
func checkHash(password, hash string) bool {
|
||||
err := bcrypt.CompareHashAndPassword([]byte(hash), []byte(password))
|
||||
return err == nil
|
||||
}
|
||||
|
|
|
@ -52,10 +52,3 @@ func (u *User) Delete() error {
|
|||
}
|
||||
return q.Error()
|
||||
}
|
||||
|
||||
func (u *User) BeforeCreate() error {
|
||||
u.Password = utils.HashPassword(u.Password)
|
||||
u.ApiKey = utils.NewSHA256Hash()
|
||||
u.ApiSecret = utils.NewSHA256Hash()
|
||||
return nil
|
||||
}
|
||||
|
|
|
@ -0,0 +1,10 @@
|
|||
package users
|
||||
|
||||
import "github.com/statping/statping/utils"
|
||||
|
||||
func (u *User) BeforeCreate() error {
|
||||
u.Password = utils.HashPassword(u.Password)
|
||||
u.ApiKey = utils.NewSHA256Hash()
|
||||
u.ApiSecret = utils.NewSHA256Hash()
|
||||
return nil
|
||||
}
|
|
@ -2,7 +2,6 @@ package utils
|
|||
|
||||
import (
|
||||
"crypto/sha256"
|
||||
"encoding/base64"
|
||||
"fmt"
|
||||
"golang.org/x/crypto/bcrypt"
|
||||
"math/rand"
|
||||
|
@ -15,6 +14,12 @@ func HashPassword(password string) string {
|
|||
return string(bytes)
|
||||
}
|
||||
|
||||
// CheckHash returns true if the password matches with a hashed bcrypt password
|
||||
func CheckHash(password, hash string) bool {
|
||||
err := bcrypt.CompareHashAndPassword([]byte(hash), []byte(password))
|
||||
return err == nil
|
||||
}
|
||||
|
||||
// NewSHA1Hash returns a random SHA1 hash based on a specific length
|
||||
func NewSHA256Hash() string {
|
||||
d := make([]byte, 10)
|
||||
|
@ -23,10 +28,6 @@ func NewSHA256Hash() string {
|
|||
return fmt.Sprintf("%x", sha256.Sum256(d))
|
||||
}
|
||||
|
||||
func Base64(s string) string {
|
||||
return base64.StdEncoding.EncodeToString([]byte(s))
|
||||
}
|
||||
|
||||
var characterRunes = []rune("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789")
|
||||
|
||||
// RandomString generates a random string of n length
|
||||
|
|
|
@ -139,7 +139,7 @@ func replaceVal(d interface{}) interface{} {
|
|||
// createLog will create the '/logs' directory based on a directory
|
||||
func createLog(dir string) error {
|
||||
if !FolderExists(dir + "/logs") {
|
||||
CreateDirectory(dir + "/logs")
|
||||
return CreateDirectory(dir + "/logs")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
|
|
@ -5,14 +5,6 @@ import (
|
|||
"time"
|
||||
)
|
||||
|
||||
// Timezoner returns the time.Time with the user set timezone
|
||||
func Timezoner(t time.Time, zone float32) time.Time {
|
||||
zoneInt := float32(3600) * zone
|
||||
loc := time.FixedZone("", int(zoneInt))
|
||||
timez := t.In(loc)
|
||||
return timez
|
||||
}
|
||||
|
||||
// Now returns the UTC timestamp
|
||||
func Now() time.Time {
|
||||
return time.Now().UTC()
|
||||
|
|
|
@ -122,15 +122,6 @@ func ExampleStringInt() {
|
|||
// Output: 42
|
||||
}
|
||||
|
||||
func TestTimezone(t *testing.T) {
|
||||
zone := float32(-4.0)
|
||||
loc, _ := time.LoadLocation("America/Los_Angeles")
|
||||
timestamp := time.Date(2018, 1, 1, 10, 0, 0, 0, loc)
|
||||
timezone := Timezoner(timestamp, zone)
|
||||
assert.Equal(t, "2018-01-01 10:00:00 -0800 PST", timestamp.String())
|
||||
assert.Equal(t, "2018-01-01 18:00:00 +0000 UTC", timezone.UTC().String())
|
||||
}
|
||||
|
||||
func TestTimestamp_Ago(t *testing.T) {
|
||||
now := Timestamp(time.Now())
|
||||
assert.Equal(t, "Just now", now.Ago())
|
||||
|
|
Loading…
Reference in New Issue