

0 / 2 embers
0 / 3000 xp
click for more info
Complete a lesson to start your streak
click for more info
Difficulty: 6
click for more info
Not enough gems
Cost: 6 gems
1: Best Practices
incomplete
2: Timestamps
incomplete
3: Minimal Logging
incomplete
4: Redundant Logs
incomplete
5: One Log Per Event
incomplete
This lesson's interactive features are locked, please to keep using them
This might seem obvious (and most default loggers do this), but always include timestamps in your logs.
Even if your logs are complete jank, timestamps at least let us do brute-force investigation. Take a look:
2023/10/01 12:34:57 INFO: User "alice" logged in
2023/10/01 12:34:57 INFO: Opening profile configuration for user "alice"
2023/10/01 12:34:57 ERROR: File not found
Each log entry alone isn't very useful, but the timestamps allow us to deduce that they're probably related, and that the "File not found" error likely relates to opening Alice's profile configuration file.
One exception is in automated tests. You may want to remove or overwrite timestamps for deterministic output.
Write a test for requestLogger that verifies timestamped output.
func Test_requestLogger(t *testing.T) {
logBuffer := &bytes.Buffer{}
logger := slog.New(slog.NewTextHandler(logBuffer, &slog.HandlerOptions{
ReplaceAttr: func(groups []string, a slog.Attr) slog.Attr {
if a.Key == slog.TimeKey {
return slog.Time(slog.TimeKey, time.Date(2023, 10, 1, 12, 34, 57, 0, time.UTC))
}
return a
},
}))
requestLoggerMiddleware := requestLogger(logger)
dummyHandler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {})
loggedHandler := requestLoggerMiddleware(dummyHandler)
req := httptest.NewRequest("GET", "http://lin.ko/api/stats", nil)
rr := httptest.NewRecorder()
loggedHandler.ServeHTTP(rr, req)
const expectedLogString = `time=2023-10-01T12:34:57.000Z level=INFO msg="Served request" method=GET path=/api/stats client_ip=192.0.2.1:1234` + "\n"
const expectedStatusCode = http.StatusOK
// replace the .Skip() call with two checks to verify the log string and status code here
// If either doesn't match, use t.Errorf to report the failure with a helpful message.
t.Skip()
}
Notice that we're using the httptest package to create a dummy HTTP request and response recorder. This is a cool way to "end-to-end" test an individual HTTP handler.
logBuffer.String() to the expected log string.rr.Code to the expected status code.Run and submit the CLI tests from the root of the Linko repo.