From ff65020a962b4bfad02e01ff4d4f38b49177df5b Mon Sep 17 00:00:00 2001 From: Laurent Demailly Date: Thu, 6 Jul 2023 18:22:40 -0700 Subject: [PATCH] use the colors now present in log base package, also use similar darkgrey for timestamp --- README.md | 2 ++ go.mod | 8 +++---- go.sum | 16 +++++++------- logc.go | 60 +++++++++++++++++----------------------------------- logc_test.go | 29 ++++++++++++++++++++++++- 5 files changed, 61 insertions(+), 54 deletions(-) diff --git a/README.md b/README.md index e6546ec..7f25592 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,8 @@ # logc Converts [fortio.org/log](https://github.com/fortio/log#log) JSON structured log back to console/text output with colors +Note that since log 1.6 output is colorized already by default on terminals. But this is to interpret/colorize server logs. The output is very similar except for attributes where this is simpler/faster output reversing the attributes string "as is". + ## Example ``` go run ./levelsDemo 2>&1 | logc diff --git a/go.mod b/go.mod index 57e6a87..2abbc66 100644 --- a/go.mod +++ b/go.mod @@ -3,9 +3,9 @@ module fortio.org/logc go 1.18 require ( - fortio.org/cli v1.1.0 - fortio.org/log v1.5.0 - fortio.org/scli v1.7.0 + fortio.org/cli v1.2.0 + fortio.org/log v1.7.0 + fortio.org/scli v1.8.0 ) require ( @@ -14,5 +14,5 @@ require ( fortio.org/version v1.0.2 // indirect github.com/fsnotify/fsnotify v1.6.0 // indirect golang.org/x/exp v0.0.0-20230420155640-133eef4313cb // indirect - golang.org/x/sys v0.9.0 // indirect + golang.org/x/sys v0.10.0 // indirect ) diff --git a/go.sum b/go.sum index c12cd73..f42a57d 100644 --- a/go.sum +++ b/go.sum @@ -1,12 +1,12 @@ fortio.org/assert v1.1.4 h1:Za1RaG+OjsTMpQS3J3UCvTF6wc4+IOHCz+jAOU37Y4o= -fortio.org/cli v1.1.0 h1:ATIxi7DgA7WAexUCF8p5a0qlGYk48ZgkwSEDrvwXeN4= -fortio.org/cli v1.1.0/go.mod h1:O3nVImKwJSvHKbMYWkqMbEagAXCS1xvSv1YbHwkKJjY= +fortio.org/cli v1.2.0 h1:MXmbYnbNHcclf0xYLZjeCnTINby7FpooJxR01+hnBmM= +fortio.org/cli v1.2.0/go.mod h1:zJwHjRnvVqneF7ES+REfElc33xMjhbRDJslSrqIK9Kk= fortio.org/dflag v1.5.2 h1:F9XVRj4Qr2IbJP7BMj7XZc9wB0Q/RZ61Ool+4YPVad8= fortio.org/dflag v1.5.2/go.mod h1:ppb/A8u+KKg+qUUYZNYuvRnXuVb8IsdHb/XGzsmjkN8= -fortio.org/log v1.5.0 h1:0f/O7QPXQoDSnRjy8t0IyxTlQOYQsDOe0EO4Wnw8yCA= -fortio.org/log v1.5.0/go.mod h1:u/8/2lyczXq52aT5Nw6reD+3cR6m/EbS2jBiIYhgiTU= -fortio.org/scli v1.7.0 h1:NC3z2k+2NY5zTB+XoQGX2MKJulMq61gltK8OrkR3U9U= -fortio.org/scli v1.7.0/go.mod h1:HV+Ucg3jV0n+i+mQt/MWlyLXINHmPwrQhney5j5oYW0= +fortio.org/log v1.7.0 h1:4MbU81zqe/3RYuHpXADNgJwd2KEMAwmMUtuF5qtZTug= +fortio.org/log v1.7.0/go.mod h1:u/8/2lyczXq52aT5Nw6reD+3cR6m/EbS2jBiIYhgiTU= +fortio.org/scli v1.8.0 h1:JKxPdHeb1vAXFmaliPkfz0Eq2VI35LVUKileOfxdgks= +fortio.org/scli v1.8.0/go.mod h1:QdIJu32otZ3yGztI3NZoUriMZchXq06u2Ttp+/Tm6u8= fortio.org/sets v1.0.3 h1:HzewdGjH69YmyW06yzplL35lGr+X4OcqQt0qS6jbaO4= fortio.org/sets v1.0.3/go.mod h1:QZVj0r6KP/ZD9ebySW9SgxVNy/NjghUfyHW9NN+WU+4= fortio.org/version v1.0.2 h1:8NwxdX58aoeKx7T5xAPO0xlUu1Hpk42nRz5s6e6eKZ0= @@ -16,5 +16,5 @@ github.com/fsnotify/fsnotify v1.6.0/go.mod h1:sl3t1tCWJFWoRz9R8WJCbQihKKwmorjAbS golang.org/x/exp v0.0.0-20230420155640-133eef4313cb h1:rhjz/8Mbfa8xROFiH+MQphmAmgqRM0bOMnytznhWEXk= golang.org/x/exp v0.0.0-20230420155640-133eef4313cb/go.mod h1:V1LtkGg67GoY2N1AnLN78QLrzxkLyJw7RJb1gzOOz9w= golang.org/x/sys v0.0.0-20220908164124-27713097b956/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.9.0 h1:KS/R3tvhPqvJvwcKfnBHJwwthS11LRhmM5D59eEXa0s= -golang.org/x/sys v0.9.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.10.0 h1:SqMFp9UcQJZa+pmYuAKjd9xq1f0j5rLcDIk0mj4qAsA= +golang.org/x/sys v0.10.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= diff --git a/logc.go b/logc.go index 1c22e82..ef9886c 100644 --- a/logc.go +++ b/logc.go @@ -5,6 +5,7 @@ import ( "encoding/json" "flag" "fmt" + "io" "os" "strings" "time" @@ -13,40 +14,14 @@ import ( "fortio.org/log" ) -const ( - Reset = "\033[0m" - Red = "\033[31m" - Green = "\033[32m" - Yellow = "\033[33m" - Blue = "\033[34m" - Purple = "\033[35m" - Cyan = "\033[36m" - Gray = "\033[37m" - White = "\033[97m" - BrightRed = "\033[91m" -) - // Takes json string level and returns the 1 letter short and color to use for it. func LevelToColor(levelStr string) (string, string) { - switch levelStr { - case "dbug": - return "D", Gray - case "trace": - return "V", Cyan - case "info": - return "I", Green - case "warn": - return "W", Yellow - case "err": - return "E", Red - case "crit": - return "C", Purple - case "fatal": - return "F", BrightRed - default: + level, found := log.JSONStringLevelToLevel[levelStr] + if !found { log.Critf("Bug/Unknown level %q", levelStr) + return "?", log.Colors.Blue } - return "?", "" + return log.LevelToStrA[level][0:1], log.LevelToColor[level] } // GetAttributes returns the remaining/additional attributes after the `msg`, if any, for text output. @@ -90,11 +65,11 @@ func main() { noColor := *noColorFlag for scanner.Scan() { line := scanner.Bytes() - ProcessLogLine(&prevDate, noColor, line) + ProcessLogLine(os.Stdout, &prevDate, noColor, line) } } -func ProcessLogLine(prevDate *time.Time, noColor bool, line []byte) { +func ProcessLogLine(w io.Writer, prevDate *time.Time, noColor bool, line []byte) { // json deserialize e := log.JSONEntry{} err := json.Unmarshal(line, &e) @@ -104,6 +79,15 @@ func ProcessLogLine(prevDate *time.Time, noColor bool, line []byte) { return } tsStr := "" + reset := log.Colors.Reset + darkGrey := log.Colors.DarkGray + // uppercase single letter level + color extraction + lvl, color := LevelToColor(e.Level) + if noColor { + color = "" + reset = "" + darkGrey = "" + } if e.TS != 0 { ts := e.Time() // Each time the day changes we print a header @@ -111,19 +95,13 @@ func ProcessLogLine(prevDate *time.Time, noColor bool, line []byte) { fmt.Printf("#### %s ####\n", ts.Format("2006-01-02")) *prevDate = ts } - tsStr = ts.Format("15:04:05.000000 ") - } - reset := Reset - // uppercase single letter level + color extraction - lvl, color := LevelToColor(e.Level) - if noColor { - color = "" - reset = "" + // Use full microseconds resolution unlike the log built in color version which stops at millis. + tsStr = ts.Format(darkGrey + "15:04:05.000000 ") } fileLine := "" if e.Line != 0 { fileLine = fmt.Sprintf("%s:%d> ", e.File, e.Line) } // Msg can be multi line. - fmt.Printf("%s%s%s %s%s%s%s\n", color, tsStr, lvl, fileLine, e.Msg, GetAttributes(string(line)), reset) + fmt.Fprintf(w, "%s%s%s %s%s%s%s\n", tsStr, color, lvl, fileLine, e.Msg, GetAttributes(string(line)), reset) } diff --git a/logc_test.go b/logc_test.go index ed1160d..acf20d0 100644 --- a/logc_test.go +++ b/logc_test.go @@ -1,6 +1,13 @@ package main -import "testing" +import ( + "bufio" + "strings" + "testing" + "time" + + "fortio.org/log" +) func TestGetAttributes(t *testing.T) { for _, tc := range []struct { @@ -19,3 +26,23 @@ func TestGetAttributes(t *testing.T) { } } } + +func TestLevels(t *testing.T) { + var zeroTime time.Time + for _, tc := range []struct { + in string + want string + }{ + {`{"level":"trace","msg":"foo"}`, log.Colors.Cyan + "V foo" + log.Colors.Reset + "\n"}, + {`{"level":"xyz","msg":"foo"}`, log.Colors.Blue + "? foo" + log.Colors.Reset + "\n"}, + } { + buf := &strings.Builder{} + w := bufio.NewWriter(buf) + ProcessLogLine(w, &zeroTime, false, []byte(tc.in)) + w.Flush() + got := buf.String() + if got != tc.want { + t.Errorf("LevelToColor(%s) = '%s', want '%s'", tc.in, got, tc.want) + } + } +}