mirror of
https://github.com/TwiN/gatus.git
synced 2024-12-01 04:14:20 +01:00
Implement interval + Add timestamp to Result struct
This commit is contained in:
parent
8a7aa96b97
commit
825906145f
18
README.md
18
README.md
@ -3,15 +3,25 @@
|
|||||||
A service health dashboard in Go
|
A service health dashboard in Go
|
||||||
|
|
||||||
|
|
||||||
config should look something like
|
## Usage
|
||||||
|
|
||||||
```yaml
|
```yaml
|
||||||
services:
|
services:
|
||||||
- name: twinnation
|
- name: twinnation # Name of your service, can be anything
|
||||||
url: https://twinnation.org/actuator/health
|
url: https://twinnation.org/actuator/health
|
||||||
interval: 10
|
interval: 15s # Duration to wait between every status check (opt. default: 10s)
|
||||||
failure-threshold: 3
|
failure-threshold: 3
|
||||||
conditions:
|
conditions:
|
||||||
- "$STATUS == 200"
|
- "$STATUS == 200"
|
||||||
- "IP == 200"
|
- name: github
|
||||||
|
url: https://api.github.com/healthz
|
||||||
|
conditions:
|
||||||
|
- "$STATUS == 200"
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
## Running the tests
|
||||||
|
|
||||||
|
```
|
||||||
|
go test ./... -mod vendor
|
||||||
```
|
```
|
@ -1,7 +1,7 @@
|
|||||||
services:
|
services:
|
||||||
- name: twinnation
|
- name: twinnation
|
||||||
url: https://twinnation.org/actuator/health
|
url: https://twinnation.org/actuator/health
|
||||||
interval: 15
|
interval: 15s
|
||||||
failure-threshold: 3
|
failure-threshold: 3
|
||||||
conditions:
|
conditions:
|
||||||
- "$STATUS == 200"
|
- "$STATUS == 200"
|
||||||
|
@ -4,6 +4,7 @@ import (
|
|||||||
"github.com/TwinProduction/gatus/core"
|
"github.com/TwinProduction/gatus/core"
|
||||||
"gopkg.in/yaml.v2"
|
"gopkg.in/yaml.v2"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
type Config struct {
|
type Config struct {
|
||||||
@ -37,7 +38,7 @@ func ParseConfigBytes(yamlBytes []byte) *Config {
|
|||||||
service.FailureThreshold = 1
|
service.FailureThreshold = 1
|
||||||
}
|
}
|
||||||
if service.Interval == 0 {
|
if service.Interval == 0 {
|
||||||
service.Interval = 10
|
service.Interval = 10 * time.Second
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return config
|
return config
|
||||||
|
@ -1,18 +1,22 @@
|
|||||||
package config
|
package config
|
||||||
|
|
||||||
import "testing"
|
import (
|
||||||
|
"fmt"
|
||||||
|
"testing"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
func TestParseConfigBytes(t *testing.T) {
|
func TestParseConfigBytes(t *testing.T) {
|
||||||
config := ParseConfigBytes([]byte(`
|
config := ParseConfigBytes([]byte(`
|
||||||
services:
|
services:
|
||||||
- name: twinnation
|
- name: twinnation
|
||||||
url: https://twinnation.org/actuator/health
|
url: https://twinnation.org/actuator/health
|
||||||
interval: 15
|
interval: 15s
|
||||||
failure-threshold: 3
|
failure-threshold: 3
|
||||||
conditions:
|
conditions:
|
||||||
- "$STATUS == 200"
|
- "$STATUS == 200"
|
||||||
- name: github
|
- name: github
|
||||||
url: https://github.com
|
url: https://api.github.com/healthz
|
||||||
conditions:
|
conditions:
|
||||||
- "$STATUS != 400"
|
- "$STATUS != 400"
|
||||||
- "$STATUS != 500"
|
- "$STATUS != 500"
|
||||||
@ -23,14 +27,15 @@ services:
|
|||||||
if config.Services[0].Url != "https://twinnation.org/actuator/health" {
|
if config.Services[0].Url != "https://twinnation.org/actuator/health" {
|
||||||
t.Errorf("URL should have been %s", "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" {
|
if config.Services[1].Url != "https://api.github.com/healthz" {
|
||||||
t.Errorf("URL should have been %s", "https://github.com")
|
t.Errorf("URL should have been %s", "https://api.github.com/healthz")
|
||||||
}
|
}
|
||||||
if config.Services[0].Interval != 15 {
|
fmt.Println(config.Services[0].Interval)
|
||||||
t.Errorf("Interval should have been %d", 15)
|
if config.Services[0].Interval != 15*time.Second {
|
||||||
|
t.Errorf("Interval should have been %s", 15*time.Second)
|
||||||
}
|
}
|
||||||
if config.Services[1].Interval != 10 {
|
if config.Services[1].Interval != 10*time.Second {
|
||||||
t.Errorf("Interval should have been %d, because it is the default value", 10)
|
t.Errorf("Interval should have been %s, because it is the default value", 10*time.Second)
|
||||||
}
|
}
|
||||||
if config.Services[0].FailureThreshold != 3 {
|
if config.Services[0].FailureThreshold != 3 {
|
||||||
t.Errorf("FailureThreshold should have been %d", 3)
|
t.Errorf("FailureThreshold should have been %d", 3)
|
||||||
|
@ -24,17 +24,18 @@ type Result struct {
|
|||||||
HttpStatus int `json:"status"`
|
HttpStatus int `json:"status"`
|
||||||
Hostname string `json:"hostname"`
|
Hostname string `json:"hostname"`
|
||||||
Ip string `json:"ip"`
|
Ip string `json:"ip"`
|
||||||
Duration string `json:"duration"`
|
Duration time.Duration `json:"duration"`
|
||||||
Errors []error `json:"errors"`
|
Errors []error `json:"errors"`
|
||||||
ConditionResult []*ConditionResult `json:"condition-results"`
|
ConditionResult []*ConditionResult `json:"condition-results"`
|
||||||
|
Timestamp time.Time `json:"timestamp"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type Service struct {
|
type Service struct {
|
||||||
Name string `yaml:"name"`
|
Name string `yaml:"name"`
|
||||||
Url string `yaml:"url"`
|
Url string `yaml:"url"`
|
||||||
Interval int `yaml:"interval,omitempty"` // TODO: Implement
|
Interval time.Duration `yaml:"interval,omitempty"`
|
||||||
FailureThreshold int `yaml:"failure-threshold,omitempty"` // TODO: Implement
|
FailureThreshold int `yaml:"failure-threshold,omitempty"` // TODO: Implement
|
||||||
Conditions []*Condition `yaml:"conditions"`
|
Conditions []*Condition `yaml:"conditions"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (service *Service) getIp(result *Result) {
|
func (service *Service) getIp(result *Result) {
|
||||||
@ -62,7 +63,7 @@ func (service *Service) getStatus(result *Result) {
|
|||||||
result.Errors = append(result.Errors, err)
|
result.Errors = append(result.Errors, err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
result.Duration = time.Now().Sub(startTime).String()
|
result.Duration = time.Now().Sub(startTime)
|
||||||
result.HttpStatus = response.StatusCode
|
result.HttpStatus = response.StatusCode
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -73,6 +74,7 @@ func (service *Service) EvaluateConditions() *Result {
|
|||||||
for _, condition := range service.Conditions {
|
for _, condition := range service.Conditions {
|
||||||
condition.Evaluate(result)
|
condition.Evaluate(result)
|
||||||
}
|
}
|
||||||
|
result.Timestamp = time.Now()
|
||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3,6 +3,7 @@ package watchdog
|
|||||||
import (
|
import (
|
||||||
"github.com/TwinProduction/gatus/config"
|
"github.com/TwinProduction/gatus/config"
|
||||||
"github.com/TwinProduction/gatus/core"
|
"github.com/TwinProduction/gatus/core"
|
||||||
|
"log"
|
||||||
"sync"
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
@ -17,18 +18,26 @@ func GetServiceResults() *map[string][]*core.Result {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func Monitor() {
|
func Monitor() {
|
||||||
for {
|
for _, service := range config.Get().Services {
|
||||||
for _, service := range config.Get().Services {
|
go func(service *core.Service) {
|
||||||
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()
|
result := service.EvaluateConditions()
|
||||||
rwLock.Lock()
|
rwLock.Lock()
|
||||||
defer rwLock.Unlock()
|
|
||||||
serviceResults[service.Name] = append(serviceResults[service.Name], result)
|
serviceResults[service.Name] = append(serviceResults[service.Name], result)
|
||||||
if len(serviceResults[service.Name]) > 15 {
|
if len(serviceResults[service.Name]) > 10 {
|
||||||
serviceResults[service.Name] = serviceResults[service.Name][15:]
|
serviceResults[service.Name] = serviceResults[service.Name][1:]
|
||||||
}
|
}
|
||||||
}(service)
|
rwLock.Unlock()
|
||||||
}
|
log.Printf(
|
||||||
time.Sleep(10 * time.Second)
|
"[watchdog][Monitor] Finished monitoring serviceName=%s; errors=%d; requestDuration=%s",
|
||||||
|
service.Name,
|
||||||
|
len(result.Errors),
|
||||||
|
result.Duration.Round(time.Millisecond),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}(service)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user