@@ -11,8 +11,8 @@ package log // import "go.followtheprocess.codes/log"
1111import (
1212 "bytes"
1313 "context"
14- "fmt"
1514 "io"
15+ "log/slog"
1616 "os"
1717 "slices"
1818 "strconv"
@@ -37,9 +37,6 @@ const (
3737 errorStyle = hue .Red | hue .Bold
3838)
3939
40- // missingValue is the placeholder text for a missing value in a log line's key value pair.
41- const missingValue = "<MISSING>"
42-
4340// ctxKey is the unexported type used for context key so this key never collides with another.
4441type ctxKey struct {}
4542
@@ -54,7 +51,7 @@ type Logger struct {
5451 mu * sync.Mutex // Protects w
5552 timeFormat string // The time format layout string, defaults to [time.RFC3339]
5653 prefix string // Optional prefix to prepend to all log messages
57- kv [] any // Persistent key value pairs
54+ attrs []slog. Attr // Persistent key value pairs
5855 level Level // The configured level of this logger, logs below this level are not shown
5956 isDiscard atomic.Bool // w == [io.Discard], cached
6057}
@@ -103,10 +100,10 @@ func FromContext(ctx context.Context) *Logger {
103100// With returns a new [Logger] with the given persistent key value pairs.
104101//
105102// The returned logger is otherwise an exact clone of the caller.
106- func (l * Logger ) With (kv ... any ) * Logger {
103+ func (l * Logger ) With (attrs ... slog. Attr ) * Logger {
107104 sub := l .clone ()
108105
109- sub .kv = slices .Concat (sub .kv , kv )
106+ sub .attrs = slices .Concat (sub .attrs , attrs )
110107
111108 return sub
112109}
@@ -123,27 +120,27 @@ func (l *Logger) Prefixed(prefix string) *Logger {
123120}
124121
125122// Debug writes a debug level log line.
126- func (l * Logger ) Debug (msg string , kv ... any ) {
127- l .log (LevelDebug , msg , kv ... )
123+ func (l * Logger ) Debug (msg string , attrs ... slog. Attr ) {
124+ l .log (LevelDebug , msg , attrs ... )
128125}
129126
130127// Info writes an info level log line.
131- func (l * Logger ) Info (msg string , kv ... any ) {
132- l .log (LevelInfo , msg , kv ... )
128+ func (l * Logger ) Info (msg string , attrs ... slog. Attr ) {
129+ l .log (LevelInfo , msg , attrs ... )
133130}
134131
135132// Warn writes a warning level log line.
136- func (l * Logger ) Warn (msg string , kv ... any ) {
137- l .log (LevelWarn , msg , kv ... )
133+ func (l * Logger ) Warn (msg string , attrs ... slog. Attr ) {
134+ l .log (LevelWarn , msg , attrs ... )
138135}
139136
140137// Error writes an error level log line.
141- func (l * Logger ) Error (msg string , kv ... any ) {
142- l .log (LevelError , msg , kv ... )
138+ func (l * Logger ) Error (msg string , attrs ... slog. Attr ) {
139+ l .log (LevelError , msg , attrs ... )
143140}
144141
145142// log logs the given levelled message.
146- func (l * Logger ) log (level Level , msg string , kv ... any ) {
143+ func (l * Logger ) log (level Level , msg string , attrs ... slog. Attr ) {
147144 if l .isDiscard .Load () || l .level > level {
148145 // Do as little work as possible
149146 return
@@ -157,7 +154,7 @@ func (l *Logger) log(level Level, msg string, kv ...any) {
157154
158155 buf .WriteString (timestampStyle .Text (l .timeFunc ().Format (l .timeFormat )))
159156 buf .WriteByte (' ' )
160- buf .WriteString (level .styled ())
157+ buf .WriteString (level .String ())
161158
162159 if l .prefix != "" {
163160 buf .WriteString (" " + prefixStyle .Text (l .prefix ))
@@ -173,24 +170,14 @@ func (l *Logger) log(level Level, msg string, kv ...any) {
173170 buf .WriteString (strings .Repeat (" " , padding ))
174171 buf .WriteString (msg )
175172
176- if numKVs := len (l .kv ) + len (kv ); numKVs != 0 {
177- kvs := make ([]any , 0 , numKVs )
178-
179- kvs = append (kvs , l .kv ... )
180- if len (kvs )% 2 != 0 {
181- kvs = append (kvs , missingValue )
182- }
183-
184- kvs = append (kvs , kv ... )
185- if len (kvs )% 2 != 0 {
186- kvs = append (kvs , missingValue )
187- }
173+ if totalAttrs := len (l .attrs ) + len (attrs ); totalAttrs != 0 {
174+ all := slices .Concat (l .attrs , attrs )
188175
189- for i := 0 ; i < len ( kvs ); i += 2 {
176+ for _ , attr := range all {
190177 buf .WriteByte (' ' )
191178
192- key := keyStyle .Sprint ( kvs [ i ] )
193- val := fmt . Sprintf ( "%+v" , kvs [ i + 1 ] )
179+ key := keyStyle .Text ( attr . Key )
180+ val := attr . Value . String ( )
194181
195182 if needsQuotes (val ) || val == "" {
196183 val = strconv .Quote (val )
0 commit comments