diff --git a/.golangci.yml b/.golangci.yml index e6a744f..0ea78a5 100644 --- a/.golangci.yml +++ b/.golangci.yml @@ -36,6 +36,7 @@ linters: - nestif # cyclop does this - nlreturn # Similar to wsl, I think best left to judgement - nonamedreturns # Named returns are often helpful, it's naked returns that are the issue + - noinlineerr # This is more readable in some cases - paralleltest # I've never had Go tests take longer than a few seconds, it's fine - unparam # gopls is better and more subtle - varnamelen # Lots of false positives of things that are fine @@ -56,8 +57,8 @@ linters: - path: examples linters: - - gosec - mnd + - gosec settings: cyclop: @@ -157,7 +158,12 @@ linters: disabled: true # predeclared does this - name: unhandled-error - disabled: true # errcheck does this + arguments: + - fmt\.(Fp|P)rint(ln|f)? + - strings.Builder.Write(String|Byte)? + - bytes.Buffer.Write(String|Byte)? + - bytes.Buffer.WriteTo? + - os.File.Close? - name: flag-parameter disabled: true # As far as I can work out this just doesn't like bools diff --git a/examples/prefix/main.go b/examples/prefix/main.go index 34cfc9a..7ccde13 100644 --- a/examples/prefix/main.go +++ b/examples/prefix/main.go @@ -2,6 +2,7 @@ package main import ( "math/rand/v2" + "net/http" "os" "time" @@ -17,9 +18,9 @@ func main() { prefixed.Warn("Slow endpoint", "endpoint", "users/slow", "duration", 10*time.Second) sleep() - prefixed.Info("Response from get repos", "status", 200, "duration", 500*time.Millisecond) + prefixed.Info("Response from get repos", "status", http.StatusOK, "duration", 500*time.Millisecond) sleep() - prefixed.Error("Response from something else", "status", 400, "duration", 33*time.Millisecond) + prefixed.Error("Response from something else", "status", http.StatusBadRequest, "duration", 33*time.Millisecond) } func sleep() { diff --git a/log.go b/log.go index d19228f..45fa0c6 100644 --- a/log.go +++ b/log.go @@ -4,7 +4,7 @@ // intended to be human readable and easy on the eye with a good choice of colours, ideal for command line // applications that have a --debug or --verbose flag that enables extra logging. // -// log emphasis simplicity and efficiency so there aren't too many knobs to twiddle, you just get a consistent, +// log emphasises simplicity and efficiency so there aren't too many knobs to twiddle, you just get a consistent, // easy to use, simple logger with minimal overhead. package log // import "go.followtheprocess.codes/log" @@ -106,6 +106,7 @@ func (l *Logger) With(kv ...any) *Logger { sub := l.clone() sub.kv = slices.Concat(sub.kv, kv) + return sub } @@ -116,6 +117,7 @@ func (l *Logger) Prefixed(prefix string) *Logger { sub := l.clone() sub.prefix = prefix + return sub } @@ -155,15 +157,18 @@ func (l *Logger) log(level Level, msg string, kv ...any) { buf.WriteString(timestampStyle.Text(l.timeFunc().Format(l.timeFormat))) buf.WriteByte(' ') buf.WriteString(level.styled()) + if l.prefix != "" { buf.WriteString(" " + prefixStyle.Text(l.prefix)) } + buf.WriteByte(':') buf.WriteByte(' ') buf.WriteString(msg) if numKVs := len(l.kv) + len(kv); numKVs != 0 { kvs := make([]any, 0, numKVs) + kvs = append(kvs, l.kv...) if len(kvs)%2 != 0 { kvs = append(kvs, missingValue) @@ -176,6 +181,7 @@ func (l *Logger) log(level Level, msg string, kv ...any) { for i := 0; i < len(kvs); i += 2 { buf.WriteByte(' ') + key := keyStyle.Sprint(kvs[i]) val := fmt.Sprintf("%+v", kvs[i+1]) @@ -194,6 +200,7 @@ func (l *Logger) log(level Level, msg string, kv ...any) { // WriteTo drains the buffer l.mu.Lock() defer l.mu.Unlock() + buf.WriteTo(l.w) //nolint: errcheck // Just like printing } @@ -226,6 +233,7 @@ var bufPool = sync.Pool{ func getBuffer() *bytes.Buffer { buf := bufPool.Get().(*bytes.Buffer) //nolint:revive,errcheck,forcetypeassert // We are in total control of this buf.Reset() + return buf } diff --git a/log_test.go b/log_test.go index fc6d6e8..2baa7d0 100644 --- a/log_test.go +++ b/log_test.go @@ -189,17 +189,21 @@ func TestRace(t *testing.T) { var wg sync.WaitGroup wg.Add(n) + for i := range n { go func(wg *sync.WaitGroup, i int) { defer wg.Done() + logger.Info(fmt.Sprintf("Something: %d", i)) }(&wg, i) } wg.Add(n) + for i := range n { go func(wg *sync.WaitGroup, i int) { defer wg.Done() + sub.Info(fmt.Sprintf("Other: %d", i)) }(&wg, i) }