3
3
package glogr
4
4
5
5
import (
6
+ "bytes"
7
+ "encoding/json"
6
8
"fmt"
7
9
"runtime"
10
+ "sort"
8
11
12
+ "github.com/go-logr/logr"
9
13
"github.com/golang/glog"
10
- "github.com/thockin/logr"
11
14
)
12
15
13
16
// New returns a logr.Logger which is implemented by glog.
14
- func New () ( logr.Logger , error ) {
17
+ func New () logr.Logger {
15
18
return glogger {
16
19
level : 0 ,
17
20
prefix : "" ,
18
- }, nil
21
+ values : nil ,
22
+ }
19
23
}
20
24
21
25
type glogger struct {
22
26
level int
23
27
prefix string
28
+ values []interface {}
29
+ }
30
+
31
+ func (l glogger ) clone () glogger {
32
+ return glogger {
33
+ level : l .level ,
34
+ prefix : l .prefix ,
35
+ values : copySlice (l .values ),
36
+ }
24
37
}
25
38
26
- func prepend (prefix interface {}, args []interface {}) []interface {} {
27
- return append ([]interface {}{prefix }, args ... )
39
+ func copySlice (in []interface {}) []interface {} {
40
+ out := make ([]interface {}, len (in ))
41
+ copy (out , in )
42
+ return out
28
43
}
29
44
30
45
// Magic string for intermediate frames that we should ignore.
@@ -44,42 +59,93 @@ func framesToCaller() int {
44
59
return 1 // something went wrong, this is safe
45
60
}
46
61
47
- func (l glogger ) Info (args ... interface {}) {
48
- if l .Enabled () {
49
- glog .InfoDepth (framesToCaller (), prepend (l .prefix , args )... )
62
+ type kvPair struct {
63
+ key string
64
+ val interface {}
65
+ }
66
+
67
+ func flatten (kvList ... interface {}) string {
68
+ keys := make ([]string , 0 , len (kvList ))
69
+ vals := make (map [string ]interface {}, len (kvList ))
70
+ for i := 0 ; i < len (kvList ); i += 2 {
71
+ k , ok := kvList [i ].(string )
72
+ if ! ok {
73
+ panic (fmt .Sprintf ("key is not a string: %s" , pretty (kvList [i ])))
74
+ }
75
+ var v interface {}
76
+ if i + 1 < len (kvList ) {
77
+ v = kvList [i + 1 ]
78
+ }
79
+ keys = append (keys , k )
80
+ vals [k ] = v
50
81
}
82
+ sort .Strings (keys )
83
+ buf := bytes.Buffer {}
84
+ for i , k := range keys {
85
+ v := vals [k ]
86
+ if i > 0 {
87
+ buf .WriteRune (' ' )
88
+ }
89
+ buf .WriteString (pretty (k ))
90
+ buf .WriteString ("=" )
91
+ buf .WriteString (pretty (v ))
92
+ }
93
+ return buf .String ()
94
+ }
95
+
96
+ func pretty (value interface {}) string {
97
+ jb , _ := json .Marshal (value )
98
+ return string (jb )
51
99
}
52
100
53
- func (l glogger ) Infof ( format string , args ... interface {}) {
101
+ func (l glogger ) Info ( msg string , kvList ... interface {}) {
54
102
if l .Enabled () {
55
- glog .InfoDepth (framesToCaller (), fmt .Sprintf ("%s" + format , prepend (l .prefix , args )... ))
103
+ lvlStr := flatten ("level" , l .level )
104
+ msgStr := flatten ("msg" , msg )
105
+ fixedStr := flatten (l .values ... )
106
+ userStr := flatten (kvList ... )
107
+ glog .InfoDepth (framesToCaller (), l .prefix , " " , lvlStr , " " , msgStr , " " , fixedStr , " " , userStr )
56
108
}
57
109
}
58
110
59
111
func (l glogger ) Enabled () bool {
60
112
return bool (glog .V (glog .Level (l .level )))
61
113
}
62
114
63
- func (l glogger ) Error (args ... interface {}) {
64
- glog .ErrorDepth (framesToCaller (), prepend (l .prefix , args )... )
115
+ func (l glogger ) Error (err error , msg string , kvList ... interface {}) {
116
+ msgStr := flatten ("msg" , msg )
117
+ var loggableErr interface {}
118
+ if err != nil {
119
+ loggableErr = err .Error ()
120
+ }
121
+ errStr := flatten ("error" , loggableErr )
122
+ fixedStr := flatten (l .values ... )
123
+ userStr := flatten (kvList ... )
124
+ glog .ErrorDepth (framesToCaller (), l .prefix , " " , msgStr , " " , errStr , " " , fixedStr , " " , userStr )
65
125
}
66
126
67
- func (l glogger ) Errorf (format string , args ... interface {}) {
68
- glog .ErrorDepth (framesToCaller (), fmt .Sprintf ("%s" + format , prepend (l .prefix , args )... ))
127
+ func (l glogger ) V (level int ) logr.InfoLogger {
128
+ new := l .clone ()
129
+ new .level = level
130
+ return new
69
131
}
70
132
71
- func (l glogger ) V (level int ) logr.InfoLogger {
72
- return glogger {
73
- level : level ,
74
- prefix : l .prefix ,
133
+ // WithName returns a new logr.Logger with the specified name appended. glogr
134
+ // uses '/' characters to separate name elements. Callers should not pass '/'
135
+ // in the provided name string, but this library does not actually enforce that.
136
+ func (l glogger ) WithName (name string ) logr.Logger {
137
+ new := l .clone ()
138
+ if len (l .prefix ) > 0 {
139
+ new .prefix = l .prefix + "/"
75
140
}
141
+ new .prefix += name
142
+ return new
76
143
}
77
144
78
- func (l glogger ) NewWithPrefix (prefix string ) logr.Logger {
79
- return glogger {
80
- level : l .level ,
81
- prefix : prefix ,
82
- }
145
+ func (l glogger ) WithValues (kvList ... interface {}) logr.Logger {
146
+ new := l .clone ()
147
+ new .values = append (new .values , kvList ... )
148
+ return new
83
149
}
84
150
85
151
var _ logr.Logger = glogger {}
0 commit comments