Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit a3fbba1

Browse files
committed
Remove Value interface and ForceJSON
Realized we can replace ForceJSON now that we only marshal structs as JSON if they have a json struct tag and json.Marshaller can be used in place of Value as well so its not necessary.
1 parent a13a242 commit a3fbba1

File tree

9 files changed

+173
-212
lines changed

9 files changed

+173
-212
lines changed

example_forcejson_test.go

Lines changed: 0 additions & 30 deletions
This file was deleted.

example_value_test.go

Lines changed: 0 additions & 32 deletions
This file was deleted.

go.mod

Lines changed: 14 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -3,15 +3,19 @@ module cdr.dev/slog
33
go 1.13
44

55
require (
6-
cloud.google.com/go v0.43.0
7-
github.com/alecthomas/chroma v0.6.6
6+
cloud.google.com/go v0.49.0
7+
github.com/alecthomas/chroma v0.7.0
8+
github.com/dlclark/regexp2 v1.2.0 // indirect
89
github.com/fatih/color v1.7.0
9-
github.com/kylelemons/godebug v1.1.0
10-
github.com/mattn/go-colorable v0.1.2 // indirect
11-
github.com/mattn/go-isatty v0.0.9 // indirect
12-
go.opencensus.io v0.22.1
13-
golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5
14-
golang.org/x/sys v0.0.0-20190904154756-749cb33beabd // indirect
15-
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7
16-
google.golang.org/genproto v0.0.0-20190716160619-c506a9f90610
10+
github.com/golang/groupcache v0.0.0-20191027212112-611e8accdfc9 // indirect
11+
github.com/google/go-cmp v0.3.2-0.20191216170541-340f1ebe299e
12+
github.com/mattn/go-colorable v0.1.4 // indirect
13+
github.com/mattn/go-isatty v0.0.11 // indirect
14+
go.opencensus.io v0.22.2
15+
golang.org/x/crypto v0.0.0-20191206172530-e9b2fee46413
16+
golang.org/x/net v0.0.0-20191209160850-c0dbc17a3553 // indirect
17+
golang.org/x/sys v0.0.0-20191210023423-ac6580df4449 // indirect
18+
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543
19+
google.golang.org/genproto v0.0.0-20191216164720-4f79533eabd1
20+
google.golang.org/grpc v1.25.1 // indirect
1721
)

go.sum

Lines changed: 85 additions & 17 deletions
Large diffs are not rendered by default.

internal/assert/assert.go

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,15 +5,24 @@ import (
55
"reflect"
66
"testing"
77

8-
"github.com/kylelemons/godebug/pretty"
8+
"github.com/google/go-cmp/cmp"
9+
"github.com/google/go-cmp/cmp/cmpopts"
910
)
1011

12+
// Diff returns a diff between exp and act.
13+
func Diff(exp, act interface{}, opts ...cmp.Option) string {
14+
opts = append(opts, cmpopts.EquateErrors(), cmp.Exporter(func(r reflect.Type) bool {
15+
return true
16+
}))
17+
return cmp.Diff(exp, act, opts...)
18+
}
19+
1120
// Equal asserts exp == act.
1221
func Equal(t testing.TB, name string, exp, act interface{}) {
1322
t.Helper()
14-
if !reflect.DeepEqual(exp, act) {
23+
if diff := Diff(exp, act); diff != "" {
1524
t.Fatalf(`unexpected %v: diff:
16-
%v`, name, pretty.Compare(exp, act))
25+
%v`, name, diff)
1726
}
1827
}
1928

map.go

Lines changed: 46 additions & 61 deletions
Original file line numberDiff line numberDiff line change
@@ -13,11 +13,6 @@ import (
1313
// Map represents an ordered map of fields.
1414
type Map []Field
1515

16-
// SlogValue implements Value.
17-
func (m Map) SlogValue() interface{} {
18-
return ForceJSON(m)
19-
}
20-
2116
var _ json.Marshaler = Map(nil)
2217

2318
// MarshalJSON implements json.Marshaler.
@@ -27,23 +22,20 @@ var _ json.Marshaler = Map(nil)
2722
//
2823
// Every field value is encoded with the following process:
2924
//
30-
// 1. slog.Value is checked to allow any type to replace its representation for logging.
31-
//
32-
// 2. json.Marshaller is handled.
25+
// 1. json.Marshaller is handled.
3326
//
3427
// 2. xerrors.Formatter is handled.
3528
//
36-
// 3. Protobufs are encoded with json.Marshal.
29+
// 3. structs that have a field with a json tag are encoded with json.Marshal.
3730
//
38-
// 4. error and fmt.Stringer are used if possible.
31+
// 4. error and fmt.Stringer is handled.
3932
//
4033
// 5. slices and arrays go through the encode function for every element.
4134
//
42-
// 6. If the value is a struct without exported fields or a type that
43-
// cannot be encoded with json.Marshal (like channels) then
44-
// fmt.Sprintf("%+v") is used.
35+
// 6. If the value cannot be encoded directly with json.Marshal (like channels)
36+
// then fmt.Sprintf("%+v") is used.
4537
//
46-
// 8. json.Marshal(v) is used for all other values.
38+
// 7. json.Marshal(v) is used for all other values.
4739
func (m Map) MarshalJSON() ([]byte, error) {
4840
b := &bytes.Buffer{}
4941
b.WriteByte('{')
@@ -62,19 +54,6 @@ func (m Map) MarshalJSON() ([]byte, error) {
6254
return b.Bytes(), nil
6355
}
6456

65-
// ForceJSON ensures the value is logged via json.Marshal.
66-
//
67-
// Use it when implementing SlogValue to ensure a structured
68-
// representation of a struct if you know it's capable even
69-
// when it implements fmt.Stringer or error.
70-
func ForceJSON(v interface{}) interface{} {
71-
return jsonVal{v: v}
72-
}
73-
74-
type jsonVal struct {
75-
v interface{}
76-
}
77-
7857
func marshalList(rv reflect.Value) []byte {
7958
b := &bytes.Buffer{}
8059
b.WriteByte('[')
@@ -93,51 +72,57 @@ func marshalList(rv reflect.Value) []byte {
9372

9473
func encode(v interface{}) []byte {
9574
switch v := v.(type) {
96-
case Value:
97-
return encode(v.SlogValue())
9875
case json.Marshaler:
9976
return encodeJSON(v)
100-
case jsonVal:
101-
return encodeJSON(v.v)
10277
case xerrors.Formatter:
10378
return encode(errorChain(v))
104-
case interface {
105-
ProtoMessage()
106-
}:
107-
return encode(ForceJSON(v))
79+
}
80+
81+
rv := reflect.Indirect(reflect.ValueOf(v))
82+
if !rv.IsValid() {
83+
return encodeJSON(v)
84+
}
85+
86+
if rv.Kind() == reflect.Struct {
87+
b, ok := encodeStruct(rv)
88+
if ok {
89+
return b
90+
}
91+
}
92+
93+
switch v.(type) {
10894
case error, fmt.Stringer:
10995
return encode(fmt.Sprint(v))
110-
default:
111-
rv := reflect.Indirect(reflect.ValueOf(v))
112-
if !rv.IsValid() {
113-
return encodeJSON(v)
114-
}
96+
}
11597

116-
switch rv.Type().Kind() {
117-
case reflect.Slice:
118-
if !rv.IsNil() {
119-
return marshalList(rv)
120-
}
121-
case reflect.Array:
98+
switch rv.Type().Kind() {
99+
case reflect.Slice:
100+
if !rv.IsNil() {
122101
return marshalList(rv)
123-
case reflect.Struct:
124-
typ := rv.Type()
125-
for i := 0; i < rv.NumField(); i++ {
126-
// Found an exported field.
127-
if typ.Field(i).PkgPath == "" {
128-
return encodeJSON(v)
129-
}
130-
}
131-
132-
return encodeJSON(fmt.Sprintf("%+v", v))
133-
case reflect.Chan, reflect.Complex64, reflect.Complex128, reflect.Func:
134-
// These types cannot be directly encoded with json.Marshal.
135-
// See https://golang.org/pkg/encoding/json/#Marshal
136-
return encodeJSON(fmt.Sprintf("%+v", v))
137102
}
103+
case reflect.Array:
104+
return marshalList(rv)
105+
case reflect.Struct, reflect.Chan, reflect.Complex64, reflect.Complex128, reflect.Func:
106+
// These types cannot be directly encoded with json.Marshal.
107+
// See https://golang.org/pkg/encoding/json/#Marshal
108+
return encodeJSON(fmt.Sprintf("%+v", v))
109+
}
138110

139-
return encodeJSON(v)
111+
return encodeJSON(v)
112+
}
113+
114+
func encodeStruct(rv reflect.Value) ([]byte, bool) {
115+
if rv.Kind() == reflect.Struct {
116+
for i := 0; i < rv.NumField(); i++ {
117+
ft := rv.Type().Field(i)
118+
// Found a field with a json tag.
119+
if ft.Tag.Get("json") != "" {
120+
return encodeJSON(rv.Interface()), true
121+
}
122+
}
140123
}
124+
125+
return nil, false
141126
}
142127

143128
func encodeJSON(v interface{}) []byte {

map_test.go

Lines changed: 10 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -86,18 +86,18 @@ func TestMap(t *testing.T) {
8686
mapTestFile := strings.Replace(mapTestFile, "_test", "", 1)
8787

8888
test(t, slog.M(
89-
slog.F("meow", slog.ForceJSON(complex(10, 10))),
89+
slog.F("meow", complexJSON(complex(10, 10))),
9090
), `{
9191
"meow": {
9292
"error": [
9393
{
9494
"msg": "failed to marshal to JSON",
9595
"fun": "cdr.dev/slog.encodeJSON",
96-
"loc": "`+mapTestFile+`:147"
96+
"loc": "`+mapTestFile+`:132"
9797
},
98-
"json: unsupported type: complex128"
98+
"json: error calling MarshalJSON for type slog_test.complexJSON: json: unsupported type: complex128"
9999
],
100-
"type": "complex128",
100+
"type": "slog_test.complexJSON",
101101
"value": "(10+10i)"
102102
}
103103
}`)
@@ -163,26 +163,6 @@ func TestMap(t *testing.T) {
163163
}`)
164164
})
165165

166-
t.Run("forceJSON", func(t *testing.T) {
167-
t.Parallel()
168-
169-
test(t, slog.M(
170-
slog.F("error", slog.ForceJSON(io.EOF)),
171-
), `{
172-
"error": {}
173-
}`)
174-
})
175-
176-
t.Run("value", func(t *testing.T) {
177-
t.Parallel()
178-
179-
test(t, slog.M(
180-
slog.F("error", meow{1}),
181-
), `{
182-
"error": "xdxd"
183-
}`)
184-
})
185-
186166
t.Run("nilSlice", func(t *testing.T) {
187167
t.Parallel()
188168

@@ -246,10 +226,6 @@ type meow struct {
246226
a int
247227
}
248228

249-
func (m meow) SlogValue() interface{} {
250-
return "xdxd"
251-
}
252-
253229
func indentJSON(t *testing.T, j string) string {
254230
b := &bytes.Buffer{}
255231
err := json.Indent(b, []byte(j), "", strings.Repeat(" ", 4))
@@ -263,3 +239,9 @@ func marshalJSON(t *testing.T, m slog.Map) string {
263239
assert.Success(t, "marshal map to JSON", err)
264240
return indentJSON(t, string(actb))
265241
}
242+
243+
type complexJSON complex128
244+
245+
func (c complexJSON) MarshalJSON() ([]byte, error) {
246+
return json.Marshal(complex128(c))
247+
}

slog.go

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -226,14 +226,6 @@ func M(fs ...Field) Map {
226226
return fs
227227
}
228228

229-
// Value represents a log value.
230-
//
231-
// Implement SlogValue in your own types to override
232-
// the value encoded when logging.
233-
type Value interface {
234-
SlogValue() interface{}
235-
}
236-
237229
// Error is the standard key used for logging a Go error value.
238230
func Error(err error) Field {
239231
return F("error", err)

0 commit comments

Comments
 (0)