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