diff --git a/docs/img/demo.gif b/docs/img/demo.gif index a88defd..c2a6a4d 100644 Binary files a/docs/img/demo.gif and b/docs/img/demo.gif differ diff --git a/docs/img/keys.gif b/docs/img/keys.gif index 5b49144..b4deed9 100644 Binary files a/docs/img/keys.gif and b/docs/img/keys.gif differ diff --git a/docs/img/prefix.gif b/docs/img/prefix.gif index 672a62b..608ce8f 100644 Binary files a/docs/img/prefix.gif and b/docs/img/prefix.gif differ diff --git a/examples/demo/main.go b/examples/demo/main.go index 83a00ef..8ed5010 100644 --- a/examples/demo/main.go +++ b/examples/demo/main.go @@ -18,17 +18,30 @@ func main() { slog.Int("temp", 42), slog.Duration("time", 2*time.Minute), ) + sleep() + logger.Info( "Choosing wine pairing", slog.Any("choices", []string{"merlot", "malbec", "rioja"}), ) + sleep() + logger.Error("No malbec left!") + sleep() - logger.Warn("Falling back to second choice", slog.String("fallback", "rioja")) - logger.Info("Eating steak", slog.String("cut", "sirloin"), slog.Bool("enjoying", true)) + logger.Warn( + "Falling back to second choice", + slog.String("fallback", "rioja"), + ) + + logger.Info( + "Eating steak", + slog.String("cut", "sirloin"), + slog.Bool("enjoying", true), + ) } func sleep() { diff --git a/examples/keys/main.go b/examples/keys/main.go index e3b747b..dec7d88 100644 --- a/examples/keys/main.go +++ b/examples/keys/main.go @@ -18,10 +18,15 @@ func main() { slog.Duration("duration", 30*time.Second), slog.Int("number", 42), ) + sleep() sub := logger.With(slog.Bool("sub", true)) - sub.Info("Hello from the sub logger", slog.String("subkey", "yes")) + + sub.Info( + "Hello from the sub logger", + slog.String("subkey", "yes"), + ) } func sleep() { diff --git a/examples/prefix/main.go b/examples/prefix/main.go index 3600489..9e65e67 100644 --- a/examples/prefix/main.go +++ b/examples/prefix/main.go @@ -14,7 +14,11 @@ func main() { logger := log.New(os.Stderr) prefixed := logger.Prefixed("http") - logger.Info("Calling GitHub API", slog.String("url", "https://api.github.com/")) + logger.Info( + "Calling GitHub API", + slog.String("url", "https://api.github.com/"), + ) + sleep() prefixed.Warn( @@ -22,13 +26,17 @@ func main() { slog.String("endpoint", "users/slow"), slog.Duration("duration", 10*time.Second), ) + sleep() + prefixed.Info( "Response from get repos", slog.Int("status", http.StatusOK), slog.Duration("duration", 500*time.Millisecond), ) + sleep() + prefixed.Error( "Response from something else", slog.Int("status", http.StatusBadRequest), diff --git a/log.go b/log.go index 879d663..c934f48 100644 --- a/log.go +++ b/log.go @@ -10,10 +10,8 @@ package log // import "go.followtheprocess.codes/log" import ( "bytes" - "context" "io" "log/slog" - "os" "slices" "strconv" "strings" @@ -37,12 +35,6 @@ const ( errorStyle = hue.Red | hue.Bold ) -// ctxKey is the unexported type used for context key so this key never collides with another. -type ctxKey struct{} - -// contextKey is the actual key used to store and retrieve a Logger from a Context. -var contextKey = ctxKey{} - // Logger is a command line logger. It is safe to use across concurrently // executing goroutines. type Logger struct { @@ -78,25 +70,6 @@ func New(w io.Writer, options ...Option) *Logger { return logger } -// WithContext stores the given logger in a [context.Context]. -// -// The logger may be retrieved from the context with [FromContext]. -func WithContext(ctx context.Context, logger *Logger) context.Context { - return context.WithValue(ctx, contextKey, logger) -} - -// FromContext returns the [Logger] from a [context.Context]. -// -// If the context does not contain a logger, a default logger is returned. -func FromContext(ctx context.Context) *Logger { - logger, ok := ctx.Value(contextKey).(*Logger) - if !ok || logger == nil { - return New(os.Stderr) - } - - return logger -} - // With returns a new [Logger] with the given persistent key value pairs. // // The returned logger is otherwise an exact clone of the caller. diff --git a/log_test.go b/log_test.go index 53c7821..e05938e 100644 --- a/log_test.go +++ b/log_test.go @@ -21,7 +21,6 @@ func TestVisual(t *testing.T) { hue.Enabled(true) // Force colour logger := log.New(os.Stdout, log.WithLevel(log.LevelDebug)) - prefixed := logger.Prefixed("cooking") logger.Debug("Doing some debuggy things") @@ -192,7 +191,7 @@ func TestRace(t *testing.T) { logger := log.New(buf, log.TimeFunc(fixedTime)) sub := logger.Prefixed("sub") - const n = 5 + const n = 1000 var wg sync.WaitGroup wg.Add(n) @@ -224,46 +223,6 @@ func TestRace(t *testing.T) { test.Equal(t, len(lines), n*2, test.Context("expected %d log lines", n*2)) } -func TestContext(t *testing.T) { - t.Run("present", func(t *testing.T) { - buf := &bytes.Buffer{} - - // Constantly return the same time - fixedTime := func() time.Time { - fixed, err := time.Parse(time.RFC3339, "2025-04-01T13:34:03Z") - test.Ok(t, err) - - return fixed - } - - // Configure it a bit so we know we're getting the right one - logger := log.New(buf, log.TimeFunc(fixedTime), log.TimeFormat(time.Kitchen)) - - logger.Info("Before") - - ctx := t.Context() - - ctx = log.WithContext(ctx, logger) - - after := log.FromContext(ctx) - - after.Info("After") - - got := buf.String() - - test.Diff(t, got, "1:34PM INFO: Before\n1:34PM INFO: After\n") - }) - - t.Run("missing", func(t *testing.T) { - _, stderr := test.CaptureOutput(t, func() error { - log.FromContext(t.Context()).Info("FromContext") - return nil - }) - - test.True(t, strings.Contains(stderr, "FromContext")) - }) -} - func BenchmarkLogger(b *testing.B) { hue.Enabled(true) // Force colour