From 825906145fb350aaf83f87423a1b41f055255125 Mon Sep 17 00:00:00 2001 From: TwinProduction Date: Sun, 8 Sep 2019 21:07:08 -0400 Subject: [PATCH] Implement interval + Add timestamp to Result struct --- README.md | 22 ++++++++++++++++------ config.yaml | 2 +- config/config.go | 3 ++- config/config_test.go | 23 ++++++++++++++--------- core/types.go | 16 +++++++++------- watchdog/watchdog.go | 27 ++++++++++++++++++--------- 6 files changed, 60 insertions(+), 33 deletions(-) diff --git a/README.md b/README.md index 51ff7bd3..ca945b1b 100644 --- a/README.md +++ b/README.md @@ -3,15 +3,25 @@ A service health dashboard in Go -config should look something like +## Usage ```yaml services: - - name: twinnation + - name: twinnation # Name of your service, can be anything url: https://twinnation.org/actuator/health - interval: 10 - failure-threshold: 3 + interval: 15s # Duration to wait between every status check (opt. default: 10s) + failure-threshold: 3 conditions: - "$STATUS == 200" - - "IP == 200" -``` \ No newline at end of file + - name: github + url: https://api.github.com/healthz + conditions: + - "$STATUS == 200" +``` + + +## Running the tests + +``` +go test ./... -mod vendor +``` diff --git a/config.yaml b/config.yaml index 15b1f86b..a6d7b30a 100644 --- a/config.yaml +++ b/config.yaml @@ -1,7 +1,7 @@ services: - name: twinnation url: https://twinnation.org/actuator/health - interval: 15 + interval: 15s failure-threshold: 3 conditions: - "$STATUS == 200" diff --git a/config/config.go b/config/config.go index f248ae86..b2756787 100644 --- a/config/config.go +++ b/config/config.go @@ -4,6 +4,7 @@ import ( "github.com/TwinProduction/gatus/core" "gopkg.in/yaml.v2" "io/ioutil" + "time" ) type Config struct { @@ -37,7 +38,7 @@ func ParseConfigBytes(yamlBytes []byte) *Config { service.FailureThreshold = 1 } if service.Interval == 0 { - service.Interval = 10 + service.Interval = 10 * time.Second } } return config diff --git a/config/config_test.go b/config/config_test.go index e923c2dd..556f2861 100644 --- a/config/config_test.go +++ b/config/config_test.go @@ -1,18 +1,22 @@ package config -import "testing" +import ( + "fmt" + "testing" + "time" +) func TestParseConfigBytes(t *testing.T) { config := ParseConfigBytes([]byte(` services: - name: twinnation url: https://twinnation.org/actuator/health - interval: 15 + interval: 15s failure-threshold: 3 conditions: - "$STATUS == 200" - name: github - url: https://github.com + url: https://api.github.com/healthz conditions: - "$STATUS != 400" - "$STATUS != 500" @@ -23,14 +27,15 @@ services: if config.Services[0].Url != "https://twinnation.org/actuator/health" { t.Errorf("URL should have been %s", "https://twinnation.org/actuator/health") } - if config.Services[1].Url != "https://github.com" { - t.Errorf("URL should have been %s", "https://github.com") + if config.Services[1].Url != "https://api.github.com/healthz" { + t.Errorf("URL should have been %s", "https://api.github.com/healthz") } - if config.Services[0].Interval != 15 { - t.Errorf("Interval should have been %d", 15) + fmt.Println(config.Services[0].Interval) + if config.Services[0].Interval != 15*time.Second { + t.Errorf("Interval should have been %s", 15*time.Second) } - if config.Services[1].Interval != 10 { - t.Errorf("Interval should have been %d, because it is the default value", 10) + if config.Services[1].Interval != 10*time.Second { + t.Errorf("Interval should have been %s, because it is the default value", 10*time.Second) } if config.Services[0].FailureThreshold != 3 { t.Errorf("FailureThreshold should have been %d", 3) diff --git a/core/types.go b/core/types.go index 2d65e542..dd25fa5a 100644 --- a/core/types.go +++ b/core/types.go @@ -24,17 +24,18 @@ type Result struct { HttpStatus int `json:"status"` Hostname string `json:"hostname"` Ip string `json:"ip"` - Duration string `json:"duration"` + Duration time.Duration `json:"duration"` Errors []error `json:"errors"` ConditionResult []*ConditionResult `json:"condition-results"` + Timestamp time.Time `json:"timestamp"` } type Service struct { - Name string `yaml:"name"` - Url string `yaml:"url"` - Interval int `yaml:"interval,omitempty"` // TODO: Implement - FailureThreshold int `yaml:"failure-threshold,omitempty"` // TODO: Implement - Conditions []*Condition `yaml:"conditions"` + Name string `yaml:"name"` + Url string `yaml:"url"` + Interval time.Duration `yaml:"interval,omitempty"` + FailureThreshold int `yaml:"failure-threshold,omitempty"` // TODO: Implement + Conditions []*Condition `yaml:"conditions"` } func (service *Service) getIp(result *Result) { @@ -62,7 +63,7 @@ func (service *Service) getStatus(result *Result) { result.Errors = append(result.Errors, err) return } - result.Duration = time.Now().Sub(startTime).String() + result.Duration = time.Now().Sub(startTime) result.HttpStatus = response.StatusCode } @@ -73,6 +74,7 @@ func (service *Service) EvaluateConditions() *Result { for _, condition := range service.Conditions { condition.Evaluate(result) } + result.Timestamp = time.Now() return result } diff --git a/watchdog/watchdog.go b/watchdog/watchdog.go index 1d493619..498be3db 100644 --- a/watchdog/watchdog.go +++ b/watchdog/watchdog.go @@ -3,6 +3,7 @@ package watchdog import ( "github.com/TwinProduction/gatus/config" "github.com/TwinProduction/gatus/core" + "log" "sync" "time" ) @@ -17,18 +18,26 @@ func GetServiceResults() *map[string][]*core.Result { } func Monitor() { - for { - for _, service := range config.Get().Services { - go func(service *core.Service) { + for _, service := range config.Get().Services { + go func(service *core.Service) { + for { + log.Printf("[watchdog][Monitor] Waiting interval=%s before monitoring serviceName=%s", service.Interval, service.Name) + time.Sleep(service.Interval) + log.Printf("[watchdog][Monitor] Monitoring serviceName=%s", service.Name) result := service.EvaluateConditions() rwLock.Lock() - defer rwLock.Unlock() serviceResults[service.Name] = append(serviceResults[service.Name], result) - if len(serviceResults[service.Name]) > 15 { - serviceResults[service.Name] = serviceResults[service.Name][15:] + if len(serviceResults[service.Name]) > 10 { + serviceResults[service.Name] = serviceResults[service.Name][1:] } - }(service) - } - time.Sleep(10 * time.Second) + rwLock.Unlock() + log.Printf( + "[watchdog][Monitor] Finished monitoring serviceName=%s; errors=%d; requestDuration=%s", + service.Name, + len(result.Errors), + result.Duration.Round(time.Millisecond), + ) + } + }(service) } }