go.mondoo.com/cnquery@v0.0.0-20231005093811-59568235f6ea/logger/cliwriter.go (about) 1 // Copyright (c) Mondoo, Inc. 2 // SPDX-License-Identifier: BUSL-1.1 3 4 package logger 5 6 import ( 7 "fmt" 8 "github.com/muesli/termenv" 9 "go.mondoo.com/cnquery/cli/theme/colors" 10 "io" 11 "os" 12 "runtime" 13 "strings" 14 15 "github.com/rs/zerolog" 16 "github.com/rs/zerolog/log" 17 ) 18 19 func NewConsoleWriter(out io.Writer, compact bool) zerolog.Logger { 20 w := zerolog.ConsoleWriter{Out: out} 21 // zerolog's own color output implementation does not work on Windows, therefore we re-implement all 22 // colored methods here 23 // TODO: its unclear why but the first 3 messages are outputted wrongly on windows 24 // therefore we disable the colors for the indicators for now 25 26 if compact && runtime.GOOS != "windows" { 27 w.FormatLevel = consoleFormatLevel() 28 } else if compact { 29 w.FormatLevel = consoleFormatLevelNoColor() 30 } 31 32 w.FormatFieldName = consoleDefaultFormatFieldName() 33 w.FormatFieldValue = consoleDefaultFormatFieldValue 34 w.FormatErrFieldName = consoleDefaultFormatErrFieldName() 35 w.FormatErrFieldValue = consoleDefaultFormatErrFieldValue() 36 w.FormatCaller = consoleDefaultFormatCaller() 37 w.FormatMessage = consoleDefaultFormatMessage 38 w.FormatTimestamp = func(i interface{}) string { return "" } 39 40 return log.Output(w) 41 } 42 43 func consoleDefaultFormatCaller() zerolog.Formatter { 44 return func(i interface{}) string { 45 var c string 46 if cc, ok := i.(string); ok { 47 c = cc 48 } 49 if len(c) > 0 { 50 cwd, err := os.Getwd() 51 if err == nil { 52 c = strings.TrimPrefix(c, cwd) 53 c = strings.TrimPrefix(c, "/") 54 } 55 } 56 return c 57 } 58 } 59 60 func consoleDefaultFormatMessage(i interface{}) string { 61 if i == nil { 62 return "" 63 } 64 return fmt.Sprintf("%s", i) 65 } 66 67 func consoleDefaultFormatFieldName() zerolog.Formatter { 68 return func(i interface{}) string { 69 return termenv.String(fmt.Sprintf("%s=", i)).Foreground(colors.DefaultColorTheme.Primary).String() 70 } 71 } 72 73 func consoleDefaultFormatFieldValue(i interface{}) string { 74 return fmt.Sprintf("%s", i) 75 } 76 77 func consoleDefaultFormatErrFieldName() zerolog.Formatter { 78 return func(i interface{}) string { 79 return termenv.String(fmt.Sprintf("%s=", i)).Foreground(colors.DefaultColorTheme.Error).String() 80 } 81 } 82 83 func consoleDefaultFormatErrFieldValue() zerolog.Formatter { 84 return func(i interface{}) string { 85 return termenv.String(fmt.Sprintf("%s", i)).Foreground(colors.DefaultColorTheme.Error).String() 86 } 87 } 88 89 // consoleFormatLevelNoColor returns a formatter that outputs the level in uppercase without any color 90 // this is used for compact mode and primarily for windows which has a restricted color palette and character set 91 // for the console 92 func consoleFormatLevelNoColor() zerolog.Formatter { 93 return func(i interface{}) string { 94 var l string 95 96 if ll, ok := i.(string); ok { 97 switch ll { 98 case "trace": 99 l = "TRC" 100 case "debug": 101 l = "DBG" 102 case "info": 103 l = "-" 104 case "warn": 105 l = "WRN" 106 case "error": 107 l = "ERR" 108 case "fatal": 109 l = "FTL" 110 case "panic": 111 l = "PNC" 112 default: 113 l = "UNK" 114 } 115 } else { 116 if i == nil { 117 l = "UNK" 118 } else { 119 l = strings.ToUpper(fmt.Sprintf("%s", i))[0:3] 120 } 121 } 122 123 return l 124 } 125 } 126 127 func consoleFormatLevel() zerolog.Formatter { 128 return func(i interface{}) string { 129 var l string 130 var color termenv.Color 131 132 // set no color as default 133 color = termenv.NoColor{} 134 135 if ll, ok := i.(string); ok { 136 switch ll { 137 case "trace": 138 l = "TRC" 139 color = colors.DefaultColorTheme.Secondary 140 case "debug": 141 l = "DBG" 142 color = colors.DefaultColorTheme.Primary 143 case "info": 144 l = "→" 145 color = colors.DefaultColorTheme.Good 146 case "warn": 147 l = "!" 148 color = colors.DefaultColorTheme.Medium 149 case "error": 150 l = "x" 151 color = colors.DefaultColorTheme.Error 152 case "fatal": 153 l = "FTL" 154 color = colors.DefaultColorTheme.Error 155 case "panic": 156 l = "PNC" 157 color = colors.DefaultColorTheme.Error 158 default: 159 l = "???" 160 } 161 } else { 162 if i == nil { 163 l = "???" 164 } else { 165 l = strings.ToUpper(fmt.Sprintf("%s", i))[0:3] 166 } 167 } 168 169 return termenv.String(l).Foreground(color).String() 170 } 171 }