From 962cb0041bfef1eef65fc1937617128b32de9cdf Mon Sep 17 00:00:00 2001 From: Bogdan Drutu Date: Wed, 2 Oct 2024 17:42:01 -0700 Subject: [PATCH] Fix an issue when the error is nil but is different than nil Signed-off-by: Bogdan Drutu --- receiver/receiverhelper/obsreport.go | 12 +++++++++++- receiver/receiverhelper/obsreport_test.go | 24 ++++++++++++++++++++++- 2 files changed, 34 insertions(+), 2 deletions(-) diff --git a/receiver/receiverhelper/obsreport.go b/receiver/receiverhelper/obsreport.go index c92c464ff53..5ca49c38e87 100644 --- a/receiver/receiverhelper/obsreport.go +++ b/receiver/receiverhelper/obsreport.go @@ -7,6 +7,7 @@ package receiverhelper // import "go.opentelemetry.io/collector/receiver/receive import ( "context" + "reflect" "go.opentelemetry.io/otel/attribute" "go.opentelemetry.io/otel/codes" @@ -186,7 +187,7 @@ func (rec *ObsReport) endOp( attribute.Int64(acceptedItemsKey, int64(numAccepted)), attribute.Int64(refusedItemsKey, int64(numRefused)), ) - if err != nil { + if !isErrorNil(err) { span.SetStatus(codes.Error, err.Error()) } } @@ -210,3 +211,12 @@ func (rec *ObsReport) recordMetrics(receiverCtx context.Context, signal pipeline acceptedMeasure.Add(receiverCtx, int64(numAccepted), metric.WithAttributes(rec.otelAttrs...)) refusedMeasure.Add(receiverCtx, int64(numRefused), metric.WithAttributes(rec.otelAttrs...)) } + +// Correctly checks for nil, even in case of https://go.dev/doc/faq#nil_error. +func isErrorNil(err error) bool { + if err == nil { + return true + } + val := reflect.ValueOf(err) + return val.Kind() == reflect.Ptr && val.IsNil() +} diff --git a/receiver/receiverhelper/obsreport_test.go b/receiver/receiverhelper/obsreport_test.go index 455fd16a8e9..896e4a97e4f 100644 --- a/receiver/receiverhelper/obsreport_test.go +++ b/receiver/receiverhelper/obsreport_test.go @@ -296,10 +296,32 @@ func TestCheckReceiverLogsViews(t *testing.T) { assert.Error(t, tt.CheckReceiverLogs(transport, 0, 7)) } +type myError struct { + error +} + +func returnsError(b bool) error { + var p *myError + if b { + p = &myError{error: errors.New("my error")} + } + return p // Will always return a non-nil error. +} + +func TestIsErrorNil(t *testing.T) { + assert.True(t, isErrorNil(nil)) + assert.False(t, isErrorNil(returnsError(true))) + // nolint + assert.NotNil(t, returnsError(true) == nil) + assert.True(t, isErrorNil(returnsError(false))) + // nolint + assert.False(t, returnsError(false) == nil) + assert.False(t, isErrorNil(myError{error: errors.New("my error")})) +} + func testTelemetry(t *testing.T, id component.ID, testFunc func(t *testing.T, tt componenttest.TestTelemetry)) { tt, err := componenttest.SetupTelemetry(id) require.NoError(t, err) t.Cleanup(func() { require.NoError(t, tt.Shutdown(context.Background())) }) - testFunc(t, tt) }