Skip to content

Commit

Permalink
Include target in request logging
Browse files Browse the repository at this point in the history
  • Loading branch information
kevinmcconnell committed Mar 25, 2024
1 parent 4e798c5 commit 9588875
Show file tree
Hide file tree
Showing 3 changed files with 26 additions and 0 deletions.
13 changes: 13 additions & 0 deletions internal/server/logging_middleware.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package server

import (
"bufio"
"context"
"encoding/json"
"errors"
"io"
Expand All @@ -12,6 +13,10 @@ import (
"time"
)

type contextKey string

var contextKeyTarget = contextKey("target")

type LoggingMiddlewareLine struct {
Timestamp string `json:"@timestamp"`
Message string `json:"message"`
Expand All @@ -25,6 +30,9 @@ type LoggingMiddlewareLine struct {
Event struct {
Duration int64 `json:"duration"`
} `json:"event"`
Destination struct {
Address string `json:"address"`
} `json:"destination"`
HTTP struct {
Request struct {
Method string `json:"method"`
Expand Down Expand Up @@ -67,6 +75,10 @@ func NewLoggingMiddleware(w io.Writer, next http.Handler) *LoggingMiddleware {
func (h *LoggingMiddleware) ServeHTTP(w http.ResponseWriter, r *http.Request) {
writer := newResponseWriter(w)

var target string
ctx := context.WithValue(r.Context(), contextKeyTarget, &target)
r = r.WithContext(ctx)

started := time.Now()
h.next.ServeHTTP(writer, r)
elapsed := time.Since(started)
Expand All @@ -90,6 +102,7 @@ func (h *LoggingMiddleware) ServeHTTP(w http.ResponseWriter, r *http.Request) {
line.Log.Level = "INFO"
line.Client.IP = clientIP
line.Client.Port = clientPort
line.Destination.Address = target
line.Event.Duration = elapsed.Nanoseconds()
line.HTTP.Request.Body.Bytes = r.ContentLength
line.HTTP.Request.Method = r.Method
Expand Down
7 changes: 7 additions & 0 deletions internal/server/logging_middleware_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,12 @@ import (
func TestMiddleware_LoggingMiddleware(t *testing.T) {
out := &strings.Builder{}
middleware := NewLoggingMiddleware(out, http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
// Record a value for the `target` context key.
target, ok := r.Context().Value(contextKeyTarget).(*string)
if ok {
*target = "upstream:3000"
}

w.Header().Set("Content-Type", "text/html")
w.WriteHeader(http.StatusCreated)
fmt.Fprintln(w, "goodbye")
Expand All @@ -35,6 +41,7 @@ func TestMiddleware_LoggingMiddleware(t *testing.T) {

assert.Equal(t, "Request", logline.Message)
assert.Equal(t, "INFO", logline.Log.Level)
assert.Equal(t, "upstream:3000", logline.Destination.Address)

assert.Equal(t, "http", logline.URL.Scheme)
assert.Equal(t, "example.com", logline.URL.Domain)
Expand Down
6 changes: 6 additions & 0 deletions internal/server/router.go
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,12 @@ func (r *Router) ServeHTTP(w http.ResponseWriter, req *http.Request) {
if target == nil {
w.WriteHeader(http.StatusServiceUnavailable)
} else {
// Record the target that served the request, if its context is available.
targetIdentifer, ok := req.Context().Value(contextKeyTarget).(*string)
if ok {
*targetIdentifer = target.Target()
}

target.ServeHTTP(w, req)
}
}
Expand Down

0 comments on commit 9588875

Please sign in to comment.