Skip to content

Commit 687c3f5

Browse files
bachgarashdmathieupellaredMrAlias
authored
semconv: add ErrorType attribute function (#6962)
Closes #6904 This PR adds a helper method to semconv package to set ErrorType attribute easily. --------- Co-authored-by: Damien Mathieu <[email protected]> Co-authored-by: Robert Pająk <[email protected]> Co-authored-by: Tyler Yahn <[email protected]>
1 parent 73b2cd3 commit 687c3f5

File tree

5 files changed

+181
-0
lines changed

5 files changed

+181
-0
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ This project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.htm
3939
- `RPCConnectRPCResponseMetadata`
4040
- `RPCGRPCRequestMetadata`
4141
- `RPCGRPCResponseMetadata`
42+
- Add `ErrorType` attribute helper function to the `go.opentelmetry.io/otel/semconv/v1.34.0` package. (#6962)
4243

4344
### Changed
4445

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
// Copyright The OpenTelemetry Authors
2+
// SPDX-License-Identifier: Apache-2.0
3+
4+
package semconv // import "go.opentelemetry.io/otel/semconv/{{.TagVer}}"
5+
6+
import (
7+
"fmt"
8+
"reflect"
9+
10+
"go.opentelemetry.io/otel/attribute"
11+
)
12+
13+
// ErrorType returns an [attribute.KeyValue] identifying the error type of err.
14+
func ErrorType(err error) attribute.KeyValue {
15+
if err == nil {
16+
return ErrorTypeOther
17+
}
18+
t := reflect.TypeOf(err)
19+
var value string
20+
if t.PkgPath() == "" && t.Name() == "" {
21+
// Likely a builtin type.
22+
value = t.String()
23+
} else {
24+
value = fmt.Sprintf("%s.%s", t.PkgPath(), t.Name())
25+
}
26+
27+
if value == "" {
28+
return ErrorTypeOther
29+
}
30+
return ErrorTypeKey.String(value)
31+
}
Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
// Copyright The OpenTelemetry Authors
2+
// SPDX-License-Identifier: Apache-2.0
3+
4+
package semconv // import "go.opentelemetry.io/otel/semconv/{{.TagVer}}"
5+
6+
import (
7+
"errors"
8+
"fmt"
9+
"reflect"
10+
"testing"
11+
12+
"go.opentelemetry.io/otel/attribute"
13+
)
14+
15+
type CustomError struct{}
16+
17+
func (CustomError) Error() string {
18+
return "custom error"
19+
}
20+
21+
func TestErrorType(t *testing.T) {
22+
customErr := CustomError{}
23+
builtinErr := errors.New("something went wrong")
24+
var nilErr error
25+
26+
wantCustomType := reflect.TypeOf(customErr)
27+
wantCustomStr := fmt.Sprintf("%s.%s", wantCustomType.PkgPath(), wantCustomType.Name())
28+
29+
tests := []struct {
30+
name string
31+
err error
32+
want attribute.KeyValue
33+
}{
34+
{
35+
name: "BuiltinError",
36+
err: builtinErr,
37+
want: attribute.String("error.type", "*errors.errorString"),
38+
},
39+
{
40+
name: "CustomError",
41+
err: customErr,
42+
want: attribute.String("error.type", wantCustomStr),
43+
},
44+
{
45+
name: "NilError",
46+
err: nilErr,
47+
want: ErrorTypeOther,
48+
},
49+
}
50+
51+
for _, tt := range tests {
52+
t.Run(tt.name, func(t *testing.T) {
53+
got := ErrorType(tt.err)
54+
if got != tt.want {
55+
t.Errorf("ErrorType(%v) = %v, want %v", tt.err, got, tt.want)
56+
}
57+
})
58+
}
59+
}

semconv/v1.34.0/error_type.go

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
// Copyright The OpenTelemetry Authors
2+
// SPDX-License-Identifier: Apache-2.0
3+
4+
package semconv // import "go.opentelemetry.io/otel/semconv/v1.34.0"
5+
6+
import (
7+
"fmt"
8+
"reflect"
9+
10+
"go.opentelemetry.io/otel/attribute"
11+
)
12+
13+
// ErrorType returns an [attribute.KeyValue] identifying the error type of err.
14+
func ErrorType(err error) attribute.KeyValue {
15+
if err == nil {
16+
return ErrorTypeOther
17+
}
18+
t := reflect.TypeOf(err)
19+
var value string
20+
if t.PkgPath() == "" && t.Name() == "" {
21+
// Likely a builtin type.
22+
value = t.String()
23+
} else {
24+
value = fmt.Sprintf("%s.%s", t.PkgPath(), t.Name())
25+
}
26+
27+
if value == "" {
28+
return ErrorTypeOther
29+
}
30+
return ErrorTypeKey.String(value)
31+
}

semconv/v1.34.0/error_type_test.go

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
// Copyright The OpenTelemetry Authors
2+
// SPDX-License-Identifier: Apache-2.0
3+
4+
package semconv // import "go.opentelemetry.io/otel/semconv/v1.34.0"
5+
6+
import (
7+
"errors"
8+
"fmt"
9+
"reflect"
10+
"testing"
11+
12+
"go.opentelemetry.io/otel/attribute"
13+
)
14+
15+
type CustomError struct{}
16+
17+
func (CustomError) Error() string {
18+
return "custom error"
19+
}
20+
21+
func TestErrorType(t *testing.T) {
22+
customErr := CustomError{}
23+
builtinErr := errors.New("something went wrong")
24+
var nilErr error
25+
26+
wantCustomType := reflect.TypeOf(customErr)
27+
wantCustomStr := fmt.Sprintf("%s.%s", wantCustomType.PkgPath(), wantCustomType.Name())
28+
29+
tests := []struct {
30+
name string
31+
err error
32+
want attribute.KeyValue
33+
}{
34+
{
35+
name: "BuiltinError",
36+
err: builtinErr,
37+
want: attribute.String("error.type", "*errors.errorString"),
38+
},
39+
{
40+
name: "CustomError",
41+
err: customErr,
42+
want: attribute.String("error.type", wantCustomStr),
43+
},
44+
{
45+
name: "NilError",
46+
err: nilErr,
47+
want: ErrorTypeOther,
48+
},
49+
}
50+
51+
for _, tt := range tests {
52+
t.Run(tt.name, func(t *testing.T) {
53+
got := ErrorType(tt.err)
54+
if got != tt.want {
55+
t.Errorf("ErrorType(%v) = %v, want %v", tt.err, got, tt.want)
56+
}
57+
})
58+
}
59+
}

0 commit comments

Comments
 (0)