diff --git a/internal/entryhuman/entry.go b/internal/entryhuman/entry.go index a77e245..168a7b9 100644 --- a/internal/entryhuman/entry.go +++ b/internal/entryhuman/entry.go @@ -72,7 +72,8 @@ func formatValue(v interface{}) string { case reflect.Struct, reflect.Map: byt, err := json.Marshal(v) if err != nil { - panic(err) + // don't panic + return "!! Error while marshalling value !!" } return string(byt) case reflect.Slice: @@ -334,7 +335,8 @@ func levelStyle(level slog.Level) lipgloss.Style { case slog.LevelError, slog.LevelFatal, slog.LevelCritical: return levelErrorStyle default: - panic("unknown level") + // don't panic + return levelErrorStyle } } diff --git a/slog.go b/slog.go index a3b705c..375c5e9 100644 --- a/slog.go +++ b/slog.go @@ -80,67 +80,40 @@ func Make(sinks ...Sink) Logger { } // Debug logs the msg and fields at LevelDebug. -// See Info for information on the fields argument. -func (l Logger) Debug(ctx context.Context, msg string, fields ...any) { +func (l Logger) Debug(ctx context.Context, msg string, fields ...Field) { l.log(ctx, LevelDebug, msg, fields) } // Info logs the msg and fields at LevelInfo. -// Fields may contain any combination of key value pairs, Field, and Map. -// For example: -// -// log.Info(ctx, "something happened", "user", "alex", slog.F("age", 20)) -// -// is equivalent to: -// -// log.Info(ctx, "something happened", slog.F("user", "alex"), slog.F("age", 20)) -// -// is equivalent to: -// -// log.Info(ctx, "something happened", slog.M( -// slog.F("user", "alex"), -// slog.F("age", 20), -// )) -// -// is equivalent to: -// -// log.Info(ctx, "something happened", "user", "alex", "age", 20) -// -// In general, prefer using key value pairs over Field and Map, as that is how -// the standard library's slog package works. -func (l Logger) Info(ctx context.Context, msg string, fields ...any) { +func (l Logger) Info(ctx context.Context, msg string, fields ...Field) { l.log(ctx, LevelInfo, msg, fields) } // Warn logs the msg and fields at LevelWarn. -// See Info() for information on the fields argument. -func (l Logger) Warn(ctx context.Context, msg string, fields ...any) { +func (l Logger) Warn(ctx context.Context, msg string, fields ...Field) { l.log(ctx, LevelWarn, msg, fields) } // Error logs the msg and fields at LevelError. -// See Info() for information on the fields argument. // // It will then Sync(). -func (l Logger) Error(ctx context.Context, msg string, fields ...any) { +func (l Logger) Error(ctx context.Context, msg string, fields ...Field) { l.log(ctx, LevelError, msg, fields) l.Sync() } // Critical logs the msg and fields at LevelCritical. -// See Info() for information on the fields argument. // // It will then Sync(). -func (l Logger) Critical(ctx context.Context, msg string, fields ...any) { +func (l Logger) Critical(ctx context.Context, msg string, fields ...Field) { l.log(ctx, LevelCritical, msg, fields) l.Sync() } // Fatal logs the msg and fields at LevelFatal. -// See Info() for information on the fields argument. // // It will then Sync() and os.Exit(1). -func (l Logger) Fatal(ctx context.Context, msg string, fields ...any) { +func (l Logger) Fatal(ctx context.Context, msg string, fields ...Field) { l.log(ctx, LevelFatal, msg, fields) l.Sync() @@ -182,32 +155,7 @@ func (l Logger) AppendSinks(s ...Sink) Logger { return l } -func (l Logger) log(ctx context.Context, level Level, msg string, rawFields []any) { - fields := make(Map, 0, len(rawFields)) - var wipField Field - for i, f := range rawFields { - if wipField.Name != "" { - wipField.Value = f - fields = append(fields, wipField) - wipField = Field{} - continue - } - switch f := f.(type) { - case Field: - fields = append(fields, f) - case Map: - fields = append(fields, f...) - case string: - wipField.Name = f - default: - panic(fmt.Sprintf("unexpected field type %T at index %v (does it have a key?)", f, i)) - } - } - - if wipField.Name != "" { - panic(fmt.Sprintf("field %q has no value", wipField.Name)) - } - +func (l Logger) log(ctx context.Context, level Level, msg string, fields []Field) { ent := l.entry(ctx, level, msg, fields) l.Log(ctx, ent) } diff --git a/slog_test.go b/slog_test.go index 277a9c3..4e41767 100644 --- a/slog_test.go +++ b/slog_test.go @@ -2,7 +2,6 @@ package slog_test import ( "context" - "fmt" "io" "runtime" "testing" @@ -76,7 +75,7 @@ func TestLogger(t *testing.T) { File: slogTestFile, Func: "cdr.dev/slog_test.TestLogger.func2", - Line: 68, + Line: 67, Fields: slog.M( slog.F("ctx", 1024), @@ -113,7 +112,7 @@ func TestLogger(t *testing.T) { File: slogTestFile, Func: "cdr.dev/slog_test.TestLogger.func3", - Line: 103, + Line: 102, SpanContext: span.SpanContext(), @@ -154,36 +153,6 @@ func TestLogger(t *testing.T) { assert.Equal(t, "level", slog.LevelFatal, s.entries[5].Level) assert.Equal(t, "exits", 1, exits) }) - - t.Run("kv", func(t *testing.T) { - s := &fakeSink{} - l := slog.Make(s) - - // All of these formats should be equivalent. - formats := [][]any{ - {"animal", "cat", "weight", 15}, - {slog.F("animal", "cat"), "weight", 15}, - {slog.M( - slog.F("animal", "cat"), - slog.F("weight", 15), - )}, - {slog.F("animal", "cat"), slog.F("weight", 15)}, - } - - for _, format := range formats { - l.Info(bg, "msg", format...) - } - - assert.Len(t, "entries", 4, s.entries) - - for i := range s.entries { - assert.Equal( - t, fmt.Sprintf("%v", i), - s.entries[0].Fields, - s.entries[i].Fields, - ) - } - }) } func TestLevel_String(t *testing.T) { diff --git a/sloggers/slogtest/t.go b/sloggers/slogtest/t.go index 8c0f328..567a5f6 100644 --- a/sloggers/slogtest/t.go +++ b/sloggers/slogtest/t.go @@ -146,25 +146,25 @@ func l(t testing.TB) slog.Logger { } // Debug logs the given msg and fields to t via t.Log at the debug level. -func Debug(t testing.TB, msg string, fields ...any) { +func Debug(t testing.TB, msg string, fields ...slog.Field) { slog.Helper() l(t).Debug(ctx, msg, fields...) } // Info logs the given msg and fields to t via t.Log at the info level. -func Info(t testing.TB, msg string, fields ...any) { +func Info(t testing.TB, msg string, fields ...slog.Field) { slog.Helper() l(t).Info(ctx, msg, fields...) } // Error logs the given msg and fields to t via t.Error at the error level. -func Error(t testing.TB, msg string, fields ...any) { +func Error(t testing.TB, msg string, fields ...slog.Field) { slog.Helper() l(t).Error(ctx, msg, fields...) } // Fatal logs the given msg and fields to t via t.Fatal at the fatal level. -func Fatal(t testing.TB, msg string, fields ...any) { +func Fatal(t testing.TB, msg string, fields ...slog.Field) { slog.Helper() l(t).Fatal(ctx, msg, fields...) }