forked from danielgtaylor/openapi-cli-generator
-
Notifications
You must be signed in to change notification settings - Fork 4
/
log.go
139 lines (130 loc) · 2.92 KB
/
log.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
package cli
import (
"bytes"
"encoding/json"
"fmt"
"io"
"path"
"sort"
"strconv"
"strings"
"sync"
"github.com/rs/zerolog"
)
var (
// These colors match those in formatter.go
cReset = 0
cLightGray = 247
cBlue = 74
cOrange = 172
cRed = 204
cGreen = 150
cPurple = 98
cYellow = 222
)
var consoleBufPool = sync.Pool{
New: func() interface{} {
return bytes.NewBuffer(make([]byte, 0, 100))
},
}
// ConsoleWriter reads a JSON object per write operation and outputs an
// optionally colored human readable version on the Out writer.
// This has been modified from the ConsoleWriter that ships with zerolog.
type ConsoleWriter struct {
Out io.Writer
NoColor bool
}
func (w ConsoleWriter) Write(p []byte) (n int, err error) {
var event map[string]interface{}
d := json.NewDecoder(bytes.NewReader(p))
d.UseNumber()
err = d.Decode(&event)
if err != nil {
return
}
buf := consoleBufPool.Get().(*bytes.Buffer)
defer consoleBufPool.Put(buf)
lvlColor := cReset
level := "????"
if l, ok := event[zerolog.LevelFieldName].(string); ok {
if !w.NoColor {
lvlColor = levelColor(l)
}
level = strings.ToUpper(l)
}
fmt.Fprintf(buf, "%s %s %s",
colorize(level, lvlColor, !w.NoColor),
colorize(path.Base(event[zerolog.CallerFieldName].(string)), cReset, !w.NoColor),
colorize(event[zerolog.MessageFieldName], cReset, !w.NoColor))
fields := make([]string, 0, len(event))
errorField := ""
for field := range event {
switch field {
case zerolog.LevelFieldName, zerolog.TimestampFieldName, zerolog.MessageFieldName, zerolog.CallerFieldName:
continue
case "error":
errorField = fmt.Sprintf("%v\n", event[field])
continue
}
fields = append(fields, field)
}
sort.Strings(fields)
for _, field := range fields {
fmt.Fprintf(buf, " %s=", colorize(field, lvlColor, !w.NoColor))
switch value := event[field].(type) {
case string:
if needsQuote(value) {
buf.WriteString(strconv.Quote(value))
} else {
buf.WriteString(value)
}
case json.Number:
fmt.Fprint(buf, value)
default:
b, err := json.Marshal(value)
if err != nil {
fmt.Fprintf(buf, "[error: %v]", err)
} else {
fmt.Fprint(buf, string(b))
}
}
}
buf.WriteByte('\n')
if errorField != "" {
buf.Write([]byte(errorField))
}
buf.WriteTo(w.Out)
n = len(p)
return
}
func colorize(s interface{}, color int, enabled bool) string {
if !enabled {
return fmt.Sprintf("%v", s)
}
if color == 0 {
return fmt.Sprintf("\x1b[%dm%v\x1b[0m", color, s)
}
return fmt.Sprintf("\x1b[38;5;%dm%v\x1b[0m", color, s)
}
func levelColor(level string) int {
switch level {
case "debug":
return cLightGray
case "info":
return cGreen
case "warn":
return cOrange
case "error", "fatal", "panic":
return cRed
default:
return cReset
}
}
func needsQuote(s string) bool {
for i := range s {
if s[i] < 0x20 || s[i] > 0x7e || s[i] == ' ' || s[i] == '\\' || s[i] == '"' {
return true
}
}
return false
}