mirror of
https://github.com/TwiN/gatus.git
synced 2026-02-04 12:56:48 +00:00
feat(conditions,ui): Add endpoints[].ui.resolve-successful-conditions (#1486)
feat(ui&endpoints): add bolean option for show resolve-successful-conditions
This commit is contained in:
committed by
GitHub
parent
1095deb3c6
commit
7bb959e072
@@ -303,6 +303,7 @@ You can then configure alerts to be triggered when an endpoint is unhealthy once
|
|||||||
| `endpoints[].ui.hide-url` | Whether to hide the URL from the results. Useful if the URL contains a token. | `false` |
|
| `endpoints[].ui.hide-url` | Whether to hide the URL from the results. Useful if the URL contains a token. | `false` |
|
||||||
| `endpoints[].ui.hide-errors` | Whether to hide errors from the results. | `false` |
|
| `endpoints[].ui.hide-errors` | Whether to hide errors from the results. | `false` |
|
||||||
| `endpoints[].ui.dont-resolve-failed-conditions` | Whether to resolve failed conditions for the UI. | `false` |
|
| `endpoints[].ui.dont-resolve-failed-conditions` | Whether to resolve failed conditions for the UI. | `false` |
|
||||||
|
| `endpoints[].ui.resolve-successful-conditions` | Whether to resolve successful conditions for the UI (helpful to expose body assertions even when checks pass). | `false` |
|
||||||
| `endpoints[].ui.badge.response-time` | List of response time thresholds. Each time a threshold is reached, the badge has a different color. | `[50, 200, 300, 500, 750]` |
|
| `endpoints[].ui.badge.response-time` | List of response time thresholds. Each time a threshold is reached, the badge has a different color. | `[50, 200, 300, 500, 750]` |
|
||||||
| `endpoints[].extra-labels` | Extra labels to add to the metrics. Useful for grouping endpoints together. | `{}` |
|
| `endpoints[].extra-labels` | Extra labels to add to the metrics. Useful for grouping endpoints together. | `{}` |
|
||||||
| `endpoints[].always-run` | (SUITES ONLY) Whether to execute this endpoint even if previous endpoints in the suite failed. | `false` |
|
| `endpoints[].always-run` | (SUITES ONLY) Whether to execute this endpoint even if previous endpoints in the suite failed. | `false` |
|
||||||
|
|||||||
@@ -26,7 +26,7 @@ type Condition string
|
|||||||
// Validate checks if the Condition is valid
|
// Validate checks if the Condition is valid
|
||||||
func (c Condition) Validate() error {
|
func (c Condition) Validate() error {
|
||||||
r := &Result{}
|
r := &Result{}
|
||||||
c.evaluate(r, false, nil)
|
c.evaluate(r, false, false, nil)
|
||||||
if len(r.Errors) != 0 {
|
if len(r.Errors) != 0 {
|
||||||
return errors.New(r.Errors[0])
|
return errors.New(r.Errors[0])
|
||||||
}
|
}
|
||||||
@@ -34,44 +34,50 @@ func (c Condition) Validate() error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// evaluate the Condition with the Result and an optional context
|
// evaluate the Condition with the Result and an optional context
|
||||||
func (c Condition) evaluate(result *Result, dontResolveFailedConditions bool, context *gontext.Gontext) bool {
|
func (c Condition) evaluate(result *Result, dontResolveFailedConditions bool, resolveSuccessfulConditions bool, context *gontext.Gontext) bool {
|
||||||
condition := string(c)
|
condition := string(c)
|
||||||
success := false
|
success := false
|
||||||
conditionToDisplay := condition
|
conditionToDisplay := condition
|
||||||
|
shouldResolveCondition := func(success bool) bool {
|
||||||
|
if success {
|
||||||
|
return resolveSuccessfulConditions
|
||||||
|
}
|
||||||
|
return !dontResolveFailedConditions
|
||||||
|
}
|
||||||
if strings.Contains(condition, " == ") {
|
if strings.Contains(condition, " == ") {
|
||||||
parameters, resolvedParameters := sanitizeAndResolveWithContext(strings.Split(condition, " == "), result, context)
|
parameters, resolvedParameters := sanitizeAndResolveWithContext(strings.Split(condition, " == "), result, context)
|
||||||
success = isEqual(resolvedParameters[0], resolvedParameters[1])
|
success = isEqual(resolvedParameters[0], resolvedParameters[1])
|
||||||
if !success && !dontResolveFailedConditions {
|
if shouldResolveCondition(success) {
|
||||||
conditionToDisplay = prettify(parameters, resolvedParameters, "==")
|
conditionToDisplay = prettify(parameters, resolvedParameters, "==")
|
||||||
}
|
}
|
||||||
} else if strings.Contains(condition, " != ") {
|
} else if strings.Contains(condition, " != ") {
|
||||||
parameters, resolvedParameters := sanitizeAndResolveWithContext(strings.Split(condition, " != "), result, context)
|
parameters, resolvedParameters := sanitizeAndResolveWithContext(strings.Split(condition, " != "), result, context)
|
||||||
success = !isEqual(resolvedParameters[0], resolvedParameters[1])
|
success = !isEqual(resolvedParameters[0], resolvedParameters[1])
|
||||||
if !success && !dontResolveFailedConditions {
|
if shouldResolveCondition(success) {
|
||||||
conditionToDisplay = prettify(parameters, resolvedParameters, "!=")
|
conditionToDisplay = prettify(parameters, resolvedParameters, "!=")
|
||||||
}
|
}
|
||||||
} else if strings.Contains(condition, " <= ") {
|
} else if strings.Contains(condition, " <= ") {
|
||||||
parameters, resolvedParameters := sanitizeAndResolveNumericalWithContext(strings.Split(condition, " <= "), result, context)
|
parameters, resolvedParameters := sanitizeAndResolveNumericalWithContext(strings.Split(condition, " <= "), result, context)
|
||||||
success = resolvedParameters[0] <= resolvedParameters[1]
|
success = resolvedParameters[0] <= resolvedParameters[1]
|
||||||
if !success && !dontResolveFailedConditions {
|
if shouldResolveCondition(success) {
|
||||||
conditionToDisplay = prettifyNumericalParameters(parameters, resolvedParameters, "<=")
|
conditionToDisplay = prettifyNumericalParameters(parameters, resolvedParameters, "<=")
|
||||||
}
|
}
|
||||||
} else if strings.Contains(condition, " >= ") {
|
} else if strings.Contains(condition, " >= ") {
|
||||||
parameters, resolvedParameters := sanitizeAndResolveNumericalWithContext(strings.Split(condition, " >= "), result, context)
|
parameters, resolvedParameters := sanitizeAndResolveNumericalWithContext(strings.Split(condition, " >= "), result, context)
|
||||||
success = resolvedParameters[0] >= resolvedParameters[1]
|
success = resolvedParameters[0] >= resolvedParameters[1]
|
||||||
if !success && !dontResolveFailedConditions {
|
if shouldResolveCondition(success) {
|
||||||
conditionToDisplay = prettifyNumericalParameters(parameters, resolvedParameters, ">=")
|
conditionToDisplay = prettifyNumericalParameters(parameters, resolvedParameters, ">=")
|
||||||
}
|
}
|
||||||
} else if strings.Contains(condition, " > ") {
|
} else if strings.Contains(condition, " > ") {
|
||||||
parameters, resolvedParameters := sanitizeAndResolveNumericalWithContext(strings.Split(condition, " > "), result, context)
|
parameters, resolvedParameters := sanitizeAndResolveNumericalWithContext(strings.Split(condition, " > "), result, context)
|
||||||
success = resolvedParameters[0] > resolvedParameters[1]
|
success = resolvedParameters[0] > resolvedParameters[1]
|
||||||
if !success && !dontResolveFailedConditions {
|
if shouldResolveCondition(success) {
|
||||||
conditionToDisplay = prettifyNumericalParameters(parameters, resolvedParameters, ">")
|
conditionToDisplay = prettifyNumericalParameters(parameters, resolvedParameters, ">")
|
||||||
}
|
}
|
||||||
} else if strings.Contains(condition, " < ") {
|
} else if strings.Contains(condition, " < ") {
|
||||||
parameters, resolvedParameters := sanitizeAndResolveNumericalWithContext(strings.Split(condition, " < "), result, context)
|
parameters, resolvedParameters := sanitizeAndResolveNumericalWithContext(strings.Split(condition, " < "), result, context)
|
||||||
success = resolvedParameters[0] < resolvedParameters[1]
|
success = resolvedParameters[0] < resolvedParameters[1]
|
||||||
if !success && !dontResolveFailedConditions {
|
if shouldResolveCondition(success) {
|
||||||
conditionToDisplay = prettifyNumericalParameters(parameters, resolvedParameters, "<")
|
conditionToDisplay = prettifyNumericalParameters(parameters, resolvedParameters, "<")
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ func BenchmarkCondition_evaluateWithBodyStringAny(b *testing.B) {
|
|||||||
condition := Condition("[BODY].name == any(john.doe, jane.doe)")
|
condition := Condition("[BODY].name == any(john.doe, jane.doe)")
|
||||||
for n := 0; n < b.N; n++ {
|
for n := 0; n < b.N; n++ {
|
||||||
result := &Result{Body: []byte("{\"name\": \"john.doe\"}")}
|
result := &Result{Body: []byte("{\"name\": \"john.doe\"}")}
|
||||||
condition.evaluate(result, false, nil)
|
condition.evaluate(result, false, false, nil)
|
||||||
}
|
}
|
||||||
b.ReportAllocs()
|
b.ReportAllocs()
|
||||||
}
|
}
|
||||||
@@ -17,7 +17,7 @@ func BenchmarkCondition_evaluateWithBodyStringAnyFailure(b *testing.B) {
|
|||||||
condition := Condition("[BODY].name == any(john.doe, jane.doe)")
|
condition := Condition("[BODY].name == any(john.doe, jane.doe)")
|
||||||
for n := 0; n < b.N; n++ {
|
for n := 0; n < b.N; n++ {
|
||||||
result := &Result{Body: []byte("{\"name\": \"bob.doe\"}")}
|
result := &Result{Body: []byte("{\"name\": \"bob.doe\"}")}
|
||||||
condition.evaluate(result, false, nil)
|
condition.evaluate(result, false, false, nil)
|
||||||
}
|
}
|
||||||
b.ReportAllocs()
|
b.ReportAllocs()
|
||||||
}
|
}
|
||||||
@@ -26,7 +26,7 @@ func BenchmarkCondition_evaluateWithBodyString(b *testing.B) {
|
|||||||
condition := Condition("[BODY].name == john.doe")
|
condition := Condition("[BODY].name == john.doe")
|
||||||
for n := 0; n < b.N; n++ {
|
for n := 0; n < b.N; n++ {
|
||||||
result := &Result{Body: []byte("{\"name\": \"john.doe\"}")}
|
result := &Result{Body: []byte("{\"name\": \"john.doe\"}")}
|
||||||
condition.evaluate(result, false, nil)
|
condition.evaluate(result, false, false, nil)
|
||||||
}
|
}
|
||||||
b.ReportAllocs()
|
b.ReportAllocs()
|
||||||
}
|
}
|
||||||
@@ -35,7 +35,7 @@ func BenchmarkCondition_evaluateWithBodyStringFailure(b *testing.B) {
|
|||||||
condition := Condition("[BODY].name == john.doe")
|
condition := Condition("[BODY].name == john.doe")
|
||||||
for n := 0; n < b.N; n++ {
|
for n := 0; n < b.N; n++ {
|
||||||
result := &Result{Body: []byte("{\"name\": \"bob.doe\"}")}
|
result := &Result{Body: []byte("{\"name\": \"bob.doe\"}")}
|
||||||
condition.evaluate(result, false, nil)
|
condition.evaluate(result, false, false, nil)
|
||||||
}
|
}
|
||||||
b.ReportAllocs()
|
b.ReportAllocs()
|
||||||
}
|
}
|
||||||
@@ -44,7 +44,7 @@ func BenchmarkCondition_evaluateWithBodyStringFailureInvalidPath(b *testing.B) {
|
|||||||
condition := Condition("[BODY].user.name == bob.doe")
|
condition := Condition("[BODY].user.name == bob.doe")
|
||||||
for n := 0; n < b.N; n++ {
|
for n := 0; n < b.N; n++ {
|
||||||
result := &Result{Body: []byte("{\"name\": \"bob.doe\"}")}
|
result := &Result{Body: []byte("{\"name\": \"bob.doe\"}")}
|
||||||
condition.evaluate(result, false, nil)
|
condition.evaluate(result, false, false, nil)
|
||||||
}
|
}
|
||||||
b.ReportAllocs()
|
b.ReportAllocs()
|
||||||
}
|
}
|
||||||
@@ -53,7 +53,7 @@ func BenchmarkCondition_evaluateWithBodyStringLen(b *testing.B) {
|
|||||||
condition := Condition("len([BODY].name) == 8")
|
condition := Condition("len([BODY].name) == 8")
|
||||||
for n := 0; n < b.N; n++ {
|
for n := 0; n < b.N; n++ {
|
||||||
result := &Result{Body: []byte("{\"name\": \"john.doe\"}")}
|
result := &Result{Body: []byte("{\"name\": \"john.doe\"}")}
|
||||||
condition.evaluate(result, false, nil)
|
condition.evaluate(result, false, false, nil)
|
||||||
}
|
}
|
||||||
b.ReportAllocs()
|
b.ReportAllocs()
|
||||||
}
|
}
|
||||||
@@ -62,7 +62,7 @@ func BenchmarkCondition_evaluateWithBodyStringLenFailure(b *testing.B) {
|
|||||||
condition := Condition("len([BODY].name) == 8")
|
condition := Condition("len([BODY].name) == 8")
|
||||||
for n := 0; n < b.N; n++ {
|
for n := 0; n < b.N; n++ {
|
||||||
result := &Result{Body: []byte("{\"name\": \"bob.doe\"}")}
|
result := &Result{Body: []byte("{\"name\": \"bob.doe\"}")}
|
||||||
condition.evaluate(result, false, nil)
|
condition.evaluate(result, false, false, nil)
|
||||||
}
|
}
|
||||||
b.ReportAllocs()
|
b.ReportAllocs()
|
||||||
}
|
}
|
||||||
@@ -71,7 +71,7 @@ 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++ {
|
||||||
result := &Result{HTTPStatus: 200}
|
result := &Result{HTTPStatus: 200}
|
||||||
condition.evaluate(result, false, nil)
|
condition.evaluate(result, false, false, nil)
|
||||||
}
|
}
|
||||||
b.ReportAllocs()
|
b.ReportAllocs()
|
||||||
}
|
}
|
||||||
@@ -80,7 +80,7 @@ func BenchmarkCondition_evaluateWithStatusFailure(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++ {
|
||||||
result := &Result{HTTPStatus: 400}
|
result := &Result{HTTPStatus: 400}
|
||||||
condition.evaluate(result, false, nil)
|
condition.evaluate(result, false, false, nil)
|
||||||
}
|
}
|
||||||
b.ReportAllocs()
|
b.ReportAllocs()
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -62,6 +62,7 @@ func TestCondition_evaluate(t *testing.T) {
|
|||||||
Condition Condition
|
Condition Condition
|
||||||
Result *Result
|
Result *Result
|
||||||
DontResolveFailedConditions bool
|
DontResolveFailedConditions bool
|
||||||
|
ResolveSuccessfulConditions bool
|
||||||
ExpectedSuccess bool
|
ExpectedSuccess bool
|
||||||
ExpectedOutput string
|
ExpectedOutput string
|
||||||
}{
|
}{
|
||||||
@@ -184,6 +185,14 @@ func TestCondition_evaluate(t *testing.T) {
|
|||||||
ExpectedSuccess: true,
|
ExpectedSuccess: true,
|
||||||
ExpectedOutput: "[BODY] == test",
|
ExpectedOutput: "[BODY] == test",
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
Name: "body-resolved-on-success",
|
||||||
|
Condition: Condition("[BODY].status == UP"),
|
||||||
|
Result: &Result{Body: []byte("{\"status\":\"UP\"}")},
|
||||||
|
ResolveSuccessfulConditions: true,
|
||||||
|
ExpectedSuccess: true,
|
||||||
|
ExpectedOutput: "[BODY].status (UP) == UP",
|
||||||
|
},
|
||||||
{
|
{
|
||||||
Name: "body-numerical-equal",
|
Name: "body-numerical-equal",
|
||||||
Condition: Condition("[BODY] == 123"),
|
Condition: Condition("[BODY] == 123"),
|
||||||
@@ -757,7 +766,7 @@ func TestCondition_evaluate(t *testing.T) {
|
|||||||
}
|
}
|
||||||
for _, scenario := range scenarios {
|
for _, scenario := range scenarios {
|
||||||
t.Run(scenario.Name, func(t *testing.T) {
|
t.Run(scenario.Name, func(t *testing.T) {
|
||||||
scenario.Condition.evaluate(scenario.Result, scenario.DontResolveFailedConditions, nil)
|
scenario.Condition.evaluate(scenario.Result, scenario.DontResolveFailedConditions, scenario.ResolveSuccessfulConditions, nil)
|
||||||
if scenario.Result.ConditionResults[0].Success != scenario.ExpectedSuccess {
|
if scenario.Result.ConditionResults[0].Success != scenario.ExpectedSuccess {
|
||||||
t.Errorf("Condition '%s' should have been success=%v", scenario.Condition, scenario.ExpectedSuccess)
|
t.Errorf("Condition '%s' should have been success=%v", scenario.Condition, scenario.ExpectedSuccess)
|
||||||
}
|
}
|
||||||
@@ -771,7 +780,7 @@ func TestCondition_evaluate(t *testing.T) {
|
|||||||
func TestCondition_evaluateWithInvalidOperator(t *testing.T) {
|
func TestCondition_evaluateWithInvalidOperator(t *testing.T) {
|
||||||
condition := Condition("[STATUS] ? 201")
|
condition := Condition("[STATUS] ? 201")
|
||||||
result := &Result{HTTPStatus: 201}
|
result := &Result{HTTPStatus: 201}
|
||||||
condition.evaluate(result, false, nil)
|
condition.evaluate(result, false, false, nil)
|
||||||
if result.Success {
|
if result.Success {
|
||||||
t.Error("condition was invalid, result should've been a failure")
|
t.Error("condition was invalid, result should've been a failure")
|
||||||
}
|
}
|
||||||
@@ -791,7 +800,7 @@ func TestConditionEvaluateWithInvalidContextPlaceholder(t *testing.T) {
|
|||||||
"max_response_time": 5000,
|
"max_response_time": 5000,
|
||||||
})
|
})
|
||||||
// Simulate suite endpoint evaluation with context
|
// Simulate suite endpoint evaluation with context
|
||||||
success := condition.evaluate(result, false, ctx) // false = don't skip resolution (default)
|
success := condition.evaluate(result, false, false, ctx) // false = don't skip resolution (default)
|
||||||
if success {
|
if success {
|
||||||
t.Error("Condition should have failed because [CONTEXT].expected_statusz doesn't exist")
|
t.Error("Condition should have failed because [CONTEXT].expected_statusz doesn't exist")
|
||||||
}
|
}
|
||||||
@@ -814,7 +823,7 @@ func TestConditionEvaluateWithValidContextPlaceholder(t *testing.T) {
|
|||||||
"expected_status": 200,
|
"expected_status": 200,
|
||||||
})
|
})
|
||||||
// Simulate suite endpoint evaluation with context
|
// Simulate suite endpoint evaluation with context
|
||||||
success := condition.evaluate(result, false, ctx)
|
success := condition.evaluate(result, false, false, ctx)
|
||||||
if !success {
|
if !success {
|
||||||
t.Error("Condition should have succeeded")
|
t.Error("Condition should have succeeded")
|
||||||
}
|
}
|
||||||
@@ -839,7 +848,7 @@ func TestConditionEvaluateWithMixedValidAndInvalidContext(t *testing.T) {
|
|||||||
"valid_key": 5000,
|
"valid_key": 5000,
|
||||||
})
|
})
|
||||||
// Simulate suite endpoint evaluation with context
|
// Simulate suite endpoint evaluation with context
|
||||||
success := condition.evaluate(result, false, ctx)
|
success := condition.evaluate(result, false, false, ctx)
|
||||||
if success {
|
if success {
|
||||||
t.Error("Condition should have failed because [CONTEXT].invalid_key doesn't exist")
|
t.Error("Condition should have failed because [CONTEXT].invalid_key doesn't exist")
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -332,7 +332,7 @@ func (e *Endpoint) EvaluateHealthWithContext(context *gontext.Gontext) *Result {
|
|||||||
}
|
}
|
||||||
// Evaluate the conditions
|
// Evaluate the conditions
|
||||||
for _, condition := range processedEndpoint.Conditions {
|
for _, condition := range processedEndpoint.Conditions {
|
||||||
success := condition.evaluate(result, processedEndpoint.UIConfig.DontResolveFailedConditions, context)
|
success := condition.evaluate(result, processedEndpoint.UIConfig.DontResolveFailedConditions, processedEndpoint.UIConfig.ResolveSuccessfulConditions, context)
|
||||||
if !success {
|
if !success {
|
||||||
result.Success = false
|
result.Success = false
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -268,6 +268,31 @@ func TestEndpoint(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestEndpoint_ResolveSuccessfulConditions(t *testing.T) {
|
||||||
|
defer client.InjectHTTPClient(nil)
|
||||||
|
endpoint := Endpoint{
|
||||||
|
Name: "test-endpoint",
|
||||||
|
URL: "https://example.com/health",
|
||||||
|
Conditions: []Condition{"[BODY].status == UP"},
|
||||||
|
UIConfig: &ui.Config{ResolveSuccessfulConditions: true},
|
||||||
|
}
|
||||||
|
mockResponse := test.MockRoundTripper(func(r *http.Request) *http.Response {
|
||||||
|
return &http.Response{StatusCode: http.StatusOK, Body: io.NopCloser(bytes.NewBufferString(`{"status":"UP"}`))}
|
||||||
|
})
|
||||||
|
client.InjectHTTPClient(&http.Client{Transport: mockResponse})
|
||||||
|
if err := endpoint.ValidateAndSetDefaults(); err != nil {
|
||||||
|
t.Fatalf("ValidateAndSetDefaults failed: %v", err)
|
||||||
|
}
|
||||||
|
result := endpoint.EvaluateHealth()
|
||||||
|
if len(result.ConditionResults) != 1 {
|
||||||
|
t.Fatalf("expected 1 condition result, got %d", len(result.ConditionResults))
|
||||||
|
}
|
||||||
|
expectedCondition := "[BODY].status (UP) == UP"
|
||||||
|
if result.ConditionResults[0].Condition != expectedCondition {
|
||||||
|
t.Errorf("expected condition to be '%s', got '%s'", expectedCondition, result.ConditionResults[0].Condition)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func TestEndpoint_IsEnabled(t *testing.T) {
|
func TestEndpoint_IsEnabled(t *testing.T) {
|
||||||
if !(&Endpoint{Enabled: nil}).IsEnabled() {
|
if !(&Endpoint{Enabled: nil}).IsEnabled() {
|
||||||
t.Error("endpoint.IsEnabled() should've returned true, because Enabled was set to nil")
|
t.Error("endpoint.IsEnabled() should've returned true, because Enabled was set to nil")
|
||||||
|
|||||||
@@ -22,6 +22,9 @@ type Config struct {
|
|||||||
// DontResolveFailedConditions whether to resolve failed conditions in the Result for display in the UI
|
// DontResolveFailedConditions whether to resolve failed conditions in the Result for display in the UI
|
||||||
DontResolveFailedConditions bool `yaml:"dont-resolve-failed-conditions"`
|
DontResolveFailedConditions bool `yaml:"dont-resolve-failed-conditions"`
|
||||||
|
|
||||||
|
// ResolveSuccessfulConditions whether to resolve successful conditions in the Result for display in the UI
|
||||||
|
ResolveSuccessfulConditions bool `yaml:"resolve-successful-conditions"`
|
||||||
|
|
||||||
// Badge is the configuration for the badges generated
|
// Badge is the configuration for the badges generated
|
||||||
Badge *Badge `yaml:"badge"`
|
Badge *Badge `yaml:"badge"`
|
||||||
}
|
}
|
||||||
@@ -63,6 +66,7 @@ func GetDefaultConfig() *Config {
|
|||||||
HidePort: false,
|
HidePort: false,
|
||||||
HideErrors: false,
|
HideErrors: false,
|
||||||
DontResolveFailedConditions: false,
|
DontResolveFailedConditions: false,
|
||||||
|
ResolveSuccessfulConditions: false,
|
||||||
HideConditions: false,
|
HideConditions: false,
|
||||||
Badge: &Badge{
|
Badge: &Badge{
|
||||||
ResponseTime: &ResponseTime{
|
ResponseTime: &ResponseTime{
|
||||||
|
|||||||
Reference in New Issue
Block a user