Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Handle complex structs in metadata #215

Merged
merged 4 commits into from
Mar 1, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,10 @@
* Start showing inlined functions in stack trace
[#208](https://github.com/bugsnag/bugsnag-go/pull/208)

* Handle complex structs in metadata
[#215](https://github.com/bugsnag/bugsnag-go/pull/215)
[Chris Duncan](https://github.com/veqryn)

## 2.2.0 (2022-10-12)

### Enhancements
Expand Down
25 changes: 21 additions & 4 deletions v2/metadata.go
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
package bugsnag

import (
"encoding"
"fmt"
"reflect"
"strings"
"time"
)

// MetaData is added to the Bugsnag dashboard in tabs. Each tab is
Expand Down Expand Up @@ -65,7 +67,7 @@ func (meta MetaData) sanitize(filters []string) interface{} {

}

// The sanitizer is used to remove filtered params and recursion from meta-data.
// sanitizer is used to remove filtered params and recursion from meta-data.
type sanitizer struct {
Filters []string
Seen []interface{}
Expand All @@ -83,6 +85,24 @@ func (s sanitizer) Sanitize(data interface{}) interface{} {
// s.Seen for nested calls.
s.Seen = append(s.Seen, data)

// Handle certain well known interfaces and types
switch data := data.(type) {
case error:
return data.Error()

case time.Time:
return data.Format(time.RFC3339Nano)

case fmt.Stringer:
// This also covers time.Duration
return data.String()

case encoding.TextMarshaler:
if b, err := data.MarshalText(); err == nil {
return string(b)
}
}

t := reflect.TypeOf(data)
v := reflect.ValueOf(data)

Expand Down Expand Up @@ -123,9 +143,7 @@ func (s sanitizer) Sanitize(data interface{}) interface{} {
// case t.Chan, t.Func, reflect.Complex64, reflect.Complex128, reflect.UnsafePointer:
default:
return "[" + t.String() + "]"

}

}

func (s sanitizer) sanitizeMap(v reflect.Value) interface{} {
Expand Down Expand Up @@ -175,7 +193,6 @@ func (s sanitizer) sanitizeStruct(v reflect.Value, t reflect.Type) interface{} {
} else {
ret[name] = sanitized
}

}
}

Expand Down
16 changes: 16 additions & 0 deletions v2/metadata_test.go
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
package bugsnag

import (
stderrors "errors"
"reflect"
"testing"
"time"
"unsafe"

"github.com/bugsnag/bugsnag-go/v2/errors"
Expand All @@ -26,6 +28,12 @@ type _broken struct {
Data string
}

type _textMarshaller struct{}

func (_textMarshaller) MarshalText() ([]byte, error) {
return []byte("marshalled text"), nil
}

var account = _account{}
var notifier = New(Configuration{})

Expand Down Expand Up @@ -123,6 +131,10 @@ func TestMetaDataSanitize(t *testing.T) {
"unsafe": unsafe.Pointer(broken.Me),
"string": "string",
"password": "secret",
"error": stderrors.New("some error"),
"time": time.Date(2023, 12, 5, 23, 59, 59, 123456789, time.UTC),
"duration": 105567462 * time.Millisecond,
"text": _textMarshaller{},
"array": []hash{{
"creditcard": "1234567812345678",
"broken": broken,
Expand All @@ -144,6 +156,10 @@ func TestMetaDataSanitize(t *testing.T) {
"unsafe": "[unsafe.Pointer]",
"func": "[func()]",
"password": "[FILTERED]",
"error": "some error",
"time": "2023-12-05T23:59:59.123456789Z",
"duration": "29h19m27.462s",
"text": "marshalled text",
"array": []interface{}{map[string]interface{}{
"creditcard": "[FILTERED]",
"broken": map[string]interface{}{
Expand Down
Loading