Skip to content

Commit 6b21701

Browse files
committed
Merge remote-tracking branch 'rs/master' into daver/merge-remote
2 parents 22af876 + 417580d commit 6b21701

26 files changed

+765
-82
lines changed

.github/workflows/test.yml

+1-1
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ jobs:
1313
with:
1414
go-version: ${{ matrix.go-version }}
1515
- name: Checkout code
16-
uses: actions/checkout@v3
16+
uses: actions/checkout@v4
1717
- uses: actions/cache@v3
1818
with:
1919
path: ~/go/pkg/mod

README.md

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
# Zero Allocation JSON Logger
22

3-
[![godoc](http://img.shields.io/badge/godoc-reference-blue.svg?style=flat)](https://godoc.org/github.com/rs/zerolog) [![license](http://img.shields.io/badge/license-MIT-red.svg?style=flat)](https://raw.githubusercontent.com/rs/zerolog/master/LICENSE) [![Build Status](https://travis-ci.org/rs/zerolog.svg?branch=master)](https://travis-ci.org/rs/zerolog) [![Go Coverage](https://github.com/rs/zerolog/wiki/coverage.svg)](https://raw.githack.com/wiki/rs/zerolog/coverage.html)
3+
[![godoc](http://img.shields.io/badge/godoc-reference-blue.svg?style=flat)](https://godoc.org/github.com/rs/zerolog) [![license](http://img.shields.io/badge/license-MIT-red.svg?style=flat)](https://raw.githubusercontent.com/rs/zerolog/master/LICENSE) [![Build Status](https://github.com/rs/zerolog/actions/workflows/test.yml/badge.svg)](https://github.com/rs/zerolog/actions/workflows/test.yml) [![Go Coverage](https://github.com/rs/zerolog/wiki/coverage.svg)](https://raw.githack.com/wiki/rs/zerolog/coverage.html)
44

55
The zerolog package provides a fast and simple logger dedicated to JSON output.
66

@@ -547,7 +547,7 @@ and facilitates the unification of logging and tracing in some systems:
547547
type TracingHook struct{}
548548

549549
func (h TracingHook) Run(e *zerolog.Event, level zerolog.Level, msg string) {
550-
ctx := e.Ctx()
550+
ctx := e.GetCtx()
551551
spanId := getSpanIdFromContext(ctx) // as per your tracing framework
552552
e.Str("span-id", spanId)
553553
}

benchmark_test.go

+10-10
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ package zerolog
33
import (
44
"context"
55
"errors"
6-
"io/ioutil"
6+
"io"
77
"net"
88
"testing"
99
"time"
@@ -15,7 +15,7 @@ var (
1515
)
1616

1717
func BenchmarkLogEmpty(b *testing.B) {
18-
logger := New(ioutil.Discard)
18+
logger := New(io.Discard)
1919
b.ResetTimer()
2020
b.RunParallel(func(pb *testing.PB) {
2121
for pb.Next() {
@@ -25,7 +25,7 @@ func BenchmarkLogEmpty(b *testing.B) {
2525
}
2626

2727
func BenchmarkDisabled(b *testing.B) {
28-
logger := New(ioutil.Discard).Level(Disabled)
28+
logger := New(io.Discard).Level(Disabled)
2929
b.ResetTimer()
3030
b.RunParallel(func(pb *testing.PB) {
3131
for pb.Next() {
@@ -35,7 +35,7 @@ func BenchmarkDisabled(b *testing.B) {
3535
}
3636

3737
func BenchmarkInfo(b *testing.B) {
38-
logger := New(ioutil.Discard)
38+
logger := New(io.Discard)
3939
b.ResetTimer()
4040
b.RunParallel(func(pb *testing.PB) {
4141
for pb.Next() {
@@ -45,7 +45,7 @@ func BenchmarkInfo(b *testing.B) {
4545
}
4646

4747
func BenchmarkContextFields(b *testing.B) {
48-
logger := New(ioutil.Discard).With().
48+
logger := New(io.Discard).With().
4949
Str("string", "four!").
5050
Time("time", time.Time{}).
5151
Int("int", 123).
@@ -60,7 +60,7 @@ func BenchmarkContextFields(b *testing.B) {
6060
}
6161

6262
func BenchmarkContextAppend(b *testing.B) {
63-
logger := New(ioutil.Discard).With().
63+
logger := New(io.Discard).With().
6464
Str("foo", "bar").
6565
Logger()
6666
b.ResetTimer()
@@ -72,7 +72,7 @@ func BenchmarkContextAppend(b *testing.B) {
7272
}
7373

7474
func BenchmarkLogFields(b *testing.B) {
75-
logger := New(ioutil.Discard)
75+
logger := New(io.Discard)
7676
b.ResetTimer()
7777
b.RunParallel(func(pb *testing.PB) {
7878
for pb.Next() {
@@ -102,7 +102,7 @@ func BenchmarkLogArrayObject(b *testing.B) {
102102
obj1 := obj{"a", "b", 2}
103103
obj2 := obj{"c", "d", 3}
104104
obj3 := obj{"e", "f", 4}
105-
logger := New(ioutil.Discard)
105+
logger := New(io.Discard)
106106
b.ResetTimer()
107107
b.ReportAllocs()
108108
for i := 0; i < b.N; i++ {
@@ -224,7 +224,7 @@ func BenchmarkLogFieldType(b *testing.B) {
224224
return e.Object("k", objects[0])
225225
},
226226
}
227-
logger := New(ioutil.Discard)
227+
logger := New(io.Discard)
228228
b.ResetTimer()
229229
for name := range types {
230230
f := types[name]
@@ -358,7 +358,7 @@ func BenchmarkContextFieldType(b *testing.B) {
358358
return c.Timestamp()
359359
},
360360
}
361-
logger := New(ioutil.Discard)
361+
logger := New(io.Discard)
362362
b.ResetTimer()
363363
for name := range types {
364364
f := types[name]

binary_test.go

-1
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@ import (
77
"errors"
88
"fmt"
99

10-
// "io/ioutil"
1110
stdlog "log"
1211
"time"
1312
)

cmd/prettylog/prettylog.go

+34-6
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
package main
22

33
import (
4+
"bufio"
5+
"errors"
46
"fmt"
57
"io"
68
"os"
@@ -14,13 +16,39 @@ func isInputFromPipe() bool {
1416
}
1517

1618
func main() {
17-
if !isInputFromPipe() {
18-
fmt.Println("The command is intended to work with pipes.")
19-
fmt.Println("Usage: app_with_zerolog | 2> >(prettylog)")
19+
writer := zerolog.NewConsoleWriter()
20+
21+
if isInputFromPipe() {
22+
_, _ = io.Copy(writer, os.Stdin)
23+
} else if len(os.Args) > 1 {
24+
for _, filename := range os.Args[1:] {
25+
// Scan each line from filename and write it into writer
26+
r, err := os.Open(filename)
27+
if err != nil {
28+
fmt.Printf("%s open: %v", filename, err)
29+
os.Exit(1)
30+
}
31+
scanner := bufio.NewScanner(r)
32+
for scanner.Scan() {
33+
_, err = writer.Write(scanner.Bytes())
34+
if err != nil {
35+
if errors.Is(err, io.EOF) {
36+
break
37+
}
38+
fmt.Printf("%s write: %v", filename, err)
39+
os.Exit(1)
40+
}
41+
}
42+
if err := scanner.Err(); err != nil {
43+
fmt.Printf("%s scan: %v", filename, err)
44+
os.Exit(1)
45+
}
46+
}
47+
} else {
48+
fmt.Println("Usage:")
49+
fmt.Println(" app_with_zerolog | 2> >(prettylog)")
50+
fmt.Println(" prettylog zerolog_output.jsonl")
2051
os.Exit(1)
2152
return
2253
}
23-
24-
writer := zerolog.NewConsoleWriter()
25-
_, _ = io.Copy(writer, os.Stdin)
2654
}

console.go

+35-25
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,8 @@ type ConsoleWriter struct {
7676
FormatErrFieldValue Formatter
7777

7878
FormatExtra func(map[string]interface{}, *bytes.Buffer) error
79+
80+
FormatPrepare func(map[string]interface{}) error
7981
}
8082

8183
// NewConsoleWriter creates and initializes a new ConsoleWriter.
@@ -124,6 +126,13 @@ func (w ConsoleWriter) Write(p []byte) (n int, err error) {
124126
return n, fmt.Errorf("cannot decode event: %s", err)
125127
}
126128

129+
if w.FormatPrepare != nil {
130+
err = w.FormatPrepare(evt)
131+
if err != nil {
132+
return n, err
133+
}
134+
}
135+
127136
for _, p := range w.PartsOrder {
128137
w.writePart(buf, evt, p)
129138
}
@@ -272,7 +281,7 @@ func (w ConsoleWriter) writePart(buf *bytes.Buffer, evt map[string]interface{},
272281
}
273282
case MessageFieldName:
274283
if w.FormatMessage == nil {
275-
f = consoleDefaultFormatMessage
284+
f = consoleDefaultFormatMessage(w.NoColor, evt[LevelFieldName])
276285
} else {
277286
f = w.FormatMessage
278287
}
@@ -310,8 +319,13 @@ func needsQuote(s string) bool {
310319
return false
311320
}
312321

313-
// colorize returns the string s wrapped in ANSI code c, unless disabled is true.
322+
// colorize returns the string s wrapped in ANSI code c, unless disabled is true or c is 0.
314323
func colorize(s interface{}, c int, disabled bool) string {
324+
e := os.Getenv("NO_COLOR")
325+
if e != "" || c == 0 {
326+
disabled = true
327+
}
328+
315329
if disabled {
316330
return fmt.Sprintf("%s", s)
317331
}
@@ -373,27 +387,16 @@ func consoleDefaultFormatLevel(noColor bool) Formatter {
373387
return func(i interface{}) string {
374388
var l string
375389
if ll, ok := i.(string); ok {
376-
switch ll {
377-
case LevelTraceValue:
378-
l = colorize("TRC", colorMagenta, noColor)
379-
case LevelDebugValue:
380-
l = colorize("DBG", colorYellow, noColor)
381-
case LevelInfoValue:
382-
l = colorize("INF", colorGreen, noColor)
383-
case LevelWarnValue:
384-
l = colorize("WRN", colorRed, noColor)
385-
case LevelErrorValue:
386-
l = colorize(colorize("ERR", colorRed, noColor), colorBold, noColor)
387-
case LevelFatalValue:
388-
l = colorize(colorize("FTL", colorRed, noColor), colorBold, noColor)
389-
case LevelPanicValue:
390-
l = colorize(colorize("PNC", colorRed, noColor), colorBold, noColor)
391-
default:
392-
l = colorize(ll, colorBold, noColor)
390+
level, _ := ParseLevel(ll)
391+
fl, ok := FormattedLevels[level]
392+
if ok {
393+
l = colorize(fl, LevelColors[level], noColor)
394+
} else {
395+
l = strings.ToUpper(ll)[0:3]
393396
}
394397
} else {
395398
if i == nil {
396-
l = colorize("???", colorBold, noColor)
399+
l = "???"
397400
} else {
398401
l = strings.ToUpper(fmt.Sprintf("%s", i))[0:3]
399402
}
@@ -420,11 +423,18 @@ func consoleDefaultFormatCaller(noColor bool) Formatter {
420423
}
421424
}
422425

423-
func consoleDefaultFormatMessage(i interface{}) string {
424-
if i == nil {
425-
return ""
426+
func consoleDefaultFormatMessage(noColor bool, level interface{}) Formatter {
427+
return func(i interface{}) string {
428+
if i == nil || i == "" {
429+
return ""
430+
}
431+
switch level {
432+
case LevelInfoValue, LevelWarnValue, LevelErrorValue, LevelFatalValue, LevelPanicValue:
433+
return colorize(fmt.Sprintf("%s", i), colorBold, noColor)
434+
default:
435+
return fmt.Sprintf("%s", i)
436+
}
426437
}
427-
return fmt.Sprintf("%s", i)
428438
}
429439

430440
func consoleDefaultFormatFieldName(noColor bool) Formatter {
@@ -445,6 +455,6 @@ func consoleDefaultFormatErrFieldName(noColor bool) Formatter {
445455

446456
func consoleDefaultFormatErrFieldValue(noColor bool) Formatter {
447457
return func(i interface{}) string {
448-
return colorize(fmt.Sprintf("%s", i), colorRed, noColor)
458+
return colorize(colorize(fmt.Sprintf("%s", i), colorBold, noColor), colorRed, noColor)
449459
}
450460
}

console_test.go

+46-4
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ package zerolog_test
33
import (
44
"bytes"
55
"fmt"
6-
"io/ioutil"
6+
"io"
77
"os"
88
"strings"
99
"testing"
@@ -97,13 +97,32 @@ func TestConsoleWriter(t *testing.T) {
9797
t.Errorf("Unexpected error when writing output: %s", err)
9898
}
9999

100-
expectedOutput := "\x1b[90m<nil>\x1b[0m \x1b[31mWRN\x1b[0m Foobar\n"
100+
expectedOutput := "\x1b[90m<nil>\x1b[0m \x1b[33mWRN\x1b[0m \x1b[1mFoobar\x1b[0m\n"
101101
actualOutput := buf.String()
102102
if actualOutput != expectedOutput {
103103
t.Errorf("Unexpected output %q, want: %q", actualOutput, expectedOutput)
104104
}
105105
})
106106

107+
t.Run("NO_COLOR = true", func(t *testing.T) {
108+
os.Setenv("NO_COLOR", "anything")
109+
110+
buf := &bytes.Buffer{}
111+
w := zerolog.ConsoleWriter{Out: buf}
112+
113+
_, err := w.Write([]byte(`{"level": "warn", "message": "Foobar"}`))
114+
if err != nil {
115+
t.Errorf("Unexpected error when writing output: %s", err)
116+
}
117+
118+
expectedOutput := "<nil> WRN Foobar\n"
119+
actualOutput := buf.String()
120+
if actualOutput != expectedOutput {
121+
t.Errorf("Unexpected output %q, want: %q", actualOutput, expectedOutput)
122+
}
123+
os.Unsetenv("NO_COLOR")
124+
})
125+
107126
t.Run("Write fields", func(t *testing.T) {
108127
buf := &bytes.Buffer{}
109128
w := zerolog.ConsoleWriter{Out: buf, NoColor: true}
@@ -229,7 +248,7 @@ func TestConsoleWriter(t *testing.T) {
229248
t.Errorf("Unexpected error when writing output: %s", err)
230249
}
231250

232-
expectedOutput := "\x1b[90m<nil>\x1b[0m \x1b[31mWRN\x1b[0m Foobar \x1b[36mfoo=\x1b[0mbar\n"
251+
expectedOutput := "\x1b[90m<nil>\x1b[0m \x1b[33mWRN\x1b[0m \x1b[1mFoobar\x1b[0m \x1b[36mfoo=\x1b[0mbar\n"
233252
actualOutput := buf.String()
234253
if actualOutput != expectedOutput {
235254
t.Errorf("Unexpected output %q, want: %q", actualOutput, expectedOutput)
@@ -399,6 +418,29 @@ func TestConsoleWriterConfiguration(t *testing.T) {
399418
}
400419
})
401420

421+
t.Run("Sets FormatPrepare", func(t *testing.T) {
422+
buf := &bytes.Buffer{}
423+
w := zerolog.ConsoleWriter{
424+
Out: buf, NoColor: true, PartsOrder: []string{"level", "message"},
425+
FormatPrepare: func(evt map[string]interface{}) error {
426+
evt["message"] = fmt.Sprintf("msg=%s", evt["message"])
427+
return nil
428+
},
429+
}
430+
431+
evt := `{"level": "info", "message": "Foobar"}`
432+
_, err := w.Write([]byte(evt))
433+
if err != nil {
434+
t.Errorf("Unexpected error when writing output: %s", err)
435+
}
436+
437+
expectedOutput := "INF msg=Foobar\n"
438+
actualOutput := buf.String()
439+
if actualOutput != expectedOutput {
440+
t.Errorf("Unexpected output %q, want: %q", actualOutput, expectedOutput)
441+
}
442+
})
443+
402444
t.Run("Uses local time for console writer without time zone", func(t *testing.T) {
403445
// Regression test for issue #483 (check there for more details)
404446

@@ -432,7 +474,7 @@ func BenchmarkConsoleWriter(b *testing.B) {
432474

433475
var msg = []byte(`{"level": "info", "foo": "bar", "message": "HELLO", "time": "1990-01-01"}`)
434476

435-
w := zerolog.ConsoleWriter{Out: ioutil.Discard, NoColor: false}
477+
w := zerolog.ConsoleWriter{Out: io.Discard, NoColor: false}
436478

437479
for i := 0; i < b.N; i++ {
438480
w.Write(msg)

0 commit comments

Comments
 (0)