From 20cc4d9bfeb6add8a5244329b1facb855c0fa9fe Mon Sep 17 00:00:00 2001 From: Petro Chaikivskyi Date: Sun, 13 Sep 2026 10:51:15 +0000 Subject: [PATCH 1/2] perf: check the log level before building log arguments Signed-off-by: Petro Chaikivskyi --- middleware/log.go | 5 +++++ middleware/log_test.go | 41 +++++++++++++++++++++++++++++++++++++++++ 2 files changed, 46 insertions(+) diff --git a/middleware/log.go b/middleware/log.go index 98876d98..bb223a74 100644 --- a/middleware/log.go +++ b/middleware/log.go @@ -2,6 +2,7 @@ package middleware import ( "bufio" + "context" "io" "log/slog" "net" @@ -131,6 +132,10 @@ func (l *lm) Log(next http.Handler, accessLogs bool) http.Handler { } func (l *lm) writeLog(accessLog bool, r *http.Request, bw *wrapper, start time.Time) { + if !l.log.Enabled(context.Background(), slog.LevelInfo) { + return + } + if !accessLog { l.log.Info("http log", "status", bw.code, diff --git a/middleware/log_test.go b/middleware/log_test.go index 8b2c1735..a739f039 100644 --- a/middleware/log_test.go +++ b/middleware/log_test.go @@ -1,8 +1,13 @@ package middleware import ( + "bytes" + "io" + "log/slog" "net/http" + "net/http/httptest" "testing" + "time" "github.com/stretchr/testify/assert" ) @@ -110,3 +115,39 @@ func TestWrapper_ResetClearsState(t *testing.T) { assert.Zero(t, w.read) assert.Zero(t, w.write) } + +func TestWriteLog_BuildsNothingWhenLevelDisabled(t *testing.T) { + l := &lm{log: slog.New(slog.NewTextHandler(io.Discard, &slog.HandlerOptions{ + Level: slog.LevelError, + }))} + + bw := &wrapper{code: http.StatusOK} + req := httptest.NewRequest(http.MethodGet, "/some/path?a=1&b=2", nil) + req.Header.Set("User-Agent", "test-agent/1.0") + req.Header.Set("Referer", "http://example.com/from") + start := time.Now() + + access := testing.AllocsPerRun(100, func() { + l.writeLog(true, req, bw, start) + }) + assert.Zero(t, access, "a discarded access-log line must allocate nothing") + + plain := testing.AllocsPerRun(100, func() { + l.writeLog(false, req, bw, start) + }) + assert.Zero(t, plain, "a discarded log line must allocate nothing") +} + +func TestWriteLog_EmittedWhenLevelEnabled(t *testing.T) { + var buf bytes.Buffer + l := &lm{log: slog.New(slog.NewTextHandler(&buf, &slog.HandlerOptions{Level: slog.LevelInfo}))} + + bw := &wrapper{code: http.StatusOK, read: 3, write: 7} + req := httptest.NewRequest(http.MethodGet, "/some/path", nil) + + l.writeLog(false, req, bw, time.Now()) + + assert.Contains(t, buf.String(), "http log") + assert.Contains(t, buf.String(), "read_bytes=3") + assert.Contains(t, buf.String(), "write_bytes=7") +} From 6da0b9a50f9828946e783c7eae2f358865cc2e22 Mon Sep 17 00:00:00 2001 From: Petro Chaikivskyi Date: Sat, 3 Oct 2026 16:38:46 +0000 Subject: [PATCH 2/2] fix: go lint --- middleware/log_test.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/middleware/log_test.go b/middleware/log_test.go index a739f039..caedc388 100644 --- a/middleware/log_test.go +++ b/middleware/log_test.go @@ -122,7 +122,7 @@ func TestWriteLog_BuildsNothingWhenLevelDisabled(t *testing.T) { }))} bw := &wrapper{code: http.StatusOK} - req := httptest.NewRequest(http.MethodGet, "/some/path?a=1&b=2", nil) + req := httptest.NewRequestWithContext(t.Context(), http.MethodGet, "/some/path?a=1&b=2", nil) req.Header.Set("User-Agent", "test-agent/1.0") req.Header.Set("Referer", "http://example.com/from") start := time.Now() @@ -143,7 +143,7 @@ func TestWriteLog_EmittedWhenLevelEnabled(t *testing.T) { l := &lm{log: slog.New(slog.NewTextHandler(&buf, &slog.HandlerOptions{Level: slog.LevelInfo}))} bw := &wrapper{code: http.StatusOK, read: 3, write: 7} - req := httptest.NewRequest(http.MethodGet, "/some/path", nil) + req := httptest.NewRequestWithContext(t.Context(), http.MethodGet, "/some/path", nil) l.writeLog(false, req, bw, time.Now())