|
|
@ -86,6 +86,7 @@ type TerminalStringer interface { |
|
|
|
// [DBUG] [May 16 20:58:45] remove route ns=haproxy addr=127.0.0.1:50002
|
|
|
|
// [DBUG] [May 16 20:58:45] remove route ns=haproxy addr=127.0.0.1:50002
|
|
|
|
func TerminalFormat(usecolor bool) Format { |
|
|
|
func TerminalFormat(usecolor bool) Format { |
|
|
|
return FormatFunc(func(r *Record) []byte { |
|
|
|
return FormatFunc(func(r *Record) []byte { |
|
|
|
|
|
|
|
msg := escapeMessage(r.Msg) |
|
|
|
var color = 0 |
|
|
|
var color = 0 |
|
|
|
if usecolor { |
|
|
|
if usecolor { |
|
|
|
switch r.Lvl { |
|
|
|
switch r.Lvl { |
|
|
@ -122,19 +123,19 @@ func TerminalFormat(usecolor bool) Format { |
|
|
|
|
|
|
|
|
|
|
|
// Assemble and print the log heading
|
|
|
|
// Assemble and print the log heading
|
|
|
|
if color > 0 { |
|
|
|
if color > 0 { |
|
|
|
fmt.Fprintf(b, "\x1b[%dm%s\x1b[0m[%s|%s]%s %s ", color, lvl, r.Time.Format(termTimeFormat), location, padding, r.Msg) |
|
|
|
fmt.Fprintf(b, "\x1b[%dm%s\x1b[0m[%s|%s]%s %s ", color, lvl, r.Time.Format(termTimeFormat), location, padding, msg) |
|
|
|
} else { |
|
|
|
} else { |
|
|
|
fmt.Fprintf(b, "%s[%s|%s]%s %s ", lvl, r.Time.Format(termTimeFormat), location, padding, r.Msg) |
|
|
|
fmt.Fprintf(b, "%s[%s|%s]%s %s ", lvl, r.Time.Format(termTimeFormat), location, padding, msg) |
|
|
|
} |
|
|
|
} |
|
|
|
} else { |
|
|
|
} else { |
|
|
|
if color > 0 { |
|
|
|
if color > 0 { |
|
|
|
fmt.Fprintf(b, "\x1b[%dm%s\x1b[0m[%s] %s ", color, lvl, r.Time.Format(termTimeFormat), r.Msg) |
|
|
|
fmt.Fprintf(b, "\x1b[%dm%s\x1b[0m[%s] %s ", color, lvl, r.Time.Format(termTimeFormat), msg) |
|
|
|
} else { |
|
|
|
} else { |
|
|
|
fmt.Fprintf(b, "%s[%s] %s ", lvl, r.Time.Format(termTimeFormat), r.Msg) |
|
|
|
fmt.Fprintf(b, "%s[%s] %s ", lvl, r.Time.Format(termTimeFormat), msg) |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
// try to justify the log output for short messages
|
|
|
|
// try to justify the log output for short messages
|
|
|
|
length := utf8.RuneCountInString(r.Msg) |
|
|
|
length := utf8.RuneCountInString(msg) |
|
|
|
if len(r.Ctx) > 0 && length < termMsgJust { |
|
|
|
if len(r.Ctx) > 0 && length < termMsgJust { |
|
|
|
b.Write(bytes.Repeat([]byte{' '}, termMsgJust-length)) |
|
|
|
b.Write(bytes.Repeat([]byte{' '}, termMsgJust-length)) |
|
|
|
} |
|
|
|
} |
|
|
@ -167,6 +168,8 @@ func logfmt(buf *bytes.Buffer, ctx []interface{}, color int, term bool) { |
|
|
|
v := formatLogfmtValue(ctx[i+1], term) |
|
|
|
v := formatLogfmtValue(ctx[i+1], term) |
|
|
|
if !ok { |
|
|
|
if !ok { |
|
|
|
k, v = errorKey, formatLogfmtValue(k, term) |
|
|
|
k, v = errorKey, formatLogfmtValue(k, term) |
|
|
|
|
|
|
|
} else { |
|
|
|
|
|
|
|
k = escapeString(k) |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// XXX: we should probably check that all of your key bytes aren't invalid
|
|
|
|
// XXX: we should probably check that all of your key bytes aren't invalid
|
|
|
@ -471,7 +474,7 @@ func formatLogfmtBigInt(n *big.Int) string { |
|
|
|
func escapeString(s string) string { |
|
|
|
func escapeString(s string) string { |
|
|
|
needsQuoting := false |
|
|
|
needsQuoting := false |
|
|
|
for _, r := range s { |
|
|
|
for _, r := range s { |
|
|
|
// We quote everything below " (0x34) and above~ (0x7E), plus equal-sign
|
|
|
|
// We quote everything below " (0x22) and above~ (0x7E), plus equal-sign
|
|
|
|
if r <= '"' || r > '~' || r == '=' { |
|
|
|
if r <= '"' || r > '~' || r == '=' { |
|
|
|
needsQuoting = true |
|
|
|
needsQuoting = true |
|
|
|
break |
|
|
|
break |
|
|
@ -482,3 +485,26 @@ func escapeString(s string) string { |
|
|
|
} |
|
|
|
} |
|
|
|
return strconv.Quote(s) |
|
|
|
return strconv.Quote(s) |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// escapeMessage checks if the provided string needs escaping/quoting, similarly
|
|
|
|
|
|
|
|
// to escapeString. The difference is that this method is more lenient: it allows
|
|
|
|
|
|
|
|
// for spaces and linebreaks to occur without needing quoting.
|
|
|
|
|
|
|
|
func escapeMessage(s string) string { |
|
|
|
|
|
|
|
needsQuoting := false |
|
|
|
|
|
|
|
for _, r := range s { |
|
|
|
|
|
|
|
// Carriage return and Line feed are ok
|
|
|
|
|
|
|
|
if r == 0xa || r == 0xd { |
|
|
|
|
|
|
|
continue |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
// We quote everything below <space> (0x20) and above~ (0x7E),
|
|
|
|
|
|
|
|
// plus equal-sign
|
|
|
|
|
|
|
|
if r < ' ' || r > '~' || r == '=' { |
|
|
|
|
|
|
|
needsQuoting = true |
|
|
|
|
|
|
|
break |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
if !needsQuoting { |
|
|
|
|
|
|
|
return s |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
return strconv.Quote(s) |
|
|
|
|
|
|
|
} |
|
|
|