fleet/server/service/middleware/log/log.go
Victor Lyuboslavsky de55ecf778
Migrate HTTP request logging from go-kit/log to slog (#39729)
<!-- Add the related story/sub-task/bug number, like Resolves #123, or
remove if NA -->
**Related issue:** Resolves #38889 

# Checklist for submitter

- [x] Changes file added for user-visible changes in `changes/`,
`orbit/changes/` or `ee/fleetd-chrome/changes`.

## Testing

- [x] Added/updated automated tests
- [x] QA'd all new/changed functionality manually
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->

## Summary by CodeRabbit

* **Refactor**
* Updated internal logging infrastructure to improve standardization and
maintainability. Logging functionality remains unchanged from an
end-user perspective.

<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-02-14 13:04:41 -06:00

79 lines
2.4 KiB
Go

package log
import (
"context"
"log/slog"
"net/http"
"github.com/fleetdm/fleet/v4/server/contexts/logging"
"github.com/go-kit/kit/endpoint"
kithttp "github.com/go-kit/kit/transport/http"
)
// Logged wraps an endpoint and adds the error if the context supports it
func Logged(next endpoint.Endpoint) endpoint.Endpoint {
return func(ctx context.Context, request interface{}) (response interface{}, err error) {
res, err := next(ctx, request)
if err != nil {
logging.WithErr(ctx, err)
return nil, err
}
if errResp, ok := res.(interface{ Error() error }); ok {
err = errResp.Error()
if err != nil {
logging.WithErr(ctx, err)
}
}
return res, nil
}
}
func LogRequestEnd(logger *slog.Logger) func(context.Context, http.ResponseWriter) context.Context {
return func(ctx context.Context, w http.ResponseWriter) context.Context {
logCtx, ok := logging.FromContext(ctx)
if !ok {
return ctx
}
logCtx.Log(ctx, logger)
return ctx
}
}
func LogResponseEndMiddleware(logger *slog.Logger, next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
next.ServeHTTP(w, r)
LogRequestEnd(logger)(r.Context(), w)
})
}
// NewLoggingMiddleware creates middleware that initializes logging context and logs requests.
// This middleware should be used for raw http.Handler endpoints (not go-kit endpoints).
// It initializes the logging context with request metadata and logs the request after completion.
func NewLoggingMiddleware(logger *slog.Logger) func(http.Handler) http.Handler {
return func(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
// Create logging context
lc := &logging.LoggingContext{}
// Populate request context with kithttp fields (method, URI, etc.)
ctx := logging.NewContext(kithttp.PopulateRequestContext(r.Context(), r), lc)
// Set start time
ctx = logging.WithStartTime(ctx)
// Add IP address information to logging context
remoteAddr, _ := ctx.Value(kithttp.ContextKeyRequestRemoteAddr).(string)
xForwardedFor, _ := ctx.Value(kithttp.ContextKeyRequestXForwardedFor).(string)
lc.SetExtras("ip_addr", remoteAddr, "x_for_ip_addr", xForwardedFor)
// Create new request with updated context
r = r.WithContext(ctx)
// Call next handler
next.ServeHTTP(w, r)
// Log the request
LogRequestEnd(logger)(ctx, w)
})
}
}