Skip to content

Commit 172a28e

Browse files
committed
refactor: simplify logging functions and introduce LogLevel
This commit refactors the logging functions by removing the level parameter from the Log function, making it a shorthand for logging at the Error level. A new LogLevel function is introduced to allow logging at specified levels. Additionally, tests are updated to reflect these changes, and documentation is revised to guide users on the new logging approach.
1 parent b440d85 commit 172a28e

5 files changed

Lines changed: 50 additions & 18 deletions

File tree

MIGRATION.md

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -14,14 +14,14 @@ Version 0.5.0 is a **breaking change** release that replaces the custom field sy
1414
-**Added**: `slog.LogValuer` implementation
1515
-**Added**: Grouped attributes via `slog.Group`
1616
-**Added**: `errors.Attrs(err)` to extract attributes
17-
-**Added**: `errors.Log(ctx, logger, level, err)` for slog logging
17+
-**Added**: `errors.Log(ctx, logger, err)` and `errors.LogLevel(ctx, logger, level, err)` for slog logging
1818
- 📦 **Minimum Go version**: 1.21 (for `log/slog` support)
1919

2020
## Quick Migration Checklist
2121

2222
- [ ] Update Go version to 1.21 or higher
2323
- [ ] Remove imports of `errors/logging/logrusadapter`
24-
- [ ] Replace old `errors.Log(err, logger)` calls with new `errors.Log(ctx, logger, level, err)` or direct slog usage
24+
- [ ] Replace old `errors.Log(err, logger)` calls with new `errors.Log(ctx, logger, err)` or `errors.LogLevel(ctx, logger, level, err)` or direct slog usage
2525
- [ ] Update custom error types implementing `LoggableError`
2626
- [ ] Update mock loggers in tests to use `errorstest.Logger`
2727
- [ ] Consider using grouped attributes for better structure
@@ -326,7 +326,7 @@ If you were using the logrus adapter:
326326
- logrusadapter.Log(err, logrusLogger)
327327

328328
// Option 1: Switch to slog
329-
+ errors.Log(ctx, slog.Default(), slog.LevelError, err)
329+
+ errors.Log(ctx, slog.Default(), err)
330330

331331
// Option 2: Create your own logrus adapter
332332
+ // See "Custom Logger Adapters" section below
@@ -378,7 +378,7 @@ Replace `errors.Log()` calls:
378378
- errors.Log(err, myLogger)
379379

380380
+ // Option 1: Use Log
381-
+ errors.Log(ctx, slog.Default(), slog.LevelError, err)
381+
+ errors.Log(ctx, slog.Default(), err)
382382

383383
+ // Option 2: Extract and log
384384
+ attrs := errors.Attrs(err)
@@ -516,7 +516,7 @@ logger := otelslog.NewHandler(...)
516516
logger := slog.New(myHandler)
517517

518518
// Works the same way
519-
errors.Log(ctx, logger, slog.LevelError, err)
519+
errors.Log(ctx, logger, err)
520520
```
521521

522522
### 4. Simplified Testing
@@ -562,7 +562,7 @@ func (e *MyError) Attrs() []slog.Attr {
562562
**Solution**: Convert to `[]any` or use `Log()`:
563563
```go
564564
// Option 1: Use Log
565-
errors.Log(ctx, logger, level, err)
565+
errors.LogLevel(ctx, logger, level, err)
566566

567567
// Option 2: Convert manually
568568
attrs := errors.Attrs(err)

README.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ Key differences and features:
3636

3737
* `errors.IsOfType[T any](err error)` to test for error types.
3838
* `errors.Attrs(err error) []slog.Attr` to extract all attributes from error chain.
39-
* `errors.Log(ctx, logger, level, err)` convenience function for logging with slog.
39+
* `errors.Log(ctx, logger, err)` and `errors.LogLevel(ctx, logger, level, err)` for logging with slog.
4040

4141
## Installation
4242

@@ -318,8 +318,8 @@ err := errors.Errorf(
318318
),
319319
)
320320

321-
// Log error with all attributes and stack trace
322-
errors.Log(ctx, slog.Default(), slog.LevelError, err)
321+
// Log error at Error level with all attributes and stack trace
322+
errors.Log(ctx, slog.Default(), err)
323323
```
324324

325325
#### Extracting attributes manually

logging.go

Lines changed: 17 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -43,17 +43,29 @@ func attrsFromError(err error) []slog.Attr {
4343
return attrs
4444
}
4545

46-
// Log logs an error with all its structured attributes and stack trace
47-
// using the provided slog.Logger. This is a convenience function for logging
48-
// errors with slog.
46+
// Log logs an error at Error level with all its structured attributes and stack trace
47+
// using the provided slog.Logger. It is a shorthand for LogLevel(ctx, logger, slog.LevelError, err).
4948
//
5049
// If err is nil, this function does nothing.
5150
//
5251
// Example:
5352
//
5453
// err := errors.Wrap(dbErr, errors.String("query", sql), errors.Int("userID", 123))
55-
// errors.Log(ctx, slog.Default(), slog.LevelError, err)
56-
func Log(ctx context.Context, logger *slog.Logger, level slog.Level, err error) {
54+
// errors.Log(ctx, slog.Default(), err)
55+
func Log(ctx context.Context, logger *slog.Logger, err error) {
56+
LogLevel(ctx, logger, slog.LevelError, err)
57+
}
58+
59+
// LogLevel logs an error at the specified level with all its structured attributes
60+
// and stack trace using the provided slog.Logger.
61+
//
62+
// If err is nil, this function does nothing.
63+
//
64+
// Example:
65+
//
66+
// errors.LogLevel(ctx, slog.Default(), slog.LevelWarn, err)
67+
// errors.LogLevel(ctx, slog.Default(), slog.LevelError, err)
68+
func LogLevel(ctx context.Context, logger *slog.Logger, level slog.Level, err error) {
5769
if err == nil {
5870
return
5971
}

logging_test.go

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -107,7 +107,7 @@ func TestLog(t *testing.T) {
107107
errors.Errorf("test error", errors.String("user", "john"), errors.Int("id", 123)),
108108
)
109109

110-
errors.Log(context.Background(), logger, slog.LevelError, err)
110+
errors.Log(context.Background(), logger, err)
111111

112112
if capturedMsg != "test error" {
113113
t.Errorf("expected message 'test error', got '%s'", capturedMsg)
@@ -149,6 +149,26 @@ func TestLog(t *testing.T) {
149149
}
150150
}
151151

152+
func TestLogLevel(t *testing.T) {
153+
for _, level := range []slog.Level{slog.LevelDebug, slog.LevelInfo, slog.LevelWarn, slog.LevelError} {
154+
t.Run(level.String(), func(t *testing.T) {
155+
var capturedLevel slog.Level
156+
handler := &testHandler{
157+
onHandle: func(ctx context.Context, r slog.Record) error {
158+
capturedLevel = r.Level
159+
return nil
160+
},
161+
}
162+
logger := slog.New(handler)
163+
err := errors.New("test")
164+
errors.LogLevel(context.Background(), logger, level, err)
165+
if capturedLevel != level {
166+
t.Errorf("expected level %v, got %v", level, capturedLevel)
167+
}
168+
})
169+
}
170+
}
171+
152172
// testHandler is a simple slog.Handler for testing.
153173
type testHandler struct {
154174
onHandle func(ctx context.Context, r slog.Record) error

slog_test.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -443,7 +443,7 @@ func TestLogAttrsComplete(t *testing.T) {
443443
),
444444
)
445445

446-
errors.Log(context.Background(), logger, slog.LevelError, err)
446+
errors.Log(context.Background(), logger, err)
447447

448448
if capturedMsg != "database error" {
449449
t.Errorf("expected message 'database error', got '%s'", capturedMsg)
@@ -497,7 +497,7 @@ func TestLogAttrsComplete(t *testing.T) {
497497

498498
logger := slog.New(handler)
499499

500-
errors.Log(context.Background(), logger, slog.LevelError, nil)
500+
errors.Log(context.Background(), logger, nil)
501501

502502
if handlerCalled {
503503
t.Error("expected handler not to be called for nil error")
@@ -527,7 +527,7 @@ func TestLogAttrsComplete(t *testing.T) {
527527
),
528528
)
529529

530-
errors.Log(context.Background(), logger, slog.LevelError, err)
530+
errors.Log(context.Background(), logger, err)
531531

532532
// Should have request group and stackTrace
533533
hasRequestGroup := false

0 commit comments

Comments
 (0)