Skip to content
Merged
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ This project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.htm
- `RPCConnectRPCResponseMetadata`
- `RPCGRPCRequestMetadata`
- `RPCGRPCResponseMetadata`
- Add `ErrorType` attribute helper function to the `go.opentelmetry.io/otel/semconv/v1.34.0` package. (#6962)

### Changed

Expand Down
31 changes: 31 additions & 0 deletions internal/tools/semconvkit/templates/error_type.go.tmpl
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
// Copyright The OpenTelemetry Authors
// SPDX-License-Identifier: Apache-2.0

package semconv // import "go.opentelemetry.io/otel/semconv/{{.TagVer}}"

Comment thread
bachgarash marked this conversation as resolved.
import (
"fmt"
"reflect"

"go.opentelemetry.io/otel/attribute"
)

// ErrorType returns an [attribute.KeyValue] identifying the error type of err.
func ErrorType(err error) attribute.KeyValue {
if err == nil {
return ErrorTypeOther
}
t := reflect.TypeOf(err)
var value string
if t.PkgPath() == "" && t.Name() == "" {
// Likely a builtin type.
value = t.String()
} else {
value = fmt.Sprintf("%s.%s", t.PkgPath(), t.Name())
}

if value == "" {
return ErrorTypeOther
}
return ErrorTypeKey.String(value)
}
59 changes: 59 additions & 0 deletions internal/tools/semconvkit/templates/error_type_test.go.tmpl
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
// Copyright The OpenTelemetry Authors
// SPDX-License-Identifier: Apache-2.0

package semconv // import "go.opentelemetry.io/otel/semconv/{{.TagVer}}"

import (
"errors"
"fmt"
"reflect"
"testing"

"go.opentelemetry.io/otel/attribute"
)

type CustomError struct{}

func (CustomError) Error() string {
return "custom error"
}

func TestErrorType(t *testing.T) {
customErr := CustomError{}
builtinErr := errors.New("something went wrong")
var nilErr error

wantCustomType := reflect.TypeOf(customErr)
wantCustomStr := fmt.Sprintf("%s.%s", wantCustomType.PkgPath(), wantCustomType.Name())

tests := []struct {
name string
err error
want attribute.KeyValue
}{
{
name: "BuiltinError",
err: builtinErr,
want: attribute.String("error.type", "*errors.errorString"),
},
{
name: "CustomError",
err: customErr,
want: attribute.String("error.type", wantCustomStr),
},
{
name: "NilError",
err: nilErr,
want: ErrorTypeOther,
},
}

for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
got := ErrorType(tt.err)
if got != tt.want {
t.Errorf("ErrorType(%v) = %v, want %v", tt.err, got, tt.want)
}
})
}
}
31 changes: 31 additions & 0 deletions semconv/v1.34.0/error_type.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
// Copyright The OpenTelemetry Authors
// SPDX-License-Identifier: Apache-2.0

package semconv // import "go.opentelemetry.io/otel/semconv/v1.34.0"

import (
"fmt"
"reflect"

"go.opentelemetry.io/otel/attribute"
)

// ErrorType returns an [attribute.KeyValue] identifying the error type of err.
func ErrorType(err error) attribute.KeyValue {
Comment thread
bachgarash marked this conversation as resolved.
if err == nil {
return ErrorTypeOther
}
t := reflect.TypeOf(err)
var value string
if t.PkgPath() == "" && t.Name() == "" {
// Likely a builtin type.
value = t.String()
} else {
value = fmt.Sprintf("%s.%s", t.PkgPath(), t.Name())
}

Check warning on line 25 in semconv/v1.34.0/error_type.go

View check run for this annotation

Codecov / codecov/patch

semconv/v1.34.0/error_type.go#L14-L25

Added lines #L14 - L25 were not covered by tests

if value == "" {
return ErrorTypeOther
}
return ErrorTypeKey.String(value)

Check warning on line 30 in semconv/v1.34.0/error_type.go

View check run for this annotation

Codecov / codecov/patch

semconv/v1.34.0/error_type.go#L27-L30

Added lines #L27 - L30 were not covered by tests
}
59 changes: 59 additions & 0 deletions semconv/v1.34.0/error_type_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
// Copyright The OpenTelemetry Authors
// SPDX-License-Identifier: Apache-2.0

package semconv // import "go.opentelemetry.io/otel/semconv/v1.34.0"

import (
"errors"
"fmt"
"reflect"
"testing"

"go.opentelemetry.io/otel/attribute"
)

type CustomError struct{}

func (CustomError) Error() string {
return "custom error"
}

func TestErrorType(t *testing.T) {
customErr := CustomError{}
builtinErr := errors.New("something went wrong")
var nilErr error

wantCustomType := reflect.TypeOf(customErr)
wantCustomStr := fmt.Sprintf("%s.%s", wantCustomType.PkgPath(), wantCustomType.Name())

tests := []struct {
name string
err error
want attribute.KeyValue
}{
{
name: "BuiltinError",
err: builtinErr,
want: attribute.String("error.type", "*errors.errorString"),
},
{
name: "CustomError",
err: customErr,
want: attribute.String("error.type", wantCustomStr),
},
{
name: "NilError",
err: nilErr,
want: ErrorTypeOther,
},
}

for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
got := ErrorType(tt.err)
if got != tt.want {
t.Errorf("ErrorType(%v) = %v, want %v", tt.err, got, tt.want)
}
})
}
}
Loading