1
0
mirror of https://github.com/open-telemetry/opentelemetry-go.git synced 2026-06-03 18:35:08 +02:00
Robert Pająk
2026-04-07 20:03:30 +02:00
committed by GitHub
parent 5e9a80b3ce
commit 3b18b21580
7 changed files with 97 additions and 5 deletions
@@ -5,6 +5,7 @@ package semconv // import "go.opentelemetry.io/otel/semconv/{{.TagVer}}"
import (
"errors"
"fmt"
"reflect"
"go.opentelemetry.io/otel/attribute"
@@ -22,7 +23,8 @@ import (
// the returned attribute has that method's return value. If multiple errors in
// the chain implement this method, the value from the first match found by
// [errors.As] is used. Otherwise, the returned attribute has a value derived
// from the concrete type of err.
// from the concrete type of err after unwrapping any wrappers created with
// [fmt.Errorf].
//
// The key of the returned attribute is [ErrorTypeKey].
func ErrorType(err error) attribute.KeyValue {
@@ -50,7 +52,7 @@ func errorType(err error) string {
// Fallback to reflection if the ErrorType method is not supported or
// returns an empty value.
t := reflect.TypeOf(err)
t := reflect.TypeOf(unwrapFmtWrapped(err))
pkg, name := t.PkgPath(), t.Name()
if pkg != "" && name != "" {
s = pkg + "." + name
@@ -64,3 +66,16 @@ func errorType(err error) string {
}
return s
}
var fmtWrapErrorType = reflect.TypeOf(fmt.Errorf("wrapped: %w", errors.New("err")))
func unwrapFmtWrapped(err error) error {
for reflect.TypeOf(err) == fmtWrapErrorType {
u := errors.Unwrap(err)
if u == nil {
return err // When the wrapped error is nil, use the concrete type of the wrapper.
}
err = u
}
return err
}
@@ -5,6 +5,7 @@ package semconv // import "go.opentelemetry.io/otel/semconv/{{.TagVer}}"
import (
"errors"
"fmt"
"testing"
)
@@ -18,6 +19,10 @@ func TestErrorType(t *testing.T) {
check(t, custom(""), pkg+".ErrCustomType") // empty ErrorType, use concrete type.
check(t, wrapped(custom("wrapped-aborted")), "wrapped-aborted")
check(t, wrapped(custom("")), pkg+".wrappedErr") // empty ErrorType in chain, use concrete top-level type.
check(t, fmtWrapped(custom("")), pkg+".ErrCustomType")
check(t, fmtWrapped(wrapped(custom(""))), pkg+".wrappedErr")
check(t, fmtWrapped(fmtWrapped(custom(""))), pkg+".ErrCustomType")
check(t, fmtWrapped(nil), fmtWrapErrorType.String()) // fmt.Errorf with nil error, use concrete type of the wrapper.
}
func check(t *testing.T, err error, want string) {
@@ -39,6 +44,10 @@ func wrapped(err error) error {
return wrappedErr{err: err}
}
func fmtWrapped(err error) error {
return fmt.Errorf("wrapped: %w", err)
}
type ErrCustomType struct {
Type string
}