Skip to content

Commit

Permalink
Log additional fields
Browse files Browse the repository at this point in the history
- Client address & port
- Request port
- HTTP proto
- HTTP scheme
  • Loading branch information
kevinmcconnell committed Jul 29, 2024
1 parent d360c7a commit 2a581df
Show file tree
Hide file tree
Showing 3 changed files with 43 additions and 9 deletions.
34 changes: 28 additions & 6 deletions internal/server/logging_middleware.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,14 +25,18 @@ type loggingRequestContext struct {
}

type LoggingMiddleware struct {
logger *slog.Logger
next http.Handler
logger *slog.Logger
httpPort int
httpsPort int
next http.Handler
}

func WithLoggingMiddleware(logger *slog.Logger, next http.Handler) http.Handler {
func WithLoggingMiddleware(logger *slog.Logger, httpPort, httpsPort int, next http.Handler) http.Handler {
return &LoggingMiddleware{
logger: logger,
next: next,
logger: logger,
httpPort: httpPort,
httpsPort: httpsPort,
next: next,
}
}

Expand All @@ -55,13 +59,27 @@ func (h *LoggingMiddleware) ServeHTTP(w http.ResponseWriter, r *http.Request) {
h.next.ServeHTTP(writer, r)
elapsed := time.Since(started)

port := h.httpPort
scheme := "http"
if r.TLS != nil {
port = h.httpsPort
scheme = "https"
}

clientAddr, clientPort, err := net.SplitHostPort(r.RemoteAddr)
if err != nil {
clientAddr = r.RemoteAddr
clientPort = ""
}

remoteAddr := r.Header.Get("X-Forwarded-For")
if remoteAddr == "" {
remoteAddr = r.RemoteAddr
remoteAddr = clientAddr
}

attrs := []slog.Attr{
slog.String("host", r.Host),
slog.Int("port", port),
slog.String("path", r.URL.Path),
slog.String("request_id", r.Header.Get("X-Request-ID")),
slog.Int("status", writer.statusCode),
Expand All @@ -73,8 +91,12 @@ func (h *LoggingMiddleware) ServeHTTP(w http.ResponseWriter, r *http.Request) {
slog.String("req_content_type", r.Header.Get("Content-Type")),
slog.Int64("resp_content_length", writer.bytesWritten),
slog.String("resp_content_type", writer.Header().Get("Content-Type")),
slog.String("client_addr", clientAddr),
slog.String("client_port", clientPort),
slog.String("remote_addr", remoteAddr),
slog.String("user_agent", r.Header.Get("User-Agent")),
slog.String("proto", r.Proto),
slog.String("scheme", scheme),
slog.String("query", r.URL.RawQuery),
}

Expand Down
16 changes: 14 additions & 2 deletions internal/server/logging_middleware_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ import (
func TestMiddleware_LoggingMiddleware(t *testing.T) {
out := &strings.Builder{}
logger := slog.New(slog.NewJSONHandler(out, nil))
middleware := WithLoggingMiddleware(logger, http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
handler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
LoggingRequestContext(r).Service = "myapp"
LoggingRequestContext(r).Target = "upstream:3000"
LoggingRequestContext(r).RequestHeaders = []string{"X-Custom"}
Expand All @@ -28,7 +28,9 @@ func TestMiddleware_LoggingMiddleware(t *testing.T) {
w.Header().Set("X-Custom", "goodbye")
w.WriteHeader(http.StatusCreated)
fmt.Fprintln(w, "goodbye")
}))
})

middleware := WithLoggingMiddleware(logger, 80, 443, handler)

req := httptest.NewRequest("POST", "http://app.example.com/somepath?q=ok", bytes.NewReader([]byte("hello")))
req.Header.Set("X-Request-ID", "request-id")
Expand All @@ -46,9 +48,12 @@ func TestMiddleware_LoggingMiddleware(t *testing.T) {
Level string `json:"level"`
RequestID string `json:"request_id"`
Host string `json:"host"`
Port int `json:"port"`
Path string `json:"path"`
Method string `json:"method"`
Status int `json:"status"`
ClientAddr string `json:"client_addr"`
ClientPort string `json:"client_port"`
RemoteAddr string `json:"remote_addr"`
UserAgent string `json:"user_agent"`
ReqContentLength int64 `json:"req_content_length"`
Expand All @@ -61,6 +66,8 @@ func TestMiddleware_LoggingMiddleware(t *testing.T) {
ReqXCustom string `json:"req_x_custom"`
RespCacheControl string `json:"resp_cache_control"`
RespXCustom string `json:"resp_x_custom"`
Proto string `json:"proto"`
Scheme string `json:"scheme"`
}{}

err := json.NewDecoder(strings.NewReader(out.String())).Decode(&logline)
Expand All @@ -70,9 +77,12 @@ func TestMiddleware_LoggingMiddleware(t *testing.T) {
assert.Equal(t, "INFO", logline.Level)
assert.Equal(t, "request-id", logline.RequestID)
assert.Equal(t, "app.example.com", logline.Host)
assert.Equal(t, 80, logline.Port)
assert.Equal(t, "/somepath", logline.Path)
assert.Equal(t, "POST", logline.Method)
assert.Equal(t, http.StatusCreated, logline.Status)
assert.Equal(t, "192.0.2.1", logline.ClientAddr)
assert.Equal(t, "1234", logline.ClientPort)
assert.Equal(t, "192.168.1.1", logline.RemoteAddr)
assert.Equal(t, "Robot/1", logline.UserAgent)
assert.Equal(t, "application/json", logline.ReqContentType)
Expand All @@ -85,4 +95,6 @@ func TestMiddleware_LoggingMiddleware(t *testing.T) {
assert.Equal(t, "hello", logline.ReqXCustom)
assert.Equal(t, "public, max-age=3600", logline.RespCacheControl)
assert.Equal(t, "goodbye", logline.RespXCustom)
assert.Equal(t, "HTTP/1.1", logline.Proto)
assert.Equal(t, "http", logline.Scheme)
}
2 changes: 1 addition & 1 deletion internal/server/server.go
Original file line number Diff line number Diff line change
Expand Up @@ -112,7 +112,7 @@ func (s *Server) buildHandler() http.Handler {
var handler http.Handler

handler = s.router
handler = WithLoggingMiddleware(slog.Default(), handler)
handler = WithLoggingMiddleware(slog.Default(), s.config.HttpPort, s.config.HttpsPort, handler)
handler = WithRequestIDMiddleware(handler)

return handler
Expand Down

0 comments on commit 2a581df

Please sign in to comment.