Alerting: Attempt to retry retryable errors (#79037)
* Alerting: Attempt to retry retryable errors Currently in a draft state, but this was the minimal diff I could put together to exemplify how could achieve this. Signed-off-by: gotjosh <josue.abreu@gmail.com> --------- Signed-off-by: gotjosh <josue.abreu@gmail.com>
This commit is contained in:
@@ -157,6 +157,23 @@ func (evalResults Results) HasErrors() bool {
|
||||
return false
|
||||
}
|
||||
|
||||
// HasNonRetryableErrors returns true if we have at least 1 result with:
|
||||
// 1. A `State` of `Error`
|
||||
// 2. The `Error` attribute is not nil
|
||||
// 3. The `Error` type is of `&invalidEvalResultFormatError`
|
||||
// Our thinking with this approach, is that we don't want to retry errors that have relation with invalid alert definition format.
|
||||
func (evalResults Results) HasNonRetryableErrors() bool {
|
||||
for _, r := range evalResults {
|
||||
if r.State == Error && r.Error != nil {
|
||||
var nonRetryableError *invalidEvalResultFormatError
|
||||
if errors.As(r.Error, &nonRetryableError) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// HasErrors returns true when Results contains at least one element and all elements are errors
|
||||
func (evalResults Results) IsError() bool {
|
||||
for _, r := range evalResults {
|
||||
@@ -177,6 +194,18 @@ func (evalResults Results) IsNoData() bool {
|
||||
return true
|
||||
}
|
||||
|
||||
// Error returns the aggregated `error` of all results of which state is `Error`.
|
||||
func (evalResults Results) Error() error {
|
||||
var errs []error
|
||||
for _, result := range evalResults {
|
||||
if result.State == Error && result.Error != nil {
|
||||
errs = append(errs, result.Error)
|
||||
}
|
||||
}
|
||||
|
||||
return errors.Join(errs...)
|
||||
}
|
||||
|
||||
// Result contains the evaluated State of an alert instance
|
||||
// identified by its labels.
|
||||
type Result struct {
|
||||
|
||||
@@ -2,6 +2,7 @@ package eval
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"math/rand"
|
||||
"testing"
|
||||
@@ -769,6 +770,70 @@ func TestEvaluateRaw(t *testing.T) {
|
||||
})
|
||||
}
|
||||
|
||||
func TestResults_HasNonRetryableErrors(t *testing.T) {
|
||||
tc := []struct {
|
||||
name string
|
||||
eval Results
|
||||
expected bool
|
||||
}{
|
||||
{
|
||||
name: "with non-retryable errors",
|
||||
eval: Results{
|
||||
{
|
||||
State: Error,
|
||||
Error: &invalidEvalResultFormatError{refID: "A", reason: "unable to get frame row length", err: errors.New("weird error")},
|
||||
},
|
||||
},
|
||||
expected: true,
|
||||
},
|
||||
{
|
||||
name: "with retryable errors",
|
||||
eval: Results{
|
||||
{
|
||||
State: Error,
|
||||
Error: errors.New("some weird error"),
|
||||
},
|
||||
},
|
||||
expected: false,
|
||||
},
|
||||
}
|
||||
|
||||
for _, tt := range tc {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
require.Equal(t, tt.expected, tt.eval.HasNonRetryableErrors())
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestResults_Error(t *testing.T) {
|
||||
tc := []struct {
|
||||
name string
|
||||
eval Results
|
||||
expected string
|
||||
}{
|
||||
{
|
||||
name: "with non-retryable errors",
|
||||
eval: Results{
|
||||
{
|
||||
State: Error,
|
||||
Error: &invalidEvalResultFormatError{refID: "A", reason: "unable to get frame row length", err: errors.New("weird error")},
|
||||
},
|
||||
{
|
||||
State: Error,
|
||||
Error: errors.New("unable to get a data frame"),
|
||||
},
|
||||
},
|
||||
expected: "invalid format of evaluation results for the alert definition A: unable to get frame row length: weird error\nunable to get a data frame",
|
||||
},
|
||||
}
|
||||
|
||||
for _, tt := range tc {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
require.Equal(t, tt.expected, tt.eval.Error().Error())
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
type fakeExpressionService struct {
|
||||
hook func(ctx context.Context, now time.Time, pipeline expr.DataPipeline) (*backend.QueryDataResponse, error)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user