Performance improvements

This commit is contained in:
TwinProduction 2021-01-14 22:49:48 -05:00
parent 5860a27ab5
commit 271c3dc91d
2 changed files with 37 additions and 19 deletions

View File

@ -2,7 +2,6 @@ package core
import ( import (
"fmt" "fmt"
"log"
"strconv" "strconv"
"strings" "strings"
"time" "time"
@ -73,8 +72,8 @@ const (
type Condition string type Condition string
// evaluate the Condition with the Result of the health check // evaluate the Condition with the Result of the health check
func (c *Condition) evaluate(result *Result) bool { func (c Condition) evaluate(result *Result) bool {
condition := string(*c) condition := string(c)
success := false success := false
conditionToDisplay := condition conditionToDisplay := condition
if strings.Contains(condition, "==") { if strings.Contains(condition, "==") {
@ -117,10 +116,8 @@ func (c *Condition) evaluate(result *Result) bool {
result.Errors = append(result.Errors, fmt.Sprintf("invalid condition '%s' has been provided", condition)) result.Errors = append(result.Errors, fmt.Sprintf("invalid condition '%s' has been provided", condition))
return false return false
} }
// If the condition isn't a success, return what the resolved condition was too
// XXX: make this configurable? i.e. show-resolved-conditions-on-failure
if !success { if !success {
log.Printf("[Condition][evaluate] Condition '%s' did not succeed because '%s' is false", condition, condition) //log.Printf("[Condition][evaluate] Condition '%s' did not succeed because '%s' is false", condition, condition)
} }
result.ConditionResults = append(result.ConditionResults, &ConditionResult{Condition: conditionToDisplay, Success: success}) result.ConditionResults = append(result.ConditionResults, &ConditionResult{Condition: conditionToDisplay, Success: success})
return success return success
@ -181,11 +178,13 @@ func isEqual(first, second string) bool {
// sanitizeAndResolve sanitizes and resolves a list of elements and returns the list of parameters as well as a list // sanitizeAndResolve sanitizes and resolves a list of elements and returns the list of parameters as well as a list
// of resolved parameters // of resolved parameters
func sanitizeAndResolve(elements []string, result *Result) (parameters, resolvedParameters []string) { func sanitizeAndResolve(elements []string, result *Result) ([]string, []string) {
parameters := make([]string, len(elements))
resolvedParameters := make([]string, len(elements))
body := strings.TrimSpace(string(result.Body)) body := strings.TrimSpace(string(result.Body))
for _, element := range elements { for i, element := range elements {
element = strings.TrimSpace(element) element = strings.TrimSpace(element)
parameters = append(parameters, element) parameters[i] = element
switch strings.ToUpper(element) { switch strings.ToUpper(element) {
case StatusPlaceholder: case StatusPlaceholder:
element = strconv.Itoa(result.HTTPStatus) element = strconv.Itoa(result.HTTPStatus)
@ -209,26 +208,26 @@ func sanitizeAndResolve(elements []string, result *Result) (parameters, resolved
wantLength = true wantLength = true
element = strings.TrimSuffix(strings.TrimPrefix(element, LengthFunctionPrefix), FunctionSuffix) element = strings.TrimSuffix(strings.TrimPrefix(element, LengthFunctionPrefix), FunctionSuffix)
} }
resolvedElement, resolvedElementLength, err := jsonpath.Eval(strings.Replace(element, fmt.Sprintf("%s.", BodyPlaceholder), "", 1), result.Body) resolvedElement, resolvedElementLength, err := jsonpath.Eval(strings.TrimPrefix(element, BodyPlaceholder+"."), result.Body)
if err != nil { if err != nil {
if err.Error() != "unexpected end of JSON input" { if err.Error() != "unexpected end of JSON input" {
result.Errors = append(result.Errors, err.Error()) result.Errors = append(result.Errors, err.Error())
} }
if wantLength { if wantLength {
element = fmt.Sprintf("%s%s%s %s", LengthFunctionPrefix, element, FunctionSuffix, InvalidConditionElementSuffix) element = LengthFunctionPrefix + element + FunctionSuffix + " " + InvalidConditionElementSuffix
} else { } else {
element = fmt.Sprintf("%s %s", element, InvalidConditionElementSuffix) element = element + " " + InvalidConditionElementSuffix
} }
} else { } else {
if wantLength { if wantLength {
element = fmt.Sprintf("%d", resolvedElementLength) element = strconv.Itoa(resolvedElementLength)
} else { } else {
element = resolvedElement element = resolvedElement
} }
} }
} }
} }
resolvedParameters = append(resolvedParameters, element) resolvedParameters[i] = element
} }
return parameters, resolvedParameters return parameters, resolvedParameters
} }
@ -252,24 +251,25 @@ func prettifyNumericalParameters(parameters []string, resolvedParameters []int64
return prettify(parameters, []string{strconv.Itoa(int(resolvedParameters[0])), strconv.Itoa(int(resolvedParameters[1]))}, operator) return prettify(parameters, []string{strconv.Itoa(int(resolvedParameters[0])), strconv.Itoa(int(resolvedParameters[1]))}, operator)
} }
// XXX: make this configurable? i.e. show-resolved-conditions-on-failure
func prettify(parameters []string, resolvedParameters []string, operator string) string { func prettify(parameters []string, resolvedParameters []string, operator string) string {
// Since, in the event of an invalid path, the resolvedParameters also contain the condition itself, // Since, in the event of an invalid path, the resolvedParameters also contain the condition itself,
// we'll return the resolvedParameters as-is. // we'll return the resolvedParameters as-is.
if strings.HasSuffix(resolvedParameters[0], InvalidConditionElementSuffix) || strings.HasSuffix(resolvedParameters[1], InvalidConditionElementSuffix) { if strings.HasSuffix(resolvedParameters[0], InvalidConditionElementSuffix) || strings.HasSuffix(resolvedParameters[1], InvalidConditionElementSuffix) {
return fmt.Sprintf("%v %s %v", resolvedParameters[0], operator, resolvedParameters[1]) return resolvedParameters[0] + " " + operator + " " + resolvedParameters[1]
} }
// First element is a placeholder // First element is a placeholder
if parameters[0] != resolvedParameters[0] && parameters[1] == resolvedParameters[1] { if parameters[0] != resolvedParameters[0] && parameters[1] == resolvedParameters[1] {
return fmt.Sprintf("%v (%v) %s %v", parameters[0], resolvedParameters[0], operator, resolvedParameters[1]) return parameters[0] + " (" + resolvedParameters[0] + ") " + operator + " " + parameters[1]
} }
// Second element is a placeholder // Second element is a placeholder
if parameters[0] == resolvedParameters[0] && parameters[1] != resolvedParameters[1] { if parameters[0] == resolvedParameters[0] && parameters[1] != resolvedParameters[1] {
return fmt.Sprintf("%v %s %v (%v)", resolvedParameters[0], operator, parameters[1], resolvedParameters[1]) return parameters[0] + " " + operator + " " + parameters[1] + " (" + resolvedParameters[1] + ")"
} }
// Both elements are placeholders...? // Both elements are placeholders...?
if parameters[0] != resolvedParameters[0] && parameters[1] != resolvedParameters[1] { if parameters[0] != resolvedParameters[0] && parameters[1] != resolvedParameters[1] {
return fmt.Sprintf("%v (%v) %s %v (%v)", parameters[0], resolvedParameters[0], operator, parameters[1], resolvedParameters[1]) return parameters[0] + " (" + resolvedParameters[0] + ") " + operator + " " + parameters[1] + " (" + resolvedParameters[1] + ")"
} }
// Neither elements are placeholders // Neither elements are placeholders
return fmt.Sprintf("%v %s %v", parameters[0], operator, parameters[1]) return parameters[0] + " " + operator + " " + parameters[1]
} }

View File

@ -38,6 +38,24 @@ func BenchmarkCondition_evaluateWithBodyStringFailure(b *testing.B) {
b.ReportAllocs() b.ReportAllocs()
} }
func BenchmarkCondition_evaluateWithBodyStringLen(b *testing.B) {
condition := Condition("len([BODY].name) == 8")
for n := 0; n < b.N; n++ {
result := &Result{Body: []byte("{\"name\": \"john.doe\"}")}
condition.evaluate(result)
}
b.ReportAllocs()
}
func BenchmarkCondition_evaluateWithBodyStringLenFailure(b *testing.B) {
condition := Condition("len([BODY].name) == 8")
for n := 0; n < b.N; n++ {
result := &Result{Body: []byte("{\"name\": \"bob.doe\"}")}
condition.evaluate(result)
}
b.ReportAllocs()
}
func BenchmarkCondition_evaluateWithStatus(b *testing.B) { func BenchmarkCondition_evaluateWithStatus(b *testing.B) {
condition := Condition("[STATUS] == 200") condition := Condition("[STATUS] == 200")
for n := 0; n < b.N; n++ { for n := 0; n < b.N; n++ {