diff --git a/headers/consts.go b/headers/consts.go index 3102ce4..7eb8460 100644 --- a/headers/consts.go +++ b/headers/consts.go @@ -5,6 +5,7 @@ const ( XForwardedMethod = "X-Forwarded-Method" XForwardedHost = "X-Forwarded-Host" XForwardedUri = "X-Forwarded-Uri" + XForwardedFor = "X-Forwarded-For" Accept = "Accept" UserAgent = "User-Agent" Cookie = "Cookie" diff --git a/logger.go b/logger.go index c8a64d3..7143d08 100644 --- a/logger.go +++ b/logger.go @@ -6,7 +6,10 @@ import ( "net" "net/http" "os" + "runtime/debug" "time" + + "github.com/cego/go-lib/headers" ) type Logger interface { @@ -36,26 +39,44 @@ func NewLogger() Logger { return slog.New(slog.NewJSONHandler(os.Stdout, opts)) } -func GetSlogAttrFromRequest(req *http.Request) slog.Attr { - userAgent := req.Header.Get("User-Agent") - xForwardedFor := req.Header.Get("X-Forwarded-For") - remoteAddr := req.RemoteAddr +func GetSlogAttrFromError(err error) slog.Attr { + var attrs []slog.Attr - clientIp, _, _ := net.SplitHostPort(remoteAddr) + attrs = append(attrs, slog.String("error.message", err.Error())) + attrs = append(attrs, slog.String("error.stack_trace", string(debug.Stack()))) + + attr := slog.Attr{} + attr.Value = slog.GroupValue(attrs...) + return attr +} +func GetSlogAttrFromRequest(req *http.Request) slog.Attr { var attrs []slog.Attr + reqHeaders := req.Header + + remoteAddr := req.RemoteAddr + clientIp, _, _ := net.SplitHostPort(remoteAddr) attrs = append(attrs, slog.String("client.ip", clientIp)) - attrs = append(attrs, slog.String("user_agent.original", userAgent)) - if xForwardedFor != "" { - attrs = append(attrs, slog.String("client.address", xForwardedFor)) - } - headers := req.Header.Clone() - headers.Set("Cookie", "") - headers.Set("Authorization", "") - headersJsonMarshalled, _ := json.Marshal(headers) - attrs = append(attrs, slog.String("http.request.headers.raw", string(headersJsonMarshalled))) + if reqHeaders.Get(headers.XForwardedFor) != "" { + attrs = append(attrs, slog.String("client.address", reqHeaders.Get(headers.XForwardedFor))) + } + if reqHeaders.Get(headers.UserAgent) != "" { + attrs = append(attrs, slog.String("user_agent.original", reqHeaders.Get(headers.UserAgent))) + } + + h := reqHeaders.Clone() + if h.Get(headers.Cookie) != "" { + h.Set(headers.Cookie, "") + } + if h.Get(headers.Authorization) != "" { + h.Set(headers.Authorization, "") + } + if len(h) > 0 { + headersJsonMarshalled, _ := json.Marshal(h) + attrs = append(attrs, slog.String("http.request.headers.raw", string(headersJsonMarshalled))) + } attr := slog.Attr{} attr.Value = slog.GroupValue(attrs...) diff --git a/logger_test.go b/logger_test.go index 8af0592..00e1b63 100644 --- a/logger_test.go +++ b/logger_test.go @@ -1,11 +1,12 @@ package cego import ( - "fmt" - "github.com/stretchr/testify/mock" + "errors" "net/http" "net/http/httptest" "testing" + + "github.com/stretchr/testify/mock" ) func TestLogger(t *testing.T) { @@ -14,10 +15,18 @@ func TestLogger(t *testing.T) { logger := NewMockLogger() logger.Debug("Epic request data is attached", GetSlogAttrFromRequest(req)) - fmt.Println(GetSlogAttrFromRequest(req)) - - // TODO: Figure out how mock.MatchedBy is working instead of using mock.Anything + // TODO: Figure out how to assert slog.Attr logger.AssertCalled(t, "Debug", "Epic request data is attached", mock.Anything) }) + t.Run("it can get err attr", func(t *testing.T) { + err := errors.New("test error") + logger := NewMockLogger() + + logger.Error("Something has failed here", GetSlogAttrFromError(err)) + + // TODO: Figure out how to assert slog.Attr + logger.AssertCalled(t, "Error", "Something has failed here", mock.Anything) + }) + } diff --git a/readme.md b/readme.md index d70cfc6..4f0879e 100644 --- a/readme.md +++ b/readme.md @@ -38,7 +38,6 @@ handleFunc := func(writer http.ResponseWriter, request *http.Request) { // Setting your logger as the global one logger := log.NewLogger() -slog.SetDefault(logger) slog.Debug("Also in ecs format") ```