Skip to content

Commit 35c7cdc

Browse files
authored
Merge pull request #21 from thockin/master
Logr 1.1.0 & implement glogr in terms of funcr
2 parents d7291e6 + 0704819 commit 35c7cdc

File tree

4 files changed

+26
-231
lines changed

4 files changed

+26
-231
lines changed

example/main.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ func main() {
4444
_ = flag.Set("v", "1")
4545
_ = flag.Set("logtostderr", "true")
4646
flag.Parse()
47-
log := glogr.NewWithOptions(glogr.Options{LogCaller: glogr.All}).WithName("MyName")
47+
log := glogr.NewWithOptions(glogr.Options{}).WithName("MyName")
4848
example(log.WithValues("module", "example"))
4949
}
5050

glogr.go

Lines changed: 22 additions & 227 deletions
Original file line numberDiff line numberDiff line change
@@ -19,15 +19,8 @@ limitations under the License.
1919
package glogr
2020

2121
import (
22-
"bytes"
23-
"fmt"
24-
"path/filepath"
25-
"reflect"
26-
"runtime"
27-
"strconv"
28-
"strings"
29-
3022
"github.com/go-logr/logr"
23+
"github.com/go-logr/logr/funcr"
3124
"github.com/golang/glog"
3225
)
3326

@@ -42,12 +35,17 @@ func NewWithOptions(opts Options) logr.Logger {
4235
opts.Depth = 0
4336
}
4437

38+
fopts := funcr.Options{
39+
LogCaller: funcr.MessageClass(opts.LogCaller),
40+
}
41+
4542
gl := &glogger{
46-
prefix: "",
47-
values: nil,
48-
depth: opts.Depth,
49-
logCaller: opts.LogCaller,
43+
Formatter: funcr.NewFormatter(fopts),
5044
}
45+
46+
// For skipping glogger.Info and glogger.Error.
47+
gl.Formatter.AddCallDepth(opts.Depth)
48+
5149
return logr.New(gl)
5250
}
5351

@@ -82,246 +80,43 @@ const (
8280
)
8381

8482
type glogger struct {
85-
prefix string
86-
values []interface{}
87-
depth int
88-
logCaller MessageClass
83+
funcr.Formatter
8984
}
9085

9186
var _ logr.LogSink = &glogger{}
9287
var _ logr.CallDepthLogSink = &glogger{}
9388

94-
func flatten(kvList ...interface{}) string {
95-
if len(kvList)%2 != 0 {
96-
kvList = append(kvList, "<no-value>")
97-
}
98-
// Empirically bytes.Buffer is faster than strings.Builder for this.
99-
buf := bytes.NewBuffer(make([]byte, 0, 1024))
100-
for i := 0; i < len(kvList); i += 2 {
101-
k, ok := kvList[i].(string)
102-
if !ok {
103-
k = fmt.Sprintf("<non-string-key-%d>", i/2)
104-
}
105-
v := kvList[i+1]
106-
107-
if i > 0 {
108-
buf.WriteRune(' ')
109-
}
110-
buf.WriteRune('"')
111-
buf.WriteString(k)
112-
buf.WriteRune('"')
113-
buf.WriteRune('=')
114-
buf.WriteString(pretty(v))
115-
}
116-
return buf.String()
117-
}
118-
119-
func pretty(value interface{}) string {
120-
return prettyWithFlags(value, 0)
121-
}
122-
123-
const (
124-
flagRawString = 0x1
125-
)
126-
127-
// TODO: This is not fast. Most of the overhead goes here.
128-
func prettyWithFlags(value interface{}, flags uint32) string {
129-
// Handling the most common types without reflect is a small perf win.
130-
switch v := value.(type) {
131-
case bool:
132-
return strconv.FormatBool(v)
133-
case string:
134-
if flags&flagRawString > 0 {
135-
return v
136-
}
137-
// This is empirically faster than strings.Builder.
138-
return `"` + v + `"`
139-
case int:
140-
return strconv.FormatInt(int64(v), 10)
141-
case int8:
142-
return strconv.FormatInt(int64(v), 10)
143-
case int16:
144-
return strconv.FormatInt(int64(v), 10)
145-
case int32:
146-
return strconv.FormatInt(int64(v), 10)
147-
case int64:
148-
return strconv.FormatInt(int64(v), 10)
149-
case uint:
150-
return strconv.FormatUint(uint64(v), 10)
151-
case uint8:
152-
return strconv.FormatUint(uint64(v), 10)
153-
case uint16:
154-
return strconv.FormatUint(uint64(v), 10)
155-
case uint32:
156-
return strconv.FormatUint(uint64(v), 10)
157-
case uint64:
158-
return strconv.FormatUint(v, 10)
159-
case uintptr:
160-
return strconv.FormatUint(uint64(v), 10)
161-
case float32:
162-
return strconv.FormatFloat(float64(v), 'f', -1, 32)
163-
case float64:
164-
return strconv.FormatFloat(v, 'f', -1, 64)
165-
}
166-
167-
buf := bytes.NewBuffer(make([]byte, 0, 256))
168-
t := reflect.TypeOf(value)
169-
if t == nil {
170-
return "null"
171-
}
172-
v := reflect.ValueOf(value)
173-
switch t.Kind() {
174-
case reflect.Bool:
175-
return strconv.FormatBool(v.Bool())
176-
case reflect.String:
177-
if flags&flagRawString > 0 {
178-
return v.String()
179-
}
180-
// This is empirically faster than strings.Builder.
181-
return `"` + v.String() + `"`
182-
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
183-
return strconv.FormatInt(int64(v.Int()), 10)
184-
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
185-
return strconv.FormatUint(uint64(v.Uint()), 10)
186-
case reflect.Float32:
187-
return strconv.FormatFloat(float64(v.Float()), 'f', -1, 32)
188-
case reflect.Float64:
189-
return strconv.FormatFloat(v.Float(), 'f', -1, 64)
190-
case reflect.Struct:
191-
buf.WriteRune('{')
192-
for i := 0; i < t.NumField(); i++ {
193-
f := t.Field(i)
194-
if f.PkgPath != "" {
195-
// reflect says this field is only defined for non-exported fields.
196-
continue
197-
}
198-
if i > 0 {
199-
buf.WriteRune(',')
200-
}
201-
buf.WriteRune('"')
202-
name := f.Name
203-
if tag, found := f.Tag.Lookup("json"); found {
204-
if comma := strings.Index(tag, ","); comma != -1 {
205-
name = tag[:comma]
206-
} else {
207-
name = tag
208-
}
209-
}
210-
buf.WriteString(name)
211-
buf.WriteRune('"')
212-
buf.WriteRune(':')
213-
buf.WriteString(pretty(v.Field(i).Interface()))
214-
}
215-
buf.WriteRune('}')
216-
return buf.String()
217-
case reflect.Slice, reflect.Array:
218-
buf.WriteRune('[')
219-
for i := 0; i < v.Len(); i++ {
220-
if i > 0 {
221-
buf.WriteRune(',')
222-
}
223-
e := v.Index(i)
224-
buf.WriteString(pretty(e.Interface()))
225-
}
226-
buf.WriteRune(']')
227-
return buf.String()
228-
case reflect.Map:
229-
buf.WriteRune('{')
230-
// This does not sort the map keys, for best perf.
231-
it := v.MapRange()
232-
i := 0
233-
for it.Next() {
234-
if i > 0 {
235-
buf.WriteRune(',')
236-
}
237-
// JSON only does string keys.
238-
buf.WriteRune('"')
239-
buf.WriteString(prettyWithFlags(it.Key().Interface(), flagRawString))
240-
buf.WriteRune('"')
241-
buf.WriteRune(':')
242-
buf.WriteString(pretty(it.Value().Interface()))
243-
i++
244-
}
245-
buf.WriteRune('}')
246-
return buf.String()
247-
case reflect.Ptr, reflect.Interface:
248-
return pretty(v.Elem().Interface())
249-
}
250-
return fmt.Sprintf(`"<unhandled-%s>"`, t.Kind().String())
251-
}
252-
253-
type callerID struct {
254-
File string `json:"file"`
255-
Line int `json:"line"`
256-
}
257-
258-
func (l glogger) caller() callerID {
259-
// +1 for this frame, +1 for Info/Error.
260-
_, file, line, ok := runtime.Caller(l.depth + 2)
261-
if !ok {
262-
return callerID{"<unknown>", 0}
263-
}
264-
return callerID{filepath.Base(file), line}
265-
}
266-
267-
func (l *glogger) Init(info logr.RuntimeInfo) {
268-
l.depth += info.CallDepth
269-
}
270-
27189
func (l glogger) Enabled(level int) bool {
27290
return bool(glog.V(glog.Level(level)))
27391
}
27492

27593
func (l glogger) Info(level int, msg string, kvList ...interface{}) {
276-
args := make([]interface{}, 0, 64) // using a constant here impacts perf
277-
if l.logCaller == All || l.logCaller == Info {
278-
args = append(args, "caller", l.caller())
94+
prefix, args := l.FormatInfo(level, msg, kvList)
95+
if prefix != "" {
96+
args = prefix + ": " + args
27997
}
280-
args = append(args, "level", level, "msg", msg)
281-
args = append(args, l.values...)
282-
args = append(args, kvList...)
283-
argsStr := flatten(args...)
284-
glog.InfoDepth(l.depth+1, l.prefix, argsStr)
98+
glog.InfoDepth(l.Formatter.GetDepth()+1, args)
28599
}
286100

287101
func (l glogger) Error(err error, msg string, kvList ...interface{}) {
288-
args := make([]interface{}, 0, 64) // using a constant here impacts perf
289-
if l.logCaller == All || l.logCaller == Error {
290-
args = append(args, "caller", l.caller())
102+
prefix, args := l.FormatError(err, msg, kvList)
103+
if prefix != "" {
104+
args = prefix + ": " + args
291105
}
292-
args = append(args, "msg", msg)
293-
var loggableErr interface{}
294-
if err != nil {
295-
loggableErr = err.Error()
296-
}
297-
args = append(args, "error", loggableErr)
298-
args = append(args, l.values...)
299-
args = append(args, kvList...)
300-
argsStr := flatten(args...)
301-
glog.ErrorDepth(l.depth+1, l.prefix, argsStr)
106+
glog.ErrorDepth(l.Formatter.GetDepth()+1, args)
302107
}
303108

304-
// WithName returns a new logr.Logger with the specified name appended. glogr
305-
// uses '/' characters to separate name elements. Callers should not pass '/'
306-
// in the provided name string, but this library does not actually enforce that.
307109
func (l glogger) WithName(name string) logr.LogSink {
308-
if len(l.prefix) > 0 {
309-
l.prefix += "/"
310-
}
311-
l.prefix += name
110+
l.Formatter.AddName(name)
312111
return &l
313112
}
314113

315114
func (l glogger) WithValues(kvList ...interface{}) logr.LogSink {
316-
// Three slice args forces a copy.
317-
n := len(l.values)
318-
l.values = append(l.values[:n:n], kvList...)
115+
l.Formatter.AddValues(kvList)
319116
return &l
320-
321117
}
322118

323119
func (l glogger) WithCallDepth(depth int) logr.LogSink {
324-
l.depth += depth
120+
l.Formatter.AddCallDepth(depth)
325121
return &l
326-
327122
}

go.mod

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,6 @@ module github.com/go-logr/glogr
33
go 1.16
44

55
require (
6-
github.com/go-logr/logr v1.0.0
6+
github.com/go-logr/logr v1.1.0
77
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b
88
)

go.sum

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
github.com/go-logr/logr v1.0.0 h1:kH951GinvFVaQgy/ki/B3YYmQtRpExGigSJg6O8z5jo=
2-
github.com/go-logr/logr v1.0.0/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A=
1+
github.com/go-logr/logr v1.1.0 h1:nAbevmWlS2Ic4m4+/An5NXkaGqlqpbBgdcuThZxnZyI=
2+
github.com/go-logr/logr v1.1.0/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A=
33
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b h1:VKtxabqXZkF25pY9ekfRL6a582T4P37/31XEstQ5p58=
44
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=

0 commit comments

Comments
 (0)