Skip to content

Commit a65a5a6

Browse files
authored
Tidy up consumer/consumererror package. (#2768)
* Tidy up `consumer/consumererror` package. * Updated docblocks for grammar and consistency * Added `IsPartial()` predicate to match `IsPermanent()` * Ensured tests for `PartialError` test the public interface Remove `PartialError` and replace with individual signal error types Refactor consumererror signal extraction to simplify exporterhelper request interface * Rename consumererror signal error types to align with rest of codebase * Rename `onPartialError` to `onError` in `exporterhelper.request` interface * Provide conversion methods to consumererror signal error types. This moves the accessors for signal data to methods on the individual error types and provides As<Signal>() package functions that behave as targeted versions of the errors.As() function. * Avoid unnecessary allocation, fixup docs
1 parent c81a01b commit a65a5a6

33 files changed

+216
-144
lines changed

CHANGELOG.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,12 @@
22

33
## Unreleased
44

5+
## 🛑 Breaking changes 🛑
6+
7+
- Refactored `consumererror` package (#2768)
8+
- Eliminated `PartialError` type in favor of signal-specific types
9+
- Renamed `CombineErrors` to `Combine`
10+
511
## v0.23.0 Beta
612

713
## 🛑 Breaking changes 🛑

config/configcheck/configcheck.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@ func ValidateConfigFromFactories(factories component.Factories) error {
5656
}
5757
}
5858

59-
return consumererror.CombineErrors(errs)
59+
return consumererror.Combine(errs)
6060
}
6161

6262
// ValidateConfig enforces that given configuration object is following the patterns
@@ -109,7 +109,7 @@ func validateConfigDataType(t reflect.Type) error {
109109
// reflect.UnsafePointer.
110110
}
111111

112-
if err := consumererror.CombineErrors(errs); err != nil {
112+
if err := consumererror.Combine(errs); err != nil {
113113
return fmt.Errorf(
114114
"type %q from package %q has invalid config settings: %v",
115115
t.Name(),

consumer/consumererror/combineerrors.go renamed to consumer/consumererror/combine.go

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,8 +19,14 @@ import (
1919
"strings"
2020
)
2121

22-
// CombineErrors converts a list of errors into one error.
23-
func CombineErrors(errs []error) error {
22+
// Combine converts a list of errors into one error.
23+
//
24+
// If any of the errors in errs are Permanent then the returned
25+
// error will also be Permanent.
26+
//
27+
// Any signal data associated with an error from this package
28+
// will be discarded.
29+
func Combine(errs []error) error {
2430
numErrors := len(errs)
2531
if numErrors == 0 {
2632
// No errors

consumer/consumererror/combineerrors_test.go renamed to consumer/consumererror/combine_test.go

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ import (
1919
"testing"
2020
)
2121

22-
func TestCombineErrors(t *testing.T) {
22+
func TestCombine(t *testing.T) {
2323
testCases := []struct {
2424
errors []error
2525
expected string
@@ -53,15 +53,15 @@ func TestCombineErrors(t *testing.T) {
5353
}
5454

5555
for _, tc := range testCases {
56-
got := CombineErrors(tc.errors)
56+
got := Combine(tc.errors)
5757
if (got == nil) != tc.expectNil {
58-
t.Errorf("CombineErrors(%v) == nil? Got: %t. Want: %t", tc.errors, got == nil, tc.expectNil)
58+
t.Errorf("Combine(%v) == nil? Got: %t. Want: %t", tc.errors, got == nil, tc.expectNil)
5959
}
6060
if got != nil && tc.expected != got.Error() {
61-
t.Errorf("CombineErrors(%v) = %q. Want: %q", tc.errors, got, tc.expected)
61+
t.Errorf("Combine(%v) = %q. Want: %q", tc.errors, got, tc.expected)
6262
}
6363
if tc.expectedPermanent && !IsPermanent(got) {
64-
t.Errorf("CombineErrors(%v) = %q. Want: consumererror.permanent", tc.errors, got)
64+
t.Errorf("Combine(%v) = %q. Want: consumererror.permanent", tc.errors, got)
6565
}
6666
}
6767
}

consumer/consumererror/partialerror.go

Lines changed: 0 additions & 68 deletions
This file was deleted.

consumer/consumererror/permanenterror.go renamed to consumer/consumererror/permanent.go

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -25,9 +25,6 @@ type permanent struct {
2525
err error
2626
}
2727

28-
// permanentError exists to test errors for "IsPermanent"
29-
var permanentError = &permanent{}
30-
3128
// Permanent wraps an error to indicate that it is a permanent error, i.e.: an
3229
// error that will be always returned if its source receives the same inputs.
3330
func Permanent(err error) error {
@@ -42,8 +39,8 @@ func (p permanent) Error() string {
4239
// is used to indicate that a given error will always be returned in the case
4340
// that its sources receives the same input.
4441
func IsPermanent(err error) bool {
45-
if err != nil {
46-
return errors.As(err, permanentError)
42+
if err == nil {
43+
return false
4744
}
48-
return false
45+
return errors.As(err, &permanent{})
4946
}
Lines changed: 108 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,108 @@
1+
// Copyright The OpenTelemetry Authors
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// http://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
15+
package consumererror
16+
17+
import (
18+
"errors"
19+
20+
"go.opentelemetry.io/collector/consumer/pdata"
21+
)
22+
23+
// Traces is an error that may carry associated Trace data for a subset of received data
24+
// that faiiled to be processed or sent.
25+
type Traces struct {
26+
error
27+
failed pdata.Traces
28+
}
29+
30+
// NewTraces creates a Traces that can encapsulate received data that failed to be processed or sent.
31+
func NewTraces(err error, failed pdata.Traces) error {
32+
return Traces{
33+
error: err,
34+
failed: failed,
35+
}
36+
}
37+
38+
// AsTraces finds the first error in err's chain that can be assigned to target. If such an error is found
39+
// it is assigned to target and true is returned, otherwise false is returned.
40+
func AsTraces(err error, target *Traces) bool {
41+
if err == nil {
42+
return false
43+
}
44+
return errors.As(err, target)
45+
}
46+
47+
// GetTraces returns failed traces from the associated error.
48+
func (err Traces) GetTraces() pdata.Traces {
49+
return err.failed
50+
}
51+
52+
// Logs is an error that may carry associated Log data for a subset of received data
53+
// that faiiled to be processed or sent.
54+
type Logs struct {
55+
error
56+
failed pdata.Logs
57+
}
58+
59+
// NewLogs creates a Logs that can encapsulate received data that failed to be processed or sent.
60+
func NewLogs(err error, failed pdata.Logs) error {
61+
return Logs{
62+
error: err,
63+
failed: failed,
64+
}
65+
}
66+
67+
// AsLogs finds the first error in err's chain that can be assigned to target. If such an error is found
68+
// it is assigned to target and true is returned, otherwise false is returned.
69+
func AsLogs(err error, target *Logs) bool {
70+
if err == nil {
71+
return false
72+
}
73+
return errors.As(err, target)
74+
}
75+
76+
// GetLogs returns failed logs from the associated error.
77+
func (err Logs) GetLogs() pdata.Logs {
78+
return err.failed
79+
}
80+
81+
// Metrics is an error that may carry associated Metrics data for a subset of received data
82+
// that faiiled to be processed or sent.
83+
type Metrics struct {
84+
error
85+
failed pdata.Metrics
86+
}
87+
88+
// NewMetrics creates a Metrics that can encapsulate received data that failed to be processed or sent.
89+
func NewMetrics(err error, failed pdata.Metrics) error {
90+
return Metrics{
91+
error: err,
92+
failed: failed,
93+
}
94+
}
95+
96+
// AsMetrics finds the first error in err's chain that can be assigned to target. If such an error is found
97+
// it is assigned to target and true is returned, otherwise false is returned.
98+
func AsMetrics(err error, target *Metrics) bool {
99+
if err == nil {
100+
return false
101+
}
102+
return errors.As(err, target)
103+
}
104+
105+
// GetMetrics returns failed metrics from the associated error.
106+
func (err Metrics) GetMetrics() pdata.Metrics {
107+
return err.failed
108+
}

consumer/consumererror/partialerror_test.go renamed to consumer/consumererror/signalerrors_test.go

Lines changed: 24 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -23,26 +23,38 @@ import (
2323
"go.opentelemetry.io/collector/internal/testdata"
2424
)
2525

26-
func TestPartialError(t *testing.T) {
26+
func TestTraces(t *testing.T) {
2727
td := testdata.GenerateTraceDataOneSpan()
2828
err := fmt.Errorf("some error")
29-
partialErr := PartialTracesError(err, td)
30-
assert.Equal(t, err.Error(), partialErr.Error())
31-
assert.Equal(t, td, partialErr.(PartialError).failed)
29+
traceErr := NewTraces(err, td)
30+
assert.Equal(t, err.Error(), traceErr.Error())
31+
var target Traces
32+
assert.False(t, AsTraces(nil, &target))
33+
assert.False(t, AsTraces(err, &target))
34+
assert.True(t, AsTraces(traceErr, &target))
35+
assert.Equal(t, td, target.GetTraces())
3236
}
3337

34-
func TestPartialErrorLogs(t *testing.T) {
38+
func TestLogs(t *testing.T) {
3539
td := testdata.GenerateLogDataOneLog()
3640
err := fmt.Errorf("some error")
37-
partialErr := PartialLogsError(err, td)
38-
assert.Equal(t, err.Error(), partialErr.Error())
39-
assert.Equal(t, td, partialErr.(PartialError).failedLogs)
41+
logsErr := NewLogs(err, td)
42+
assert.Equal(t, err.Error(), logsErr.Error())
43+
var target Logs
44+
assert.False(t, AsLogs(nil, &target))
45+
assert.False(t, AsLogs(err, &target))
46+
assert.True(t, AsLogs(logsErr, &target))
47+
assert.Equal(t, td, target.GetLogs())
4048
}
4149

42-
func TestPartialErrorMetrics(t *testing.T) {
50+
func TestMetrics(t *testing.T) {
4351
td := testdata.GenerateMetricsOneMetric()
4452
err := fmt.Errorf("some error")
45-
partialErr := PartialMetricsError(err, td)
46-
assert.Equal(t, err.Error(), partialErr.Error())
47-
assert.Equal(t, td, partialErr.(PartialError).failedMetrics)
53+
metricErr := NewMetrics(err, td)
54+
assert.Equal(t, err.Error(), metricErr.Error())
55+
var target Metrics
56+
assert.False(t, AsMetrics(nil, &target))
57+
assert.False(t, AsMetrics(err, &target))
58+
assert.True(t, AsMetrics(metricErr, &target))
59+
assert.Equal(t, td, target.GetMetrics())
4860
}

consumer/fanoutconsumer/cloningconsumer.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@ func (mfc metricsCloningConsumer) ConsumeMetrics(ctx context.Context, md pdata.M
5656
}
5757
}
5858

59-
return consumererror.CombineErrors(errs)
59+
return consumererror.Combine(errs)
6060
}
6161

6262
// NewTracesCloning wraps multiple traces consumers in a single one and clones the data
@@ -93,7 +93,7 @@ func (tfc tracesCloningConsumer) ConsumeTraces(ctx context.Context, td pdata.Tra
9393
}
9494
}
9595

96-
return consumererror.CombineErrors(errs)
96+
return consumererror.Combine(errs)
9797
}
9898

9999
// NewLogsCloning wraps multiple trace consumers in a single one and clones the data
@@ -130,5 +130,5 @@ func (lfc logsCloningConsumer) ConsumeLogs(ctx context.Context, ld pdata.Logs) e
130130
}
131131
}
132132

133-
return consumererror.CombineErrors(errs)
133+
return consumererror.Combine(errs)
134134
}

0 commit comments

Comments
 (0)