Add support for [RESPONSE_TIME] and >, <, <=, >= operators
This commit is contained in:
@ -10,6 +10,12 @@ import (
|
||||
"time"
|
||||
)
|
||||
|
||||
const (
|
||||
StatusPlaceholder = "[STATUS]"
|
||||
IPPlaceHolder = "[IP]"
|
||||
ResponseTimePlaceHolder = "[RESPONSE_TIME]"
|
||||
)
|
||||
|
||||
type HealthStatus struct {
|
||||
Status string `json:"status"`
|
||||
Message string `json:"message,omitempty"`
|
||||
@ -95,44 +101,31 @@ type Condition string
|
||||
|
||||
func (c *Condition) evaluate(result *Result) bool {
|
||||
condition := string(*c)
|
||||
success := false
|
||||
if strings.Contains(condition, "==") {
|
||||
parts := sanitizeAndResolve(strings.Split(condition, "=="), result)
|
||||
if parts[0] == parts[1] {
|
||||
result.ConditionResults = append(result.ConditionResults, &ConditionResult{
|
||||
Condition: c,
|
||||
Success: true,
|
||||
Explanation: fmt.Sprintf("%s is equal to %s", parts[0], parts[1]),
|
||||
})
|
||||
return true
|
||||
} else {
|
||||
result.ConditionResults = append(result.ConditionResults, &ConditionResult{
|
||||
Condition: c,
|
||||
Success: false,
|
||||
Explanation: fmt.Sprintf("%s is not equal to %s", parts[0], parts[1]),
|
||||
})
|
||||
return false
|
||||
}
|
||||
success = parts[0] == parts[1]
|
||||
} else if strings.Contains(condition, "!=") {
|
||||
parts := sanitizeAndResolve(strings.Split(condition, "!="), result)
|
||||
if parts[0] != parts[1] {
|
||||
result.ConditionResults = append(result.ConditionResults, &ConditionResult{
|
||||
Condition: c,
|
||||
Success: true,
|
||||
Explanation: fmt.Sprintf("%s is not equal to %s", parts[0], parts[1]),
|
||||
})
|
||||
return true
|
||||
} else {
|
||||
result.ConditionResults = append(result.ConditionResults, &ConditionResult{
|
||||
Condition: c,
|
||||
Success: false,
|
||||
Explanation: fmt.Sprintf("%s is equal to %s", parts[0], parts[1]),
|
||||
})
|
||||
return false
|
||||
}
|
||||
success = parts[0] != parts[1]
|
||||
} else if strings.Contains(condition, "<=") {
|
||||
parts := sanitizeAndResolveNumerical(strings.Split(condition, "<="), result)
|
||||
success = parts[0] <= parts[1]
|
||||
} else if strings.Contains(condition, ">=") {
|
||||
parts := sanitizeAndResolveNumerical(strings.Split(condition, ">="), result)
|
||||
success = parts[0] >= parts[1]
|
||||
} else if strings.Contains(condition, ">") {
|
||||
parts := sanitizeAndResolveNumerical(strings.Split(condition, ">"), result)
|
||||
success = parts[0] > parts[1]
|
||||
} else if strings.Contains(condition, "<") {
|
||||
parts := sanitizeAndResolveNumerical(strings.Split(condition, "<"), result)
|
||||
success = parts[0] < parts[1]
|
||||
} else {
|
||||
result.Errors = append(result.Errors, fmt.Sprintf("invalid condition '%s' has been provided", condition))
|
||||
return false
|
||||
}
|
||||
result.ConditionResults = append(result.ConditionResults, &ConditionResult{Condition: c, Success: success})
|
||||
return success
|
||||
}
|
||||
|
||||
func sanitizeAndResolve(list []string, result *Result) []string {
|
||||
@ -140,13 +133,29 @@ func sanitizeAndResolve(list []string, result *Result) []string {
|
||||
for _, element := range list {
|
||||
element = strings.TrimSpace(element)
|
||||
switch strings.ToUpper(element) {
|
||||
case "[STATUS]":
|
||||
case StatusPlaceholder:
|
||||
element = strconv.Itoa(result.HttpStatus)
|
||||
case "[IP]":
|
||||
case IPPlaceHolder:
|
||||
element = result.Ip
|
||||
case ResponseTimePlaceHolder:
|
||||
element = strconv.Itoa(int(result.Duration.Milliseconds()))
|
||||
default:
|
||||
}
|
||||
sanitizedList = append(sanitizedList, element)
|
||||
}
|
||||
return sanitizedList
|
||||
}
|
||||
|
||||
func sanitizeAndResolveNumerical(list []string, result *Result) []int {
|
||||
var sanitizedNumbers []int
|
||||
sanitizedList := sanitizeAndResolve(list, result)
|
||||
for _, element := range sanitizedList {
|
||||
if number, err := strconv.Atoi(element); err != nil {
|
||||
// Default to 0 if the string couldn't be converted to an integer
|
||||
sanitizedNumbers = append(sanitizedNumbers, 0)
|
||||
} else {
|
||||
sanitizedNumbers = append(sanitizedNumbers, number)
|
||||
}
|
||||
}
|
||||
return sanitizedNumbers
|
||||
}
|
||||
|
@ -2,6 +2,7 @@ package core
|
||||
|
||||
import (
|
||||
"testing"
|
||||
"time"
|
||||
)
|
||||
|
||||
func TestEvaluateWithIp(t *testing.T) {
|
||||
@ -22,7 +23,7 @@ func TestEvaluateWithStatus(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestEvaluateWithFailure(t *testing.T) {
|
||||
func TestEvaluateWithStatusFailure(t *testing.T) {
|
||||
condition := Condition("[STATUS] == 200")
|
||||
result := &Result{HttpStatus: 500}
|
||||
condition.evaluate(result)
|
||||
@ -31,6 +32,60 @@ func TestEvaluateWithFailure(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestEvaluateWithStatusUsingLessThan(t *testing.T) {
|
||||
condition := Condition("[STATUS] < 300")
|
||||
result := &Result{HttpStatus: 201}
|
||||
condition.evaluate(result)
|
||||
if !result.ConditionResults[0].Success {
|
||||
t.Errorf("Condition '%s' should have been a success", condition)
|
||||
}
|
||||
}
|
||||
|
||||
func TestEvaluateWithStatusFailureUsingLessThan(t *testing.T) {
|
||||
condition := Condition("[STATUS] < 300")
|
||||
result := &Result{HttpStatus: 404}
|
||||
condition.evaluate(result)
|
||||
if result.ConditionResults[0].Success {
|
||||
t.Errorf("Condition '%s' should have been a failure", condition)
|
||||
}
|
||||
}
|
||||
|
||||
func TestEvaluateWithResponseTimeUsingLessThan(t *testing.T) {
|
||||
condition := Condition("[RESPONSE_TIME] < 500")
|
||||
result := &Result{Duration: time.Millisecond * 50}
|
||||
condition.evaluate(result)
|
||||
if !result.ConditionResults[0].Success {
|
||||
t.Errorf("Condition '%s' should have been a success", condition)
|
||||
}
|
||||
}
|
||||
|
||||
func TestEvaluateWithResponseTimeUsingGreaterThan(t *testing.T) {
|
||||
condition := Condition("[RESPONSE_TIME] > 500")
|
||||
result := &Result{Duration: time.Millisecond * 750}
|
||||
condition.evaluate(result)
|
||||
if !result.ConditionResults[0].Success {
|
||||
t.Errorf("Condition '%s' should have been a success", condition)
|
||||
}
|
||||
}
|
||||
|
||||
func TestEvaluateWithResponseTimeUsingGreaterThanOrEqualTo(t *testing.T) {
|
||||
condition := Condition("[RESPONSE_TIME] >= 500")
|
||||
result := &Result{Duration: time.Millisecond * 500}
|
||||
condition.evaluate(result)
|
||||
if !result.ConditionResults[0].Success {
|
||||
t.Errorf("Condition '%s' should have been a success", condition)
|
||||
}
|
||||
}
|
||||
|
||||
func TestEvaluateWithResponseTimeUsingLessThanOrEqualTo(t *testing.T) {
|
||||
condition := Condition("[RESPONSE_TIME] <= 500")
|
||||
result := &Result{Duration: time.Millisecond * 500}
|
||||
condition.evaluate(result)
|
||||
if !result.ConditionResults[0].Success {
|
||||
t.Errorf("Condition '%s' should have been a success", condition)
|
||||
}
|
||||
}
|
||||
|
||||
func TestIntegrationEvaluateConditions(t *testing.T) {
|
||||
condition := Condition("[STATUS] == 200")
|
||||
service := Service{
|
||||
|
Reference in New Issue
Block a user