+
-
@@ -378,7 +388,7 @@ export default {
this.loading = false
},
async fetchUptime() {
- const uptime = await Api.service_uptime(this.id, this.params.start, this.params.end)
+ const uptime = await Api.service_uptime(this.service.id, this.params.start, this.params.end)
this.uptime_data = this.parse_uptime(uptime)
},
parse_uptime(timedata) {
diff --git a/handlers/cache.go b/handlers/cache.go
index 82de3e60..bc0e7b97 100644
--- a/handlers/cache.go
+++ b/handlers/cache.go
@@ -2,6 +2,7 @@ package handlers
import (
"github.com/statping/statping/utils"
+ "net/url"
"sync"
"time"
)
@@ -106,6 +107,13 @@ func (s Storage) Delete(key string) {
func (s Storage) Set(key string, content []byte, duration time.Duration) {
s.mu.Lock()
defer s.mu.Unlock()
+ u, err := url.Parse(key)
+ if err != nil {
+ return
+ }
+ if u.Query().Get("v") != "" {
+ return
+ }
s.items[key] = Item{
Content: content,
Expiration: utils.Now().Add(duration).UnixNano(),
diff --git a/handlers/checkin.go b/handlers/checkin.go
index 9783308f..d30a386f 100644
--- a/handlers/checkin.go
+++ b/handlers/checkin.go
@@ -24,8 +24,7 @@ func findCheckin(r *http.Request) (*checkins.Checkin, string, error) {
}
func apiAllCheckinsHandler(w http.ResponseWriter, r *http.Request) {
- chks := checkins.All()
- returnJson(chks, w, r)
+ returnJson(checkins.All(), w, r)
}
func apiCheckinHandler(w http.ResponseWriter, r *http.Request) {
@@ -39,8 +38,7 @@ func apiCheckinHandler(w http.ResponseWriter, r *http.Request) {
func checkinCreateHandler(w http.ResponseWriter, r *http.Request) {
var checkin *checkins.Checkin
- err := DecodeJSON(r, &checkin)
- if err != nil {
+ if err := DecodeJSON(r, &checkin); err != nil {
sendErrorJson(err, w, r)
return
}
@@ -63,22 +61,27 @@ func checkinHitHandler(w http.ResponseWriter, r *http.Request) {
sendErrorJson(err, w, r)
return
}
+ log.Infof("Checking %s was requested", checkin.Name)
+
ip, _, _ := net.SplitHostPort(r.RemoteAddr)
+ if last := checkin.LastHit(); last == nil {
+ checkin.Start()
+ }
+
hit := &checkins.CheckinHit{
Checkin: checkin.Id,
From: ip,
CreatedAt: utils.Now(),
}
- log.Infof("Checking %s was requested", checkin.Name)
- err = hit.Create()
- if err != nil {
+ if err := hit.Create(); err != nil {
sendErrorJson(err, w, r)
return
}
checkin.Failing = false
checkin.LastHitTime = utils.Now()
+
sendJsonAction(hit.Id, "update", w, r)
}
diff --git a/handlers/checkins_test.go b/handlers/checkins_test.go
index feb86f19..8cc6df11 100644
--- a/handlers/checkins_test.go
+++ b/handlers/checkins_test.go
@@ -45,8 +45,7 @@ func TestApiCheckinRoutes(t *testing.T) {
Body: `{
"name": "Example Checkin",
"service_id": 1,
- "checkin_interval": 300,
- "grace_period": 60,
+ "interval": 300,
"api_key": "example"
}`,
},
diff --git a/handlers/handlers.go b/handlers/handlers.go
index 5964097c..2a2f22b0 100644
--- a/handlers/handlers.go
+++ b/handlers/handlers.go
@@ -56,7 +56,7 @@ func RunHTTPServer() error {
resetCookies()
httpError = make(chan error)
- if utils.Params.GetString("LETSENCRYPT_HOST") != "" {
+ if utils.Params.GetBool("LETSENCRYPT_ENABLE") {
go startLetsEncryptServer(ip)
} else if usingSSL {
go startSSLServer(ip)
diff --git a/handlers/server.go b/handlers/server.go
index 2277c73a..81197792 100644
--- a/handlers/server.go
+++ b/handlers/server.go
@@ -64,8 +64,6 @@ func letsEncryptCert() (*tls.Config, error) {
}
func startLetsEncryptServer(ip string) {
- log.Infoln("Starting SSL with LetsEncrypt")
-
log.Infoln("Starting LetEncrypt redirect server on port 80")
go http.ListenAndServe(":80", http.HandlerFunc(simplecert.Redirect))
diff --git a/types/checkins/checkins_test.go b/types/checkins/checkins_test.go
index a850c9bd..31ccdf6d 100644
--- a/types/checkins/checkins_test.go
+++ b/types/checkins/checkins_test.go
@@ -13,8 +13,7 @@ import (
var testCheckin = &Checkin{
ServiceId: 1,
Name: "Test Checkin",
- Interval: 60,
- GracePeriod: 10,
+ Interval: 3,
ApiKey: "tHiSiSaTeStXXX",
CreatedAt: utils.Now(),
UpdatedAt: utils.Now(),
diff --git a/types/checkins/database.go b/types/checkins/database.go
index 0fefd0bf..b7676f6c 100644
--- a/types/checkins/database.go
+++ b/types/checkins/database.go
@@ -15,6 +15,11 @@ func SetDB(database database.Database) {
}
func (c *Checkin) AfterFind() {
+ c.AllHits = c.Hits()
+ c.AllFailures = c.Failures().LastAmount(64)
+ if last := c.LastHit(); last != nil {
+ c.LastHitTime = last.CreatedAt
+ }
metrics.Query("checkin", "find")
}
@@ -41,9 +46,6 @@ func (c *Checkin) Create() error {
c.ApiKey = utils.RandomString(32)
}
q := db.Create(c)
-
- c.Start()
- go c.checkinRoutine()
return q.Error()
}
diff --git a/types/checkins/database_hits.go b/types/checkins/database_hits.go
index dbbb5713..bcea292c 100644
--- a/types/checkins/database_hits.go
+++ b/types/checkins/database_hits.go
@@ -2,13 +2,13 @@ package checkins
func (c *Checkin) LastHit() *CheckinHit {
var hit CheckinHit
- dbHits.Where("checkin = ?", c.Id).Limit(1).Find(&hit)
+ dbHits.Where("checkin = ?", c.Id).Last(&hit)
return &hit
}
func (c *Checkin) Hits() []*CheckinHit {
var hits []*CheckinHit
- dbHits.Where("checkin = ?", c.Id).Find(&hits)
+ dbHits.Where("checkin = ?", c.Id).Order("DESC").Find(&hits)
c.AllHits = hits
return hits
}
diff --git a/types/checkins/failures.go b/types/checkins/failures.go
index c2745abe..78d23970 100644
--- a/types/checkins/failures.go
+++ b/types/checkins/failures.go
@@ -7,6 +7,7 @@ import (
func (c *Checkin) CreateFailure(f *failures.Failure) error {
f.Checkin = c.Id
+ c.Failing = true
return failures.DB().Create(f).Error()
}
diff --git a/types/checkins/methods.go b/types/checkins/methods.go
index fde9867f..ec28f59e 100644
--- a/types/checkins/methods.go
+++ b/types/checkins/methods.go
@@ -10,22 +10,11 @@ func (c *Checkin) Expected() time.Duration {
last := c.LastHit()
now := utils.Now()
lastDir := now.Sub(last.CreatedAt)
- sub := time.Duration(c.Period() - lastDir)
- return sub
+ return c.Period() - lastDir
}
func (c *Checkin) Period() time.Duration {
- duration, _ := time.ParseDuration(fmt.Sprintf("%ds", c.Interval))
- if duration.Seconds() <= 15 {
- return 15 * time.Second
- }
- return duration
-}
-
-// Grace will return the duration of the Checkin Grace Period (after service hasn't responded, wait a bit for a response)
-func (c *Checkin) Grace() time.Duration {
- duration, _ := time.ParseDuration(fmt.Sprintf("%vs", c.GracePeriod))
- return duration
+ return time.Duration(c.Interval) * time.Minute
}
// Start will create a channel for the checkin checking go routine
diff --git a/types/checkins/routine.go b/types/checkins/routine.go
index e9f960df..d3cb422b 100644
--- a/types/checkins/routine.go
+++ b/types/checkins/routine.go
@@ -25,11 +25,8 @@ func (c *Checkin) RecheckCheckinFailure(guard chan struct{}) {
// checkinRoutine for checking if the last Checkin was within its interval
func (c *Checkin) checkinRoutine() {
- lastHit := c.LastHit()
- if lastHit == nil {
- return
- }
reCheck := c.Period()
+
CheckinLoop:
for {
select {
@@ -38,20 +35,25 @@ CheckinLoop:
c.Failing = false
break CheckinLoop
case <-time.After(reCheck):
- log.Infoln(fmt.Sprintf("Checkin '%s' expects a request every %v", c.Name, utils.FormatDuration(c.Period())))
- if c.Expected() <= 0 {
- issue := fmt.Sprintf("Checkin '%s' is failing, no request since %v", c.Name, lastHit.CreatedAt)
- //log.Errorln(issue)
+ lastHit := c.LastHit()
+ ago := utils.Now().Sub(lastHit.CreatedAt)
+
+ log.Infoln(fmt.Sprintf("Checkin '%s' expects a request every %s last request was %s ago", c.Name, c.Period(), utils.DurationReadable(ago)))
+
+ if ago.Seconds() > c.Period().Seconds() {
+ issue := fmt.Sprintf("Checkin expects a request every %d seconds", c.Interval)
+ log.Warnln(issue)
fail := &failures.Failure{
Issue: issue,
Method: "checkin",
Service: c.ServiceId,
- Checkin: c.Id,
- PingTime: c.Expected().Milliseconds(),
+ PingTime: ago.Milliseconds(),
}
- c.CreateFailure(fail)
+ if err := c.CreateFailure(fail); err != nil {
+ log.Errorln(err)
+ }
}
reCheck = c.Period()
}
diff --git a/types/checkins/samples.go b/types/checkins/samples.go
index f7b48f37..a239804e 100644
--- a/types/checkins/samples.go
+++ b/types/checkins/samples.go
@@ -8,22 +8,20 @@ import (
func Samples() error {
log.Infoln("Inserting Sample Checkins...")
checkin1 := &Checkin{
- Name: "Demo Checkin 1",
- ServiceId: 1,
- Interval: 300,
- GracePeriod: 300,
- ApiKey: "demoCheckin123",
+ Name: "Demo Checkin 1",
+ ServiceId: 1,
+ Interval: 3,
+ ApiKey: "demoCheckin123",
}
if err := checkin1.Create(); err != nil {
return err
}
checkin2 := &Checkin{
- Name: "Example Checkin 2",
- ServiceId: 2,
- Interval: 900,
- GracePeriod: 300,
- ApiKey: utils.RandomString(7),
+ Name: "Example Checkin 2",
+ ServiceId: 2,
+ Interval: 1,
+ ApiKey: utils.RandomString(7),
}
if err := checkin2.Create(); err != nil {
return err
diff --git a/types/checkins/struct.go b/types/checkins/struct.go
index 82f725c6..44292598 100644
--- a/types/checkins/struct.go
+++ b/types/checkins/struct.go
@@ -11,7 +11,6 @@ type Checkin struct {
ServiceId int64 `gorm:"index;column:service" json:"service_id"`
Name string `gorm:"column:name" json:"name"`
Interval int64 `gorm:"column:check_interval" json:"interval"`
- GracePeriod int64 `gorm:"column:grace_period" json:"grace"`
ApiKey string `gorm:"column:api_key" json:"api_key"`
CreatedAt time.Time `gorm:"column:created_at" json:"created_at"`
UpdatedAt time.Time `gorm:"column:updated_at" json:"updated_at"`
diff --git a/types/configs/load.go b/types/configs/load.go
index 26dd21d0..4de36ab2 100644
--- a/types/configs/load.go
+++ b/types/configs/load.go
@@ -57,29 +57,43 @@ func LoadConfigs(cfgFile string) (*DbConfig, error) {
p.Set("API_SECRET", db.ApiSecret)
}
if db.Language != "" {
- p.Set("LANGUAGE", "en")
+ p.Set("LANGUAGE", db.Language)
}
if db.SendReports {
p.Set("ALLOW_REPORTS", true)
}
+ if db.LetsEncryptEmail != "" {
+ p.Set("LETSENCRYPT_EMAIL", db.LetsEncryptEmail)
+ }
+ if db.LetsEncryptHost != "" {
+ p.Set("LETSENCRYPT_HOST", db.LetsEncryptHost)
+ }
+ if db.LetsEncryptEnable {
+ p.Set("LETSENCRYPT_ENABLE", db.LetsEncryptEnable)
+ }
configs := &DbConfig{
- DbConn: p.GetString("DB_CONN"),
- DbHost: p.GetString("DB_HOST"),
- DbUser: p.GetString("DB_USER"),
- DbPass: p.GetString("DB_PASS"),
- DbData: p.GetString("DB_DATABASE"),
- DbPort: p.GetInt("DB_PORT"),
- Project: p.GetString("NAME"),
- Description: p.GetString("DESCRIPTION"),
- Domain: p.GetString("DOMAIN"),
- Email: p.GetString("EMAIL"),
- Username: p.GetString("ADMIN_USER"),
- Password: p.GetString("ADMIN_PASSWORD"),
- Location: utils.Directory,
- SqlFile: p.GetString("SQL_FILE"),
- Language: p.GetString("LANGUAGE"),
- SendReports: p.GetBool("ALLOW_REPORTS"),
+ DbConn: p.GetString("DB_CONN"),
+ DbHost: p.GetString("DB_HOST"),
+ DbUser: p.GetString("DB_USER"),
+ DbPass: p.GetString("DB_PASS"),
+ DbData: p.GetString("DB_DATABASE"),
+ DbPort: p.GetInt("DB_PORT"),
+ Project: p.GetString("NAME"),
+ Description: p.GetString("DESCRIPTION"),
+ Domain: p.GetString("DOMAIN"),
+ Email: p.GetString("EMAIL"),
+ Username: p.GetString("ADMIN_USER"),
+ Password: p.GetString("ADMIN_PASSWORD"),
+ Location: utils.Directory,
+ SqlFile: p.GetString("SQL_FILE"),
+ Language: p.GetString("LANGUAGE"),
+ SendReports: p.GetBool("ALLOW_REPORTS"),
+ LetsEncryptEnable: p.GetBool("LETSENCRYPT_ENABLE"),
+ }
+ if configs.LetsEncryptEnable {
+ configs.LetsEncryptHost = p.GetString("LETSENCRYPT_HOST")
+ configs.LetsEncryptEmail = p.GetString("LETSENCRYPT_EMAIL")
}
log.WithFields(utils.ToFields(configs)).Debugln("read config file: " + cfgFile)
diff --git a/types/configs/struct.go b/types/configs/struct.go
index 998b17f5..2b10f317 100644
--- a/types/configs/struct.go
+++ b/types/configs/struct.go
@@ -6,26 +6,29 @@ const SqliteFilename = "statping.db"
// DbConfig struct is used for the Db connection and creates the 'config.yml' file
type DbConfig struct {
- DbConn string `yaml:"connection" json:"connection"`
- DbHost string `yaml:"host" json:"-"`
- DbUser string `yaml:"user" json:"-"`
- DbPass string `yaml:"password" json:"-"`
- DbData string `yaml:"database" json:"-"`
- DbPort int `yaml:"port" json:"-"`
- ApiSecret string `yaml:"api_secret" json:"-"`
- Language string `yaml:"language" json:"language"`
- SendReports bool `yaml:"send_reports" json:"send_reports"`
- Project string `yaml:"-" json:"-"`
- Description string `yaml:"-" json:"-"`
- Domain string `yaml:"-" json:"-"`
- Username string `yaml:"-" json:"-"`
- Password string `yaml:"-" json:"-"`
- Email string `yaml:"-" json:"-"`
- Error error `yaml:"-" json:"-"`
- Location string `yaml:"location" json:"-"`
- SqlFile string `yaml:"sqlfile,omitempty" json:"-"`
- LocalIP string `yaml:"-" json:"-"`
- filename string `yaml:"-" json:"-"`
+ DbConn string `yaml:"connection" json:"connection"`
+ DbHost string `yaml:"host" json:"-"`
+ DbUser string `yaml:"user" json:"-"`
+ DbPass string `yaml:"password" json:"-"`
+ DbData string `yaml:"database" json:"-"`
+ DbPort int `yaml:"port" json:"-"`
+ ApiSecret string `yaml:"api_secret" json:"-"`
+ Language string `yaml:"language" json:"language"`
+ SendReports bool `yaml:"send_reports" json:"send_reports"`
+ Project string `yaml:"-" json:"-"`
+ Description string `yaml:"-" json:"-"`
+ Domain string `yaml:"-" json:"-"`
+ Username string `yaml:"-" json:"-"`
+ Password string `yaml:"-" json:"-"`
+ Email string `yaml:"-" json:"-"`
+ Error error `yaml:"-" json:"-"`
+ Location string `yaml:"location" json:"-"`
+ SqlFile string `yaml:"sqlfile,omitempty" json:"-"`
+ LetsEncryptHost string `yaml:"letsencrypt_host,omitempty" json:"letsencrypt_host"`
+ LetsEncryptEmail string `yaml:"letsencrypt_email,omitempty" json:"letsencrypt_email"`
+ LetsEncryptEnable bool `yaml:"letsencrypt_enable" json:"letsencrypt_enable"`
+ LocalIP string `yaml:"-" json:"-"`
+ filename string `yaml:"-" json:"-"`
Db database.Database `yaml:"-" json:"-"`
}
diff --git a/types/failures/interface.go b/types/failures/interface.go
index 2954d118..44295f00 100644
--- a/types/failures/interface.go
+++ b/types/failures/interface.go
@@ -38,7 +38,7 @@ func (f Failurer) List() []*Failure {
func (f Failurer) LastAmount(amount int) []*Failure {
var fail []*Failure
- f.db.Order("id asc").Limit(amount).Find(&fail)
+ f.db.Order("id DESC").Limit(amount).Find(&fail)
return fail
}
diff --git a/types/services/checkins.go b/types/services/checkins.go
index 6d023726..00992ca0 100644
--- a/types/services/checkins.go
+++ b/types/services/checkins.go
@@ -7,7 +7,9 @@ import (
// CheckinProcess runs the checkin routine for each checkin attached to service
func CheckinProcess(s *Service) {
for _, c := range s.Checkins() {
- c.Start()
+ if last := c.LastHit(); last != nil {
+ c.Start()
+ }
}
}
diff --git a/types/services/methods.go b/types/services/methods.go
index 54ee3bff..10f2e5a5 100644
--- a/types/services/methods.go
+++ b/types/services/methods.go
@@ -253,10 +253,6 @@ func SelectAllServices(start bool) (map[int64]*Service, error) {
return allServices, nil
}
for _, s := range all() {
-
- if start {
- CheckinProcess(s)
- }
s.Failures = s.AllFailures().LastAmount(limitedFailures)
for _, c := range s.Checkins() {
s.AllCheckins = append(s.AllCheckins, c)
@@ -264,6 +260,9 @@ func SelectAllServices(start bool) (map[int64]*Service, error) {
// collect initial service stats
s.UpdateStats()
allServices[s.Id] = s
+ if start {
+ CheckinProcess(s)
+ }
}
return allServices, nil
}
diff --git a/types/services/services_test.go b/types/services/services_test.go
index fd5fcbe2..8cfa989d 100644
--- a/types/services/services_test.go
+++ b/types/services/services_test.go
@@ -61,11 +61,10 @@ var hit3 = &hits.Hit{
}
var exmapleCheckin = &checkins.Checkin{
- ServiceId: 1,
- Name: "Example Checkin",
- Interval: 60,
- GracePeriod: 30,
- ApiKey: "wdededede",
+ ServiceId: 1,
+ Name: "Example Checkin",
+ Interval: 3,
+ ApiKey: "wdededede",
}
var fail1 = &failures.Failure{
diff --git a/utils/env.go b/utils/env.go
index d618a49a..6b6f2dad 100644
--- a/utils/env.go
+++ b/utils/env.go
@@ -52,6 +52,7 @@ func InitEnvs() {
Params.SetDefault("LETSENCRYPT_HOST", "")
Params.SetDefault("LETSENCRYPT_EMAIL", "")
Params.SetDefault("LETSENCRYPT_LOCAL", false)
+ Params.SetDefault("LETSENCRYPT_ENABLE", false)
Params.SetDefault("LOGS_MAX_COUNT", 5)
Params.SetDefault("LOGS_MAX_AGE", 28)
Params.SetDefault("LOGS_MAX_SIZE", 16)
diff --git a/version.txt b/version.txt
index 1a914184..736ae4f7 100644
--- a/version.txt
+++ b/version.txt
@@ -1 +1 @@
-0.90.59
+0.90.60