slog: Logger.Error puts error attribute first

Logger.Error adds its error argument at the beginning of the Record to
match its own argument order, instead of at the end.

Change-Id: Ie7b4915a21921ef428794e22b59b51f99ce9fa23
Reviewed-on: https://go-review.googlesource.com/c/exp/+/464101
Reviewed-by: Alan Donovan <adonovan@google.com>
TryBot-Result: Gopher Robot <gobot@golang.org>
Run-TryBot: Jonathan Amsterdam <jba@google.com>
diff --git a/slog/logger.go b/slog/logger.go
index 61dc933..3805f63 100644
--- a/slog/logger.go
+++ b/slog/logger.go
@@ -85,9 +85,9 @@
 func (l *Logger) Context() context.Context { return l.ctx }
 
 // With returns a new Logger that includes the given arguments, converted to
-// Attrs as in [Logger.Log]. The Attrs will be added to each output from the
-// Logger. The new Logger shares the old Logger's context.
-//
+// Attrs as in [Logger.Log] and resolved.
+// The Attrs will be added to each output from the Logger.
+// The new Logger shares the old Logger's context.
 // The new Logger's handler is the result of calling WithAttrs on the receiver's
 // handler.
 func (l *Logger) With(args ...any) *Logger {
@@ -160,10 +160,11 @@
 
 func (l *Logger) logPC(err error, pc uintptr, level Level, msg string, args ...any) {
 	r := l.makeRecord(msg, level, pc)
-	r.setAttrsFromArgs(args)
 	if err != nil {
-		r.AddAttrs(Any("err", err))
+		r.front[0] = Any(ErrorKey, err)
+		r.nFront++
 	}
+	r.setAttrsFromArgs(args)
 	_ = l.Handler().Handle(r)
 }
 
diff --git a/slog/logger_test.go b/slog/logger_test.go
index 766e123..c7529eb 100644
--- a/slog/logger_test.go
+++ b/slog/logger_test.go
@@ -46,7 +46,7 @@
 	check(`level=WARN msg=w dur=3s`)
 
 	l.Error("bad", io.EOF, "a", 1)
-	check(`level=ERROR msg=bad a=1 err=EOF`)
+	check(`level=ERROR msg=bad err=EOF a=1`)
 
 	l.Log(LevelWarn+1, "w", Int("a", 1), String("b", "two"))
 	check(`level=WARN\+1 msg=w a=1 b=two`)
@@ -83,7 +83,7 @@
 	checkLogOutput(t, logbuf.String(), `logger_test.go:\d+: WARN msg b=2`)
 	logbuf.Reset()
 	Error("msg", io.EOF, "c", 3)
-	checkLogOutput(t, logbuf.String(), `logger_test.go:\d+: ERROR msg c=3 err=EOF`)
+	checkLogOutput(t, logbuf.String(), `logger_test.go:\d+: ERROR msg err=EOF c=3`)
 
 	// Levels below Info are not printed.
 	logbuf.Reset()
@@ -362,10 +362,10 @@
 	}
 	l := New(HandlerOptions{ReplaceAttr: removeTime}.NewTextHandler(&buf))
 	l.Error("msg", io.EOF, "a", 1)
-	checkLogOutput(t, buf.String(), `level=ERROR msg=msg a=1 err=EOF`)
+	checkLogOutput(t, buf.String(), `level=ERROR msg=msg err=EOF a=1`)
 	buf.Reset()
 	l.Error("msg", io.EOF, "a")
-	checkLogOutput(t, buf.String(), `level=ERROR msg=msg !BADKEY=a err=EOF`)
+	checkLogOutput(t, buf.String(), `level=ERROR msg=msg err=EOF !BADKEY=a`)
 }
 
 func TestLogCopying(t *testing.T) {