Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 24 additions & 4 deletions context.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package httplog
import (
"context"
"log/slog"
"sync"
)

const (
Expand All @@ -15,16 +16,35 @@ func (c *ctxKeyLogAttrs) String() string {
return "httplog attrs context"
}

type logData struct {
mu sync.RWMutex
attrs []slog.Attr
}

// SetAttrs sets the attributes on the request log.
func SetAttrs(ctx context.Context, attrs ...slog.Attr) {
if ptr, ok := ctx.Value(ctxKeyLogAttrs{}).(*[]slog.Attr); ok && ptr != nil {
*ptr = append(*ptr, attrs...)
if ptr, ok := ctx.Value(ctxKeyLogAttrs{}).(*logData); ok && ptr != nil {
ptr.mu.Lock()
defer ptr.mu.Unlock()
ptr.attrs = append(ptr.attrs, attrs...)
}
}

func lockData(ctx context.Context) {
if ptr, ok := ctx.Value(ctxKeyLogAttrs{}).(*logData); ok && ptr != nil {
ptr.mu.RLock()
}
}

func unlockData(ctx context.Context) {
if ptr, ok := ctx.Value(ctxKeyLogAttrs{}).(*logData); ok && ptr != nil {
ptr.mu.RUnlock()
}
}

func getAttrs(ctx context.Context) []slog.Attr {
if ptr, ok := ctx.Value(ctxKeyLogAttrs{}).(*[]slog.Attr); ok && ptr != nil {
return *ptr
if ptr, ok := ctx.Value(ctxKeyLogAttrs{}).(*logData); ok && ptr != nil {
return ptr.attrs
}

return nil
Expand Down
5 changes: 4 additions & 1 deletion middleware.go
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ func RequestLogger(logger *slog.Logger, o *Options) func(http.Handler) http.Hand

return func(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
ctx := context.WithValue(r.Context(), ctxKeyLogAttrs{}, &[]slog.Attr{})
ctx := context.WithValue(r.Context(), ctxKeyLogAttrs{}, &logData{})

logReqBody := o.LogRequestBody != nil && o.LogRequestBody(r)
logRespBody := o.LogResponseBody != nil && o.LogResponseBody(r)
Expand All @@ -56,6 +56,9 @@ func RequestLogger(logger *slog.Logger, o *Options) func(http.Handler) http.Hand
start := time.Now()

defer func() {
lockData(ctx)
defer unlockData(ctx)

var logAttrs []slog.Attr

if rec := recover(); rec != nil {
Expand Down