diff --git a/klog.go b/klog.go index 907b44cf..3ee606c6 100644 --- a/klog.go +++ b/klog.go @@ -849,9 +849,17 @@ func kvListFormat(b *bytes.Buffer, keysAndValues ...interface{}) { case error: writeStringValue(b, true, v.Error()) case []byte: - // We cannot use the simpler strconv.Quote here - // because it does not escape unicode characters, which is - // expected by one test!? + // In https://github.com/kubernetes/klog/pull/237 it was decided + // to format byte slices with "%+q". The advantages of that are: + // - readable output if the bytes happen to be printable + // - non-printable bytes get represented as unicode escape + // sequences (\uxxxx) + // + // The downsides are that we cannot use the faster + // strconv.Quote here and that multi-line output is not + // supported. If developers know that a byte array is + // printable and they want multi-line output, they can + // convert the value to string before logging it. b.WriteByte('=') b.WriteString(fmt.Sprintf("%+q", v)) default: @@ -875,7 +883,21 @@ func writeStringValue(b *bytes.Buffer, quote bool, v string) { return } - // Complex multi-line string, show as-is with indention. + // Complex multi-line string, show as-is with indention like this: + // I... "hello world" key>>> + // line 1 + // line 2 + // <<< + // + // Tabs indent the lines of the value while the end of string delimiter + // is indented with a space. That has two purposes: + // - visual difference between the two for a human reader because indention + // will be different + // - no ambiguity when some value line starts with the end delimiter + // + // One downside is that the output cannot distinguish between strings that + // end with a line break and those that don't because the end delimiter + // will always be on the next line. b.WriteString(">>>\n") for index != -1 { b.WriteByte('\t')