diff options
Diffstat (limited to 'logging/logging.go')
| -rw-r--r-- | logging/logging.go | 53 |
1 files changed, 53 insertions, 0 deletions
diff --git a/logging/logging.go b/logging/logging.go new file mode 100644 index 0000000..8a2d0ee --- /dev/null +++ b/logging/logging.go @@ -0,0 +1,53 @@ +package logging + +import ( + "log/slog" + "net" + "net/http" + "os" + "strings" +) + +var ( + AppLog *slog.Logger + SecurityLog *slog.Logger +) + +// InitLoggers initializes the application and security loggers. +func InitLoggers() { + // For now, both loggers write to stdout. + // This could be configured to write to different files (e.g., app.log, security.log) + appWriter := os.Stdout + securityWriter := os.Stdout + + AppLog = slog.New(slog.NewTextHandler(appWriter, &slog.HandlerOptions{ + Level: slog.LevelInfo, + AddSource: false, // Include source file and line number for app logs + })) + + SecurityLog = slog.New(slog.NewTextHandler(securityWriter, &slog.HandlerOptions{ + Level: slog.LevelInfo, + // The default TextHandler format is `time=... level=... msg=... key=value`. + // This is structured and easily parsable, so we'll stick with it. + })) +} + +// GetClientIP extracts the client IP address from the request. +// It prioritizes the X-Forwarded-For header to work behind a reverse proxy. +func GetClientIP(r *http.Request) string { + // Check the X-Forwarded-For header first. + forwardedFor := r.Header.Get("X-Forwarded-For") + if forwardedFor != "" { + // The header can contain a comma-separated list of IPs. The client IP is the first one. + ips := strings.Split(forwardedFor, ",") + return strings.TrimSpace(ips[0]) + } + + // If the header is not present, fall back to RemoteAddr. + ip, _, err := net.SplitHostPort(r.RemoteAddr) + if err != nil { + // If parsing fails (e.g., no port), return the raw RemoteAddr. + return r.RemoteAddr + } + return ip +} |
