vanilla.go (4797B)
1 package logging 2 3 import ( 4 "context" 5 "fmt" 6 "io" 7 "os" 8 "path" 9 "runtime" 10 ) 11 12 var ( 13 // LogWriter is used as io.Writer the Vanilla Logger implementation. 14 LogWriter = os.Stderr 15 ) 16 17 // Vanilla is a basic single-line structured output logger for terminal output. 18 type Vanilla struct { 19 domain string 20 levelFilter int 21 } 22 23 // NewVanilla creates a new Vanilla logger. 24 func NewVanilla() Vanilla { 25 return Vanilla{ 26 domain: "main", 27 levelFilter: LogLevel, 28 } 29 } 30 31 // WithDomain sets the logging domain. It is prepended to the caller file/line information. 32 func(v Vanilla) WithDomain(domain string) Vanilla { 33 v.domain = domain 34 return v 35 } 36 37 // WithLevel overrides the globally set loglevel for the logger instance. 38 func(v Vanilla) WithLevel(level int) Vanilla { 39 v.levelFilter = level 40 return v 41 } 42 43 // Printf logs to the global writer. 44 func(v Vanilla) Printf(level int, msg string, args ...any) { 45 v.Writef(LogWriter, level, msg, args...) 46 } 47 48 // compile log line from inputs and send to given writer. 49 func(v Vanilla) writef(w io.Writer, file string, line int, level int, msg string, args ...any) { 50 if level > v.levelFilter { 51 return 52 } 53 argsStr := argsToString(args) 54 if len(msg) > 0 { 55 fmt.Fprintf(w, "[%s] %s:%s:%v %s\t%s\n", AsString(level), v.domain, file, line, msg, argsStr) 56 } else { 57 fmt.Fprintf(w, "[%s] %s:%s:%v %s\n", AsString(level), v.domain, file, line, argsStr) 58 } 59 } 60 61 // Writef logs to the given writer. 62 func(v Vanilla) Writef(w io.Writer, level int, msg string, args ...any) { 63 file, line := getCaller(2) 64 v.writef(w, file, line, level, msg, args) 65 } 66 67 // WriteCtxf logs with context to the given writer. 68 func(v Vanilla) WriteCtxf(ctx context.Context, w io.Writer, level int, msg string, args ...any) { 69 file, line := getCaller(2) 70 v.writef(w, file, line, level, msg, args...) 71 } 72 73 // get caller information and pass on to writef 74 func(v Vanilla) printf(level int, msg string, args ...any) { 75 file, line := getCaller(3) 76 v.writef(LogWriter, file, line, level, msg, args...) 77 } 78 79 // get caller information and pass on to writef 80 func(v Vanilla) printCtxf(ctx context.Context, level int, msg string, args ...any) { 81 file, line := getCaller(3) 82 v.writef(LogWriter, file, line, level, msg, args...) 83 } 84 85 // PrintCtxf logs with context to the global writer. 86 func(v Vanilla) PrintCtxf(ctx context.Context, level int, msg string, args ...any) { 87 v.printf(level, msg, args...) 88 } 89 90 // Tracef logs a line with level TRACE to the global writer. 91 func(v Vanilla) Tracef(msg string, args ...any) { 92 v.printf(LVL_TRACE, msg, args...) 93 } 94 95 // Debugf logs a line with level DEBUG to the global writer. 96 func(v Vanilla) Debugf(msg string, args ...any) { 97 v.printf(LVL_DEBUG, msg, args...) 98 } 99 100 // Infof logs a line with level INFO to the global writer. 101 func(v Vanilla) Infof(msg string, args ...any) { 102 v.printf(LVL_INFO, msg, args...) 103 } 104 105 // Warnf logs a line with level WARN to the global writer. 106 func(v Vanilla) Warnf(msg string, args ...any) { 107 v.printf(LVL_WARN, msg, args...) 108 } 109 110 // Errorf logs a line with level ERROR to the global writer. 111 func(v Vanilla) Errorf(msg string, args ...any) { 112 v.printf(LVL_ERROR, msg, args...) 113 } 114 115 // TraceCtxf logs a line with context with level TRACE to the global writer. 116 func(v Vanilla) TraceCtxf(ctx context.Context, msg string, args ...any) { 117 v.printCtxf(ctx, LVL_TRACE, msg, args...) 118 } 119 120 // DebugCtxf logs a line with context with level DEBUG to the global writer. 121 func(v Vanilla) DebugCtxf(ctx context.Context, msg string, args ...any) { 122 v.printCtxf(ctx, LVL_DEBUG, msg, args...) 123 } 124 125 // InfoCtxf logs a line with context with level INFO to the global writer. 126 func(v Vanilla) InfoCtxf(ctx context.Context, msg string, args ...any) { 127 v.printCtxf(ctx, LVL_INFO, msg, args...) 128 } 129 130 // WarnCtxf logs a line with context with level WARN to the global writer. 131 func(v Vanilla) WarnCtxf(ctx context.Context, msg string, args ...any) { 132 v.printCtxf(ctx, LVL_WARN, msg, args...) 133 } 134 135 // ErrorCtxf logs a line with context with level ERROR to the global writer. 136 func(v Vanilla) ErrorCtxf(ctx context.Context, msg string, args ...any) { 137 v.printCtxf(ctx, LVL_ERROR, msg, args...) 138 } 139 140 // return file basename and line for caller information. 141 func getCaller(depth int) (string, int) { 142 var file string 143 var line int 144 _, file, line,_ = runtime.Caller(depth) 145 baseFile := path.Base(file) 146 return baseFile, line 147 } 148 149 // string representation of the given structured log args. 150 func argsToString(args []any) string { 151 var s string 152 c := len(args) 153 var i int 154 for i = 0; i < c; i += 2 { 155 if len(s) > 0 { 156 s += ", " 157 } 158 159 if i + 1 < c { 160 var argByte []byte 161 var ok bool 162 argByte, ok = args[i+1].([]byte) 163 if ok { 164 s += fmt.Sprintf("%s=%x", args[i], argByte) 165 } else { 166 s += fmt.Sprintf("%s=%v", args[i], args[i+1]) 167 } 168 } else { 169 s += fmt.Sprintf("%s=??", args[i]) 170 } 171 } 172 return s 173 }