Repository: rs/zerolog
Pull request #599 (2023-10-14 18:48:39)

Use map for formatted levels
Sorry, I realized there could be few more improvements in code here:
* Use map for formatted levels. So only one place to parse levels.
* No bold for no level case as well.


Patch:
diff --git a/console.go b/console.go
index 921e4b3..e8eeaa3 100644
--- a/console.go
+++ b/console.go
@@ -387,27 +387,16 @@ func consoleDefaultFormatLevel(noColor bool) Formatter {
 	return func(i interface{}) string {
 		var l string
 		if ll, ok := i.(string); ok {
-			switch ll {
-			case LevelTraceValue:
-				l = colorize("TRC", LevelColors["TRC"], noColor)
-			case LevelDebugValue:
-				l = colorize("DBG", LevelColors["DBG"], noColor)
-			case LevelInfoValue:
-				l = colorize("INF", LevelColors["INF"], noColor)
-			case LevelWarnValue:
-				l = colorize("WRN", LevelColors["WRN"], noColor)
-			case LevelErrorValue:
-				l = colorize("ERR", LevelColors["ERR"], noColor)
-			case LevelFatalValue:
-				l = colorize("FTL", LevelColors["FTL"], noColor)
-			case LevelPanicValue:
-				l = colorize("PNC", LevelColors["PNC"], noColor)
-			default:
+			level, _ := ParseLevel(ll)
+			fl, ok := FormattedLevels[level]
+			if ok {
+				l = colorize(fl, LevelColors[level], noColor)
+			} else {
 				l = strings.ToUpper(ll)[0:3]
 			}
 		} else {
 			if i == nil {
-				l = colorize("???", colorBold, noColor)
+				l = "???"
 			} else {
 				l = strings.ToUpper(fmt.Sprintf("%s", i))[0:3]
 			}
diff --git a/globals.go b/globals.go
index 7e5ca25..bf9e3da 100644
--- a/globals.go
+++ b/globals.go
@@ -111,14 +111,26 @@ var (
 
 	// LevelColors are used by ConsoleWriter's consoleDefaultFormatLevel to color
 	// log levels.
-	LevelColors = map[string]int{
-		"TRC": colorBlue,
-		"DBG": 0,
-		"INF": colorGreen,
-		"WRN": colorYellow,
-		"ERR": colorRed,
-		"FTL": colorRed,
-		"PNC": colorRed,
+	LevelColors = map[Level]int{
+		TraceLevel: colorBlue,
+		DebugLevel: 0,
+		InfoLevel:  colorGreen,
+		WarnLevel:  colorYellow,
+		ErrorLevel: colorRed,
+		FatalLevel: colorRed,
+		PanicLevel: colorRed,
+	}
+
+	// FormattedLevels are used by ConsoleWriter's consoleDefaultFormatLevel
+	// for a short level name.
+	FormattedLevels = map[Level]string{
+		TraceLevel: "TRC",
+		DebugLevel: "DBG",
+		InfoLevel:  "INF",
+		WarnLevel:  "WRN",
+		ErrorLevel: "ERR",
+		FatalLevel: "FTL",
+		PanicLevel: "PNC",
 	}
 )
 
diff --git a/hlog/hlog.go b/hlog/hlog.go
index 3773400..e0dd512 100644
--- a/hlog/hlog.go
+++ b/hlog/hlog.go
@@ -216,3 +216,17 @@ func AccessHandler(f func(r *http.Request, status, size int, duration time.Durat
 		})
 	}
 }
+
+// HostHandler adds the request's host as a field to the context's logger
+// using fieldKey as field key.
+func HostHandler(fieldKey string) func(next http.Handler) http.Handler {
+	return func(next http.Handler) http.Handler {
+		return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
+			log := zerolog.Ctx(r.Context())
+			log.UpdateContext(func(c zerolog.Context) zerolog.Context {
+				return c.Str(fieldKey, r.Host)
+			})
+			next.ServeHTTP(w, r)
+		})
+	}
+}
diff --git a/log.go b/log.go
index 834c7e6..c186651 100644
--- a/log.go
+++ b/log.go
@@ -450,6 +450,14 @@ func (l *Logger) Printf(format string, v ...interface{}) {
 	}
 }
 
+// Println sends a log event using debug level and no extra field.
+// Arguments are handled in the manner of fmt.Println.
+func (l *Logger) Println(v ...interface{}) {
+	if e := l.Debug(); e.Enabled() {
+		e.CallerSkipFrame(1).Msg(fmt.Sprintln(v...))
+	}
+}
+
 // Write implements the io.Writer interface. This is useful to set as a writer
 // for the standard library log.
 func (l Logger) Write(p []byte) (n int, err error) {


Test patch:
diff --git a/hlog/hlog_test.go b/hlog/hlog_test.go
index c584e98..1f5a1bc 100644
--- a/hlog/hlog_test.go
+++ b/hlog/hlog_test.go
@@ -292,3 +292,17 @@ func TestCtxWithID(t *testing.T) {
 		t.Errorf("CtxWithID() = %v, want %v", got, want)
 	}
 }
+
+func TestHostHandler(t *testing.T) {
+	out := &bytes.Buffer{}
+	r := &http.Request{Host: "example.com"}
+	h := HostHandler("host")(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
+		l := FromRequest(r)
+		l.Log().Msg("")
+	}))
+	h = NewHandler(zerolog.New(out))(h)
+	h.ServeHTTP(nil, r)
+	if want, got := `{"host":"example.com"}`+"\n", decodeIfBinary(out); want != got {
+		t.Errorf("Invalid log output, got: %s, want: %s", got, want)
+	}
+}
diff --git a/log_example_test.go b/log_example_test.go
index 70caa66..81e2c20 100644
--- a/log_example_test.go
+++ b/log_example_test.go
@@ -95,6 +95,14 @@ func ExampleLogger_Printf() {
 	// Output: {"level":"debug","message":"hello world"}
 }
 
+func ExampleLogger_Println() {
+	log := zerolog.New(os.Stdout)
+
+	log.Println("hello world")
+
+	// Output: {"level":"debug","message":"hello world\n"}
+}
+
 func ExampleLogger_Trace() {
 	log := zerolog.New(os.Stdout)