content: package com.example.auction.config;
  
  import org.slf4j.Logger;
  import org.slf4j.LoggerFactory;
  import org.springframework.stereotype.Component;
  import org.springframework.web.servlet.HandlerInterceptor;
  
  import jakarta.servlet.http.HttpServletRequest;
  import jakarta.servlet.http.HttpServletResponse;
  
  @Component
  public class LoggingInterceptor implements HandlerInterceptor {
  
      private static final Logger logger = LoggerFactory.getLogger(LoggingInterceptor.class);
  
      @Override
      public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) {
          // Store start time for duration calculation
          request.setAttribute("startTime", System.currentTimeMillis());
          return true;
      }
  
      @Override
      public void afterCompletion(HttpServletRequest request, HttpServletResponse response,
              Object handler, Exception ex) {
  
          long startTime = (Long) request.getAttribute("startTime");
          long duration = System.currentTimeMillis() - startTime;
  
          String clientIP = getClientIP(request);
          String method = request.getMethod();
          String uri = request.getRequestURI();
          String queryString = request.getQueryString();
          String protocol = request.getProtocol();
          int status = response.getStatus();
  
          // Build the full URL
          String fullUrl = uri;
          if (queryString != null && !queryString.isEmpty()) {
              fullUrl += "?" + queryString;
          }
  
          // Format similar to FastAPI: IP:port - "METHOD /path HTTP/version" status
          String logMessage = String.format("%s - \"%s %s %s\" %d - %dms",
                  clientIP, method, fullUrl, protocol, status, duration);
  
          // Log at INFO level for successful requests, WARN for client errors, ERROR for server errors
          if (status >= 500) {
              logger.error(logMessage);
          } else if (status >= 400) {
              logger.warn(logMessage);
          } else {
              logger.info(logMessage);
          }
  
          // Log any exceptions
          if (ex != null) {
              logger.error("Request completed with exception: {}", ex.getMessage(), ex);
          }
      }
  
      private String getClientIP(HttpServletRequest request) {
          // Check for X-Forwarded-For header (common in load balancers/proxies)
          String xForwardedFor = request.getHeader("X-Forwarded-For");
          if (xForwardedFor != null && !xForwardedFor.isEmpty()) {
              return xForwardedFor.split(",")[0].trim();
          }
  
          // Check for X-Real-IP header
          String xRealIP = request.getHeader("X-Real-IP");
          if (xRealIP != null && !xRealIP.isEmpty()) {
              return xRealIP;
          }
  
          // Fall back to remote address
          String remoteAddr = request.getRemoteAddr();
          int remotePort = request.getRemotePort();
  
          // Include port if it's not a standard port
          if (remotePort > 0) {
              return remoteAddr + ":" + remotePort;
          }
  
          return remoteAddr;
      }
  }
  