diff --git a/core/condition.go b/core/condition.go index 7d2c3bb6..4bc33af3 100644 --- a/core/condition.go +++ b/core/condition.go @@ -126,7 +126,7 @@ func (c Condition) evaluate(result *Result) bool { conditionToDisplay = prettifyNumericalParameters(parameters, resolvedParameters, "<") } } else { - result.Errors = append(result.Errors, fmt.Sprintf("invalid condition '%s' has been provided", condition)) + result.AddError(fmt.Sprintf("invalid condition '%s' has been provided", condition)) return false } if !success { @@ -242,7 +242,7 @@ func sanitizeAndResolve(elements []string, result *Result) ([]string, []string) } else { if err != nil { if err.Error() != "unexpected end of JSON input" { - result.Errors = append(result.Errors, err.Error()) + result.AddError(err.Error()) } if checkingForLength { element = LengthFunctionPrefix + element + FunctionSuffix + " " + InvalidConditionElementSuffix diff --git a/core/condition_bench_test.go b/core/condition_bench_test.go index dbc1e582..f0aec040 100644 --- a/core/condition_bench_test.go +++ b/core/condition_bench_test.go @@ -38,6 +38,15 @@ func BenchmarkCondition_evaluateWithBodyStringFailure(b *testing.B) { b.ReportAllocs() } +func BenchmarkCondition_evaluateWithBodyStringFailureInvalidPath(b *testing.B) { + condition := Condition("[BODY].user.name == bob.doe") + for n := 0; n < b.N; n++ { + result := &Result{body: []byte("{\"name\": \"bob.doe\"}")} + condition.evaluate(result) + } + b.ReportAllocs() +} + func BenchmarkCondition_evaluateWithBodyStringLen(b *testing.B) { condition := Condition("len([BODY].name) == 8") for n := 0; n < b.N; n++ { diff --git a/core/result.go b/core/result.go index ea08b899..4be760ea 100644 --- a/core/result.go +++ b/core/result.go @@ -25,7 +25,7 @@ type Result struct { Duration time.Duration `json:"duration"` // Errors encountered during the evaluation of the service's health - Errors []string `json:"errors"` + Errors []string `json:"errors"` // XXX: find a way to filter out duplicate errors // ConditionResults results of the service's conditions ConditionResults []*ConditionResult `json:"conditionResults"` @@ -46,3 +46,15 @@ type Result struct { // and sets it to nil after the evaluation has been completed. body []byte } + +// AddError adds an error to the result's list of errors. +// It also ensures that there are no duplicates. +func (r *Result) AddError(error string) { + for _, resultError := range r.Errors { + if resultError == error { + // If the error already exists, don't add it + return + } + } + r.Errors = append(r.Errors, error) +} diff --git a/core/result_test.go b/core/result_test.go new file mode 100644 index 00000000..899ec7f9 --- /dev/null +++ b/core/result_test.go @@ -0,0 +1,21 @@ +package core + +import ( + "testing" +) + +func TestResult_AddError(t *testing.T) { + result := &Result{} + result.AddError("potato") + if len(result.Errors) != 1 { + t.Error("should've had 1 error") + } + result.AddError("potato") + if len(result.Errors) != 1 { + t.Error("should've still had 1 error, because a duplicate error was added") + } + result.AddError("tomato") + if len(result.Errors) != 2 { + t.Error("should've had 2 error") + } +} diff --git a/core/service.go b/core/service.go index 5e7fda20..5545dc9d 100644 --- a/core/service.go +++ b/core/service.go @@ -162,14 +162,14 @@ func (service *Service) getIP(result *Result) { } else { urlObject, err := url.Parse(service.URL) if err != nil { - result.Errors = append(result.Errors, err.Error()) + result.AddError(err.Error()) return } result.Hostname = urlObject.Hostname() } ips, err := net.LookupIP(result.Hostname) if err != nil { - result.Errors = append(result.Errors, err.Error()) + result.AddError(err.Error()) return } result.IP = ips[0].String() @@ -193,7 +193,7 @@ func (service *Service) call(result *Result) { service.DNS.query(service.URL, result) result.Duration = time.Since(startTime) } else if isServiceStartTLS { - result.Connected, certificate, err = client.CanPerformStartTls(strings.TrimPrefix(service.URL, "starttls://"), service.Insecure) + result.Connected, certificate, err = client.CanPerformStartTLS(strings.TrimPrefix(service.URL, "starttls://"), service.Insecure) if err != nil { result.Errors = append(result.Errors, err.Error()) return @@ -209,7 +209,7 @@ func (service *Service) call(result *Result) { response, err = client.GetHTTPClient(service.Insecure).Do(request) result.Duration = time.Since(startTime) if err != nil { - result.Errors = append(result.Errors, err.Error()) + result.AddError(err.Error()) return } defer response.Body.Close() @@ -223,7 +223,7 @@ func (service *Service) call(result *Result) { if service.needsToReadBody() { result.body, err = ioutil.ReadAll(response.Body) if err != nil { - result.Errors = append(result.Errors, err.Error()) + result.AddError(err.Error()) } } }