Skip to content

Commit 1d1affc

Browse files
committed
Address PR feedback
1 parent b3cbde5 commit 1d1affc

File tree

3 files changed

+90
-52
lines changed

3 files changed

+90
-52
lines changed

consumer/consumererror/README.md

Lines changed: 11 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -198,21 +198,20 @@ component can then later pull all errors out for analysis.
198198
> here is for design purposes. The code snippet may not work as-written.
199199
200200
When a receiver gets a response that includes an error, it can get the data out
201-
by doing something similar to the following. Note that this uses the `ErrorData`
202-
type, which is for reading error data, as opposed to the `Error` type, which is
203-
for recording errors.
201+
by doing something similar to the following. Note that this uses the `Error`
202+
type, which is for reading error data, as opposed to the `ErrorContainer` type,
203+
which is for recording errors.
204204

205205
```go
206-
cerr := consumererror.Error{}
207-
var errData []consumerError.ErrorData
206+
cerr := consumererror.ErrorContainer{}
208207

209208
if errors.As(err, &cerr) {
210-
errData := cerr.Data()
209+
errs := cerr.Errors()
211210

212-
for _, data := range errData {
213-
data.HTTPStatus()
214-
data.Retryable()
215-
data.Partial()
211+
for _, e := range errs {
212+
e.HTTPStatus()
213+
e.Retryable()
214+
e.Partial()
216215
}
217216
}
218217
```
@@ -227,7 +226,7 @@ Obtaining data from an error can be done using an interface that looks something
227226
like this:
228227

229228
```go
230-
type ErrorData interface {
229+
type Error interface {
231230
// Returns the underlying error
232231
Error() error
233232

@@ -302,5 +301,5 @@ The following describes how to transition to these error types:
302301

303302
`consumererror.IsPermanent` will be deprecated in favor of checking whether
304303
retry information is available, and only retrying if it has been provided. This
305-
will be possible by calling `ErrorData.Retryable()` and checking for retry
304+
will be possible by calling `Error.Retryable()` and checking for retry
306305
information.

consumer/consumererror/error.go

Lines changed: 31 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -11,26 +11,26 @@ import (
1111
"go.opentelemetry.io/collector/consumer/consumererror/internal/statusconversion"
1212
)
1313

14-
// Error acts as a container for errors coming from pipeline components.
14+
// ErrorContainer acts as a container for errors coming from pipeline components.
1515
// It may hold multiple errors from downstream components, and is designed
1616
// to act as a way to accumulate errors as it travels upstream in a pipeline.
17-
// `Error` should be obtained using `errors.As` and as a result, ideally
17+
// `ErrorContainer` should be obtained using `errors.As` and as a result, ideally
1818
// a single instance should exist in an error stack. If this is not possible,
19-
// the most `Error` object should be highest on the stack.
19+
// the most `ErrorContainer` object should be highest on the stack.
2020
//
2121
// Experimental: This API is at the early stage of development and may change without backward compatibility
22-
type Error struct {
23-
errors []ErrorData
22+
type ErrorContainer struct {
23+
errors []Error
2424
}
2525

26-
// ErrorData is intended to be used to encapsulate various information
26+
// Error is intended to be used to encapsulate various information
2727
// that can add context to an error that occurred within a pipeline component.
28-
// ErrorData objects are constructed through calling `New` with the relevant
28+
// Error objects are constructed through calling `New` with the relevant
2929
// options to capture data around the error that occurred. It can then be pulled
3030
// out by an upstream component by calling `Error.Data`.
3131
//
3232
// Experimental: This API is at the early stage of development and may change without backward compatibility
33-
type ErrorData interface {
33+
type Error interface {
3434
Error() string
3535

3636
Unwrap() error
@@ -55,32 +55,40 @@ type errorData struct {
5555
}
5656

5757
// ErrorOption allows annotating an Error with metadata.
58-
type ErrorOption func(error *errorData)
58+
type ErrorOption interface {
59+
applyOption(*errorData)
60+
}
61+
62+
type errorOptionFunc func(*errorData)
63+
64+
func (f errorOptionFunc) applyOption(e *errorData) {
65+
f(e)
66+
}
5967

6068
// New wraps an error that happened while consuming telemetry
6169
// and adds metadata onto it to be passed back up the pipeline.
6270
//
6371
// Experimental: This API is at the early stage of development and may change without backward compatibility
6472
func New(origErr error, options ...ErrorOption) error {
6573
errData := &errorData{error: origErr}
66-
err := &Error{errors: []ErrorData{errData}}
74+
err := &ErrorContainer{errors: []Error{errData}}
6775

6876
for _, option := range options {
69-
option(errData)
77+
option.applyOption(errData)
7078
}
7179

7280
return err
7381
}
7482

75-
var _ error = &Error{}
83+
var _ error = (*ErrorContainer)(nil)
7684

7785
// Error implements the `error` interface.
78-
func (e *Error) Error() string {
86+
func (e *ErrorContainer) Error() string {
7987
return e.errors[len(e.errors)-1].Error()
8088
}
8189

8290
// Unwrap returns the wrapped error for use by `errors.Is` and `errors.As`.
83-
func (e *Error) Unwrap() []error {
91+
func (e *ErrorContainer) Unwrap() []error {
8492
errors := make([]error, 0, len(e.errors))
8593

8694
for _, err := range e.errors {
@@ -90,21 +98,21 @@ func (e *Error) Unwrap() []error {
9098
return errors
9199
}
92100

93-
// Data returns all the accumulated ErrorData errors
101+
// Errors returns all the accumulated Error objects
94102
// emitted by components downstream in the pipeline.
95103
// These can then be aggregated or worked with individually.
96-
func (e *Error) Data() []ErrorData {
104+
func (e *ErrorContainer) Errors() []Error {
97105
return e.errors
98106
}
99107

100108
// Combine joins errors that occur at a fanout into a single
101109
// `Error` object. The component that created the data submission
102110
// can then work with the `Error` object to understand the failure.
103-
func Combine(errs ...error) *Error {
104-
e := &Error{errors: make([]ErrorData, 0, len(errs))}
111+
func Combine(errs ...error) *ErrorContainer {
112+
e := &ErrorContainer{errors: make([]Error, 0, len(errs))}
105113

106114
for _, err := range errs {
107-
var otherErr *Error
115+
var otherErr *ErrorContainer
108116
if errors.As(err, &otherErr) {
109117
e.errors = append(e.errors, otherErr.errors...)
110118
} else {
@@ -118,17 +126,17 @@ func Combine(errs ...error) *Error {
118126
// WithHTTPStatus records an HTTP status code that was received
119127
// from a server during data submission.
120128
func WithHTTPStatus(status int) ErrorOption {
121-
return func(err *errorData) {
129+
return errorOptionFunc(func(err *errorData) {
122130
err.httpStatus = &status
123-
}
131+
})
124132
}
125133

126134
// WithGRPCStatus records a gRPC status code that was received
127135
// from a server during data submission.
128136
func WithGRPCStatus(status *status.Status) ErrorOption {
129-
return func(err *errorData) {
137+
return errorOptionFunc(func(err *errorData) {
130138
err.grpcStatus = status
131-
}
139+
})
132140
}
133141

134142
var _ error = (*errorData)(nil)

consumer/consumererror/error_test.go

Lines changed: 48 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,8 @@ var errTest = errors.New("consumererror testing error")
1818
func Test_New(t *testing.T) {
1919
httpStatus := 500
2020
grpcStatus := status.New(codes.Aborted, "aborted")
21-
wantErr := &Error{
22-
errors: []ErrorData{
21+
wantErr := &ErrorContainer{
22+
errors: []Error{
2323
&errorData{
2424
error: errTest,
2525
httpStatus: &httpStatus,
@@ -43,8 +43,8 @@ func Test_Error(t *testing.T) {
4343
}
4444

4545
func TestUnwrap(t *testing.T) {
46-
err := &Error{
47-
errors: []ErrorData{
46+
err := &ErrorContainer{
47+
errors: []Error{
4848
&errorData{
4949
error: errTest,
5050
},
@@ -65,8 +65,8 @@ func TestUnwrap(t *testing.T) {
6565

6666
func TestData(t *testing.T) {
6767
httpStatus := 500
68-
err := &Error{
69-
errors: []ErrorData{
68+
err := &ErrorContainer{
69+
errors: []Error{
7070
&errorData{
7171
error: errTest,
7272
httpStatus: &httpStatus,
@@ -78,7 +78,7 @@ func TestData(t *testing.T) {
7878
},
7979
}
8080

81-
data := err.Data()
81+
data := err.Errors()
8282

8383
require.Len(t, data, 2)
8484

@@ -89,16 +89,47 @@ func TestData(t *testing.T) {
8989
}
9090
}
9191

92+
func TestErrorSliceIsCopy(t *testing.T) {
93+
httpStatus := 500
94+
err := &ErrorContainer{
95+
errors: []Error{
96+
&errorData{
97+
error: errTest,
98+
httpStatus: &httpStatus,
99+
},
100+
&errorData{
101+
error: errTest,
102+
httpStatus: &httpStatus,
103+
},
104+
},
105+
}
106+
107+
errs := err.Errors()
108+
109+
require.Len(t, errs, 2)
110+
111+
for _, e := range errs {
112+
status, ok := e.HTTPStatus()
113+
require.True(t, ok)
114+
require.Equal(t, httpStatus, status)
115+
}
116+
117+
errs = append(errs, &errorData{error: errTest})
118+
119+
require.Len(t, errs, 3)
120+
require.Len(t, err.errors, 2)
121+
}
122+
92123
func TestCombine(t *testing.T) {
93-
err0 := &Error{
94-
errors: []ErrorData{
124+
err0 := &ErrorContainer{
125+
errors: []Error{
95126
&errorData{
96127
error: errTest,
97128
},
98129
},
99130
}
100-
err1 := &Error{
101-
errors: []ErrorData{
131+
err1 := &ErrorContainer{
132+
errors: []Error{
102133
&errorData{
103134
error: errTest,
104135
},
@@ -107,8 +138,8 @@ func TestCombine(t *testing.T) {
107138
},
108139
},
109140
}
110-
want := &Error{
111-
errors: []ErrorData{
141+
want := &ErrorContainer{
142+
errors: []Error{
112143
&errorData{
113144
error: errTest,
114145
},
@@ -129,23 +160,23 @@ func TestCombine(t *testing.T) {
129160
require.Equal(t, want, err)
130161
}
131162

132-
func TestErrorDataError(t *testing.T) {
163+
func TestError_Error(t *testing.T) {
133164
err := &errorData{
134165
error: errTest,
135166
}
136167

137168
require.Equal(t, errTest.Error(), err.Error())
138169
}
139170

140-
func TestErrorDataUnwrap(t *testing.T) {
171+
func TestError_Unwrap(t *testing.T) {
141172
err := &errorData{
142173
error: errTest,
143174
}
144175

145176
require.Equal(t, errTest, err.Unwrap())
146177
}
147178

148-
func TestErrorDataHTTPStatus(t *testing.T) {
179+
func TestError_HTTPStatus(t *testing.T) {
149180
serverErr := http.StatusTooManyRequests
150181
testCases := []struct {
151182
name string
@@ -195,7 +226,7 @@ func TestErrorDataHTTPStatus(t *testing.T) {
195226
}
196227
}
197228

198-
func TestErrorDataGRPCStatus(t *testing.T) {
229+
func TestError_GRPCStatus(t *testing.T) {
199230
httpStatus := http.StatusTooManyRequests
200231
otherHTTPStatus := http.StatusOK
201232
serverErr := status.New(codes.ResourceExhausted, errTest.Error())

0 commit comments

Comments
 (0)