-
Notifications
You must be signed in to change notification settings - Fork 1.5k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add ScrapeErrors struct to simplify errors usage
Add ScrapeErrors that contains a slice with errors and that has methods to simplify adding new PartialScrapeErrors and regular generic errors. Use new methods to refactor errors appends in receiver/hostmetricsreceiver. Use ScrapeErrors.Combine() in component/componenterror to not create cycling dependencies in consumererrors package.
- Loading branch information
1 parent
bd70c80
commit 37f7da5
Showing
13 changed files
with
312 additions
and
223 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,47 @@ | ||
// Copyright The OpenTelemetry Authors | ||
// | ||
// Licensed under the Apache License, Version 2.0 (the "License"); | ||
// you may not use this file except in compliance with the License. | ||
// You may obtain a copy of the License at | ||
// | ||
// http://www.apache.org/licenses/LICENSE-2.0 | ||
// | ||
// Unless required by applicable law or agreed to in writing, software | ||
// distributed under the License is distributed on an "AS IS" BASIS, | ||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
// See the License for the specific language governing permissions and | ||
// limitations under the License. | ||
|
||
package consumererror | ||
|
||
import ( | ||
"fmt" | ||
"strings" | ||
) | ||
|
||
// CombineErrors converts a list of errors into one error. | ||
func CombineErrors(errs []error) error { | ||
numErrors := len(errs) | ||
if numErrors == 0 { | ||
// No errors | ||
return nil | ||
} | ||
|
||
if numErrors == 1 { | ||
return errs[0] | ||
} | ||
|
||
errMsgs := make([]string, 0, numErrors) | ||
permanent := false | ||
for _, err := range errs { | ||
if !permanent && IsPermanent(err) { | ||
permanent = true | ||
} | ||
errMsgs = append(errMsgs, err.Error()) | ||
} | ||
err := fmt.Errorf("[%s]", strings.Join(errMsgs, "; ")) | ||
if permanent { | ||
err = Permanent(err) | ||
} | ||
return err | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,75 @@ | ||
// Copyright The OpenTelemetry Authors | ||
// | ||
// Licensed under the Apache License, Version 2.0 (the "License"); | ||
// you may not use this file except in compliance with the License. | ||
// You may obtain a copy of the License at | ||
// | ||
// http://www.apache.org/licenses/LICENSE-2.0 | ||
// | ||
// Unless required by applicable law or agreed to in writing, software | ||
// distributed under the License is distributed on an "AS IS" BASIS, | ||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
// See the License for the specific language governing permissions and | ||
// limitations under the License. | ||
|
||
package consumererror | ||
|
||
import ( | ||
"fmt" | ||
"strings" | ||
) | ||
|
||
// ScrapeErrors contains multiple PartialScrapeErrors and can also contain generic errors. | ||
type ScrapeErrors struct { | ||
errs []error | ||
scrapeErrsCount int | ||
} | ||
|
||
// Add adds a PartialScrapeError with the provided failed count and error. | ||
func (s *ScrapeErrors) Add(failed int, err error) { | ||
s.errs = append(s.errs, NewPartialScrapeError(err, failed)) | ||
s.scrapeErrsCount++ | ||
} | ||
|
||
// Addf adds a PartialScrapeError with the provided failed count and arguments to format an error. | ||
func (s *ScrapeErrors) Addf(failed int, format string, a ...interface{}) { | ||
s.errs = append(s.errs, NewPartialScrapeError(fmt.Errorf(format, a...), failed)) | ||
s.scrapeErrsCount++ | ||
} | ||
|
||
// Add adds a regular generic error. | ||
func (s *ScrapeErrors) AddRegular(err error) { | ||
s.errs = append(s.errs, err) | ||
} | ||
|
||
// Add adds a regular generic error from the provided format specifier. | ||
func (s *ScrapeErrors) AddRegularf(format string, a ...interface{}) { | ||
s.errs = append(s.errs, fmt.Errorf(format, a...)) | ||
} | ||
|
||
// Combine converts a slice of errors into one error. | ||
// It will return a PartialScrapeError if at least one error in the slice is a PartialScrapeError. | ||
func (s *ScrapeErrors) Combine() error { | ||
if s.scrapeErrsCount == 0 { | ||
return CombineErrors(s.errs) | ||
} | ||
|
||
errMsgs := make([]string, 0, len(s.errs)) | ||
failedScrapeCount := 0 | ||
for _, err := range s.errs { | ||
if partialError, isPartial := err.(PartialScrapeError); isPartial { | ||
failedScrapeCount += partialError.Failed | ||
} | ||
|
||
errMsgs = append(errMsgs, err.Error()) | ||
} | ||
|
||
var err error | ||
if len(s.errs) == 1 { | ||
err = s.errs[0] | ||
} else { | ||
err = fmt.Errorf("[%s]", strings.Join(errMsgs, "; ")) | ||
} | ||
|
||
return NewPartialScrapeError(err, failedScrapeCount) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,145 @@ | ||
// Copyright The OpenTelemetry Authors | ||
// | ||
// Licensed under the Apache License, Version 2.0 (the "License"); | ||
// you may not use this file except in compliance with the License. | ||
// You may obtain a copy of the License at | ||
// | ||
// http://www.apache.org/licenses/LICENSE-2.0 | ||
// | ||
// Unless required by applicable law or agreed to in writing, software | ||
// distributed under the License is distributed on an "AS IS" BASIS, | ||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
// See the License for the specific language governing permissions and | ||
// limitations under the License. | ||
|
||
package consumererror | ||
|
||
import ( | ||
"errors" | ||
"fmt" | ||
"testing" | ||
|
||
"github.com/stretchr/testify/assert" | ||
) | ||
|
||
func TestScrapeErrorsAdd(t *testing.T) { | ||
err1 := errors.New("err 1") | ||
err2 := errors.New("err 2") | ||
expected := []error{ | ||
PartialScrapeError{error: err1, Failed: 1}, | ||
PartialScrapeError{error: err2, Failed: 10}, | ||
} | ||
|
||
var errs ScrapeErrors | ||
errs.Add(1, err1) | ||
errs.Add(10, err2) | ||
assert.Equal(t, expected, errs.errs) | ||
} | ||
|
||
func TestScrapeErrorsAddf(t *testing.T) { | ||
err1 := errors.New("err 10") | ||
err2 := errors.New("err 20") | ||
expected := []error{ | ||
PartialScrapeError{error: fmt.Errorf("err: %s", err1), Failed: 20}, | ||
PartialScrapeError{error: fmt.Errorf("err %s: %w", "2", err2), Failed: 2}, | ||
} | ||
|
||
var errs ScrapeErrors | ||
errs.Addf(20, "err: %s", err1) | ||
errs.Addf(2, "err %s: %w", "2", err2) | ||
assert.Equal(t, expected, errs.errs) | ||
} | ||
|
||
func TestScrapeErrorsAddRegular(t *testing.T) { | ||
err1 := errors.New("err a") | ||
err2 := errors.New("err b") | ||
expected := []error{err1, err2} | ||
|
||
var errs ScrapeErrors | ||
errs.AddRegular(err1) | ||
errs.AddRegular(err2) | ||
assert.Equal(t, expected, errs.errs) | ||
} | ||
|
||
func TestScrapeErrorsAddRegularf(t *testing.T) { | ||
err1 := errors.New("err aa") | ||
err2 := errors.New("err bb") | ||
expected := []error{ | ||
fmt.Errorf("err: %s", err1), | ||
fmt.Errorf("err %s: %w", "bb", err2), | ||
} | ||
|
||
var errs ScrapeErrors | ||
errs.AddRegularf("err: %s", err1) | ||
errs.AddRegularf("err %s: %w", "bb", err2) | ||
assert.Equal(t, expected, errs.errs) | ||
} | ||
|
||
func TestScrapeErrorsCombine(t *testing.T) { | ||
testCases := []struct { | ||
errs func() ScrapeErrors | ||
expectedErr string | ||
expectedFailedCount int | ||
expectNil bool | ||
expectedScrape bool | ||
}{ | ||
{ | ||
errs: func() ScrapeErrors { | ||
var errs ScrapeErrors | ||
return errs | ||
}, | ||
expectNil: true, | ||
}, | ||
{ | ||
errs: func() ScrapeErrors { | ||
var errs ScrapeErrors | ||
errs.Add(10, errors.New("bad scrapes")) | ||
errs.Addf(1, "err: %s", errors.New("bad scrape")) | ||
return errs | ||
}, | ||
expectedErr: "[bad scrapes; err: bad scrape]", | ||
expectedFailedCount: 11, | ||
expectedScrape: true, | ||
}, | ||
{ | ||
errs: func() ScrapeErrors { | ||
var errs ScrapeErrors | ||
errs.AddRegular(errors.New("bad regular")) | ||
errs.AddRegularf("err: %s", errors.New("bad reg")) | ||
return errs | ||
}, | ||
expectedErr: "[bad regular; err: bad reg]", | ||
}, | ||
{ | ||
errs: func() ScrapeErrors { | ||
var errs ScrapeErrors | ||
errs.Add(2, errors.New("bad two scrapes")) | ||
errs.Addf(10, "%d scrapes failed: %s", 10, errors.New("bad things happened")) | ||
errs.AddRegular(errors.New("bad event")) | ||
errs.AddRegularf("event: %s", errors.New("something happened")) | ||
return errs | ||
}, | ||
expectedErr: "[bad two scrapes; 10 scrapes failed: bad things happened; bad event; event: something happened]", | ||
expectedFailedCount: 12, | ||
expectedScrape: true, | ||
}, | ||
} | ||
|
||
for _, tc := range testCases { | ||
scrapeErrs := tc.errs() | ||
if (scrapeErrs.Combine() == nil) != tc.expectNil { | ||
t.Errorf("%+v.Combine() == nil? Got: %t. Want: %t", scrapeErrs, scrapeErrs.Combine() == nil, tc.expectNil) | ||
} | ||
if scrapeErrs.Combine() != nil && tc.expectedErr != scrapeErrs.Combine().Error() { | ||
t.Errorf("%+v.Combine() = %q. Want: %q", scrapeErrs, scrapeErrs.Combine(), tc.expectedErr) | ||
} | ||
if tc.expectedScrape { | ||
partialScrapeErr, ok := scrapeErrs.Combine().(PartialScrapeError) | ||
if !ok { | ||
t.Errorf("%+v.Combine() = %q. Want: PartialScrapeError", scrapeErrs, scrapeErrs.Combine()) | ||
} else if tc.expectedFailedCount != partialScrapeErr.Failed { | ||
t.Errorf("%+v.Combine().Failed. Got %d Failed count. Want: %d", scrapeErrs, partialScrapeErr.Failed, tc.expectedFailedCount) | ||
} | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.