diff --git a/.chloggen/consumererror_partial_success.yaml b/.chloggen/consumererror_partial_success.yaml new file mode 100644 index 00000000000..4d479b03eb8 --- /dev/null +++ b/.chloggen/consumererror_partial_success.yaml @@ -0,0 +1,25 @@ +# Use this changelog template to create an entry for release notes. + +# One of 'breaking', 'deprecation', 'new_component', 'enhancement', 'bug_fix' +change_type: enhancement + +# The name of the component, or a single word describing the area of concern, (e.g. otlpreceiver) +component: consumererror + +# A brief description of the change. Surround your text with quotes ("") if it needs to start with a backtick (`). +note: Add new partial error type to consumererror to allow consumers to report partial successes. + +# One or more tracking issues or pull requests related to the change +issues: [13423] + +# (Optional) One or more lines of additional information to render under the primary note. +# These lines will be padded with 2 spaces and then inserted directly into the document. +# Use pipe (|) for multiline entries. +subtext: + +# Optional: The change log or logs in which this entry should be included. +# e.g. '[user]' or '[user, api]' +# Include 'user' if the change is relevant to end users. +# Include 'api' if there is a change to a library API. +# Default: '[user]' +change_logs: [] diff --git a/consumer/consumererror/partial.go b/consumer/consumererror/partial.go new file mode 100644 index 00000000000..a401565b487 --- /dev/null +++ b/consumer/consumererror/partial.go @@ -0,0 +1,44 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +package consumererror // import "go.opentelemetry.io/collector/consumer/consumererror" + +import "errors" + +type partialError struct { + inner error + failed int +} + +var _ error = partialError{} + +func (pe partialError) Error() string { + return pe.inner.Error() +} + +func (pe partialError) Unwrap() error { + return pe.inner +} + +func (pe partialError) Failed() int { + return pe.failed +} + +// NewPartial creates a new partial error. This is used by consumers +// to report errors where only a subset of the total items failed +// to be written, but it is not possible to tell which particular items +// failed. +func NewPartial(err error, failed int) error { + return NewPermanent(partialError{ + inner: err, + failed: failed, + }) +} + +// AsPartial checks if an error was wrapped with the NewPartial function, +// or if it contains one such error in its Unwrap() tree. +func AsPartial(err error) (partialError, bool) { + var pe partialError + ok := errors.As(err, &pe) + return pe, ok +} diff --git a/consumer/consumererror/partial_test.go b/consumer/consumererror/partial_test.go new file mode 100644 index 00000000000..00c3979e58e --- /dev/null +++ b/consumer/consumererror/partial_test.go @@ -0,0 +1,22 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +package consumererror + +import ( + "errors" + "testing" + + "github.com/stretchr/testify/assert" +) + +func TestPartial(t *testing.T) { + internalErr := errors.New("some points failed") + err := NewPartial(internalErr, 5) + assert.True(t, IsPermanent(err)) + partialErr, ok := AsPartial(err) + assert.True(t, ok) + assert.Equal(t, 5, partialErr.Failed()) + assert.Equal(t, internalErr, partialErr.Unwrap()) + assert.Equal(t, internalErr.Error(), partialErr.Error()) +}