mirror of
https://github.com/VictoriaMetrics/VictoriaMetrics.git
synced 2024-11-21 14:44:00 +00:00
app/vmalert: retry on empty data
This commit is contained in:
parent
d53dd6ecf3
commit
3bf05ba979
1 changed files with 57 additions and 44 deletions
|
@ -20,6 +20,8 @@ type datasourceType string
|
||||||
const (
|
const (
|
||||||
datasourcePrometheus datasourceType = "prometheus"
|
datasourcePrometheus datasourceType = "prometheus"
|
||||||
datasourceGraphite datasourceType = "graphite"
|
datasourceGraphite datasourceType = "graphite"
|
||||||
|
|
||||||
|
retries = 2
|
||||||
)
|
)
|
||||||
|
|
||||||
func toDatasourceType(s string) datasourceType {
|
func toDatasourceType(s string) datasourceType {
|
||||||
|
@ -135,36 +137,41 @@ func NewVMStorage(baseURL string, authCfg *promauth.Config, queryStep time.Durat
|
||||||
|
|
||||||
// Query executes the given query and returns parsed response
|
// Query executes the given query and returns parsed response
|
||||||
func (s *VMStorage) Query(ctx context.Context, query string, ts time.Time) (Result, *http.Request, error) {
|
func (s *VMStorage) Query(ctx context.Context, query string, ts time.Time) (Result, *http.Request, error) {
|
||||||
req, err := s.newQueryRequest(ctx, query, ts)
|
var e error
|
||||||
if err != nil {
|
for retry := 1; retry < retries; retry++ {
|
||||||
return Result{}, nil, err
|
req, err := s.newQueryRequest(ctx, query, ts)
|
||||||
}
|
if err != nil {
|
||||||
resp, err := s.do(req)
|
|
||||||
if err != nil {
|
|
||||||
if !errors.Is(err, io.EOF) && !errors.Is(err, io.ErrUnexpectedEOF) && !netutil.IsTrivialNetworkError(err) {
|
|
||||||
// Return unexpected error to the caller.
|
|
||||||
return Result{}, nil, err
|
return Result{}, nil, err
|
||||||
}
|
}
|
||||||
// Something in the middle between client and datasource might be closing
|
resp, err := s.do(req)
|
||||||
// the connection. So we do a one more attempt in hope request will succeed.
|
|
||||||
req, err = s.newQueryRequest(ctx, query, ts)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return Result{}, nil, fmt.Errorf("second attempt: %w", err)
|
// Something in the middle between client and datasource might be closing
|
||||||
|
// the connection. So we do a one more attempt in hope request will succeed.
|
||||||
|
if !errors.Is(err, io.EOF) && !errors.Is(err, io.ErrUnexpectedEOF) && !netutil.IsTrivialNetworkError(err) {
|
||||||
|
// Return unexpected error to the caller.
|
||||||
|
return Result{}, nil, err
|
||||||
|
}
|
||||||
|
e = err
|
||||||
|
continue
|
||||||
}
|
}
|
||||||
resp, err = s.do(req)
|
// Process the received response.
|
||||||
|
parseFn := parsePrometheusResponse
|
||||||
|
if s.dataSourceType != datasourcePrometheus {
|
||||||
|
parseFn = parseGraphiteResponse
|
||||||
|
}
|
||||||
|
result, err := parseFn(req, resp)
|
||||||
|
_ = resp.Body.Close()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return Result{}, nil, fmt.Errorf("second attempt: %w", err)
|
// Covering possible empty response
|
||||||
|
if !errors.Is(err, io.EOF) {
|
||||||
|
return Result{}, nil, err
|
||||||
|
}
|
||||||
|
e = err
|
||||||
|
continue
|
||||||
}
|
}
|
||||||
|
return result, req, err
|
||||||
}
|
}
|
||||||
|
return Result{}, nil, fmt.Errorf("failed after %d retries: %w", retries, e)
|
||||||
// Process the received response.
|
|
||||||
parseFn := parsePrometheusResponse
|
|
||||||
if s.dataSourceType != datasourcePrometheus {
|
|
||||||
parseFn = parseGraphiteResponse
|
|
||||||
}
|
|
||||||
result, err := parseFn(req, resp)
|
|
||||||
_ = resp.Body.Close()
|
|
||||||
return result, req, err
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// QueryRange executes the given query on the given time range.
|
// QueryRange executes the given query on the given time range.
|
||||||
|
@ -180,32 +187,38 @@ func (s *VMStorage) QueryRange(ctx context.Context, query string, start, end tim
|
||||||
if end.IsZero() {
|
if end.IsZero() {
|
||||||
return res, fmt.Errorf("end param is missing")
|
return res, fmt.Errorf("end param is missing")
|
||||||
}
|
}
|
||||||
req, err := s.newQueryRangeRequest(ctx, query, start, end)
|
var e error
|
||||||
if err != nil {
|
for retry := 1; retry < retries; retry++ {
|
||||||
return res, err
|
req, err := s.newQueryRangeRequest(ctx, query, start, end)
|
||||||
}
|
if err != nil {
|
||||||
resp, err := s.do(req)
|
|
||||||
if err != nil {
|
|
||||||
if !errors.Is(err, io.EOF) && !errors.Is(err, io.ErrUnexpectedEOF) && !netutil.IsTrivialNetworkError(err) {
|
|
||||||
// Return unexpected error to the caller.
|
|
||||||
return res, err
|
return res, err
|
||||||
}
|
}
|
||||||
// Something in the middle between client and datasource might be closing
|
resp, err := s.do(req)
|
||||||
// the connection. So we do a one more attempt in hope request will succeed.
|
|
||||||
req, err = s.newQueryRangeRequest(ctx, query, start, end)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return res, fmt.Errorf("second attempt: %w", err)
|
// Something in the middle between client and datasource might be closing
|
||||||
|
// the connection. So we do a one more attempt in hope request will succeed.
|
||||||
|
if !errors.Is(err, io.EOF) && !errors.Is(err, io.ErrUnexpectedEOF) && !netutil.IsTrivialNetworkError(err) {
|
||||||
|
// Return unexpected error to the caller.
|
||||||
|
return res, err
|
||||||
|
}
|
||||||
|
e = err
|
||||||
|
continue
|
||||||
}
|
}
|
||||||
resp, err = s.do(req)
|
|
||||||
if err != nil {
|
|
||||||
return res, fmt.Errorf("second attempt: %w", err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Process the received response.
|
// Process the received response.
|
||||||
res, err = parsePrometheusResponse(req, resp)
|
res, err = parsePrometheusResponse(req, resp)
|
||||||
_ = resp.Body.Close()
|
_ = resp.Body.Close()
|
||||||
return res, err
|
if err != nil {
|
||||||
|
// Covering possible empty response
|
||||||
|
if !errors.Is(err, io.EOF) {
|
||||||
|
return Result{}, err
|
||||||
|
}
|
||||||
|
e = err
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
return res, err
|
||||||
|
}
|
||||||
|
return Result{}, fmt.Errorf("failed after %d retries: %w", retries, e)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *VMStorage) do(req *http.Request) (*http.Response, error) {
|
func (s *VMStorage) do(req *http.Request) (*http.Response, error) {
|
||||||
|
|
Loading…
Reference in a new issue