@@ -86,6 +86,7 @@ type TerminalStringer interface {
8686// [DBUG] [May 16 20:58:45] remove route ns=haproxy addr=127.0.0.1:50002
8787func TerminalFormat (usecolor bool ) Format {
8888 return FormatFunc (func (r * Record ) []byte {
89+ msg := escapeMessage (r .Msg )
8990 var color = 0
9091 if usecolor {
9192 switch r .Lvl {
@@ -122,19 +123,19 @@ func TerminalFormat(usecolor bool) Format {
122123
123124 // Assemble and print the log heading
124125 if color > 0 {
125- fmt .Fprintf (b , "\x1b [%dm%s\x1b [0m[%s|%s]%s %s " , color , lvl , r .Time .Format (termTimeFormat ), location , padding , r . Msg )
126+ fmt .Fprintf (b , "\x1b [%dm%s\x1b [0m[%s|%s]%s %s " , color , lvl , r .Time .Format (termTimeFormat ), location , padding , msg )
126127 } else {
127- fmt .Fprintf (b , "%s[%s|%s]%s %s " , lvl , r .Time .Format (termTimeFormat ), location , padding , r . Msg )
128+ fmt .Fprintf (b , "%s[%s|%s]%s %s " , lvl , r .Time .Format (termTimeFormat ), location , padding , msg )
128129 }
129130 } else {
130131 if color > 0 {
131- fmt .Fprintf (b , "\x1b [%dm%s\x1b [0m[%s] %s " , color , lvl , r .Time .Format (termTimeFormat ), r . Msg )
132+ fmt .Fprintf (b , "\x1b [%dm%s\x1b [0m[%s] %s " , color , lvl , r .Time .Format (termTimeFormat ), msg )
132133 } else {
133- fmt .Fprintf (b , "%s[%s] %s " , lvl , r .Time .Format (termTimeFormat ), r . Msg )
134+ fmt .Fprintf (b , "%s[%s] %s " , lvl , r .Time .Format (termTimeFormat ), msg )
134135 }
135136 }
136137 // try to justify the log output for short messages
137- length := utf8 .RuneCountInString (r . Msg )
138+ length := utf8 .RuneCountInString (msg )
138139 if len (r .Ctx ) > 0 && length < termMsgJust {
139140 b .Write (bytes .Repeat ([]byte {' ' }, termMsgJust - length ))
140141 }
@@ -167,6 +168,8 @@ func logfmt(buf *bytes.Buffer, ctx []interface{}, color int, term bool) {
167168 v := formatLogfmtValue (ctx [i + 1 ], term )
168169 if ! ok {
169170 k , v = errorKey , formatLogfmtValue (k , term )
171+ } else {
172+ k = escapeString (k )
170173 }
171174
172175 // XXX: we should probably check that all of your key bytes aren't invalid
@@ -471,7 +474,7 @@ func formatLogfmtBigInt(n *big.Int) string {
471474func escapeString (s string ) string {
472475 needsQuoting := false
473476 for _ , r := range s {
474- // We quote everything below " (0x34 ) and above~ (0x7E), plus equal-sign
477+ // We quote everything below " (0x22 ) and above~ (0x7E), plus equal-sign
475478 if r <= '"' || r > '~' || r == '=' {
476479 needsQuoting = true
477480 break
@@ -482,3 +485,26 @@ func escapeString(s string) string {
482485 }
483486 return strconv .Quote (s )
484487}
488+
489+ // escapeMessage checks if the provided string needs escaping/quoting, similarly
490+ // to escapeString. The difference is that this method is more lenient: it allows
491+ // for spaces and linebreaks to occur without needing quoting.
492+ func escapeMessage (s string ) string {
493+ needsQuoting := false
494+ for _ , r := range s {
495+ // Carriage return and Line feed are ok
496+ if r == 0xa || r == 0xd {
497+ continue
498+ }
499+ // We quote everything below <space> (0x20) and above~ (0x7E),
500+ // plus equal-sign
501+ if r < ' ' || r > '~' || r == '=' {
502+ needsQuoting = true
503+ break
504+ }
505+ }
506+ if ! needsQuoting {
507+ return s
508+ }
509+ return strconv .Quote (s )
510+ }
0 commit comments