Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix(condition): Partially support numbers with floating point #434

Merged
merged 2 commits into from
Feb 16, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
Gatus is a developer-oriented health dashboard that gives you the ability to monitor your services using HTTP, ICMP, TCP, and even DNS
queries as well as evaluate the result of said queries by using a list of conditions on values like the status code,
the response time, the certificate expiration, the body and many others. The icing on top is that each of these health
checks can be paired with alerting via Slack, PagerDuty, Pushover, Discord, Twilio and more.
checks can be paired with alerting via Slack, Teams, PagerDuty, Discord, Twilio and many more.

I personally deploy it in my Kubernetes cluster and let it monitor the status of my
core applications: https://status.twin.sh/
Expand Down
12 changes: 10 additions & 2 deletions core/condition.go
Original file line number Diff line number Diff line change
Expand Up @@ -302,10 +302,18 @@ func sanitizeAndResolveNumerical(list []string, result *Result) (parameters []st
parameters, resolvedParameters := sanitizeAndResolve(list, result)
for _, element := range resolvedParameters {
if duration, err := time.ParseDuration(element); duration != 0 && err == nil {
// If the string is a duration, convert it to milliseconds
resolvedNumericalParameters = append(resolvedNumericalParameters, duration.Milliseconds())
} else if number, err := strconv.ParseInt(element, 10, 64); err != nil {
// Default to 0 if the string couldn't be converted to an integer
resolvedNumericalParameters = append(resolvedNumericalParameters, 0)
// It's not an int, so we'll check if it's a float
if f, err := strconv.ParseFloat(element, 64); err == nil {
// It's a float, but we'll convert it to an int. We're losing precision here, but it's better than
// just returning 0.
resolvedNumericalParameters = append(resolvedNumericalParameters, int64(f))
} else {
// Default to 0 if the string couldn't be converted to an integer or a float
resolvedNumericalParameters = append(resolvedNumericalParameters, 0)
}
} else {
resolvedNumericalParameters = append(resolvedNumericalParameters, number)
}
Expand Down
7 changes: 7 additions & 0 deletions core/condition_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -294,6 +294,13 @@ func TestCondition_evaluate(t *testing.T) {
ExpectedSuccess: false,
ExpectedOutput: "[BODY].data.id (1) > 5",
},
{
Name: "body-jsonpath-float-using-greater-than-issue433", // As of v5.3.1, Gatus will convert a float to an int. We're losing precision, but it's better than just returning 0
Condition: Condition("[BODY].balance > 100"),
Result: &Result{body: []byte(`{"balance": "123.40000000000005"}`)},
ExpectedSuccess: true,
ExpectedOutput: "[BODY].balance > 100",
},
{
Name: "body-jsonpath-complex-int-using-less-than",
Condition: Condition("[BODY].data.id < 5"),
Expand Down
16 changes: 16 additions & 0 deletions jsonpath/jsonpath_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -158,6 +158,22 @@ func TestEval(t *testing.T) {
ExpectedOutputLength: 0,
ExpectedError: true,
},
{
Name: "float-as-string",
Path: "balance",
Data: `{"balance": "123.40000000000005"}`,
ExpectedOutput: "123.40000000000005",
ExpectedOutputLength: 18,
ExpectedError: false,
},
{
Name: "float-as-number",
Path: "balance",
Data: `{"balance": 123.40000000000005}`,
ExpectedOutput: "123.40000000000005",
ExpectedOutputLength: 18,
ExpectedError: false,
},
}
for _, scenario := range scenarios {
t.Run(scenario.Name, func(t *testing.T) {
Expand Down