본문 바로가기
Java & Spring

Spring에서 서버 상태를 체크하는 Interceptor !!

by 모닝위즈 2023. 9. 14.
반응형

Spring Interceptor에 등록하여 서버 상태를 예쁘게 출력해주는 Interceptor .

아래 그림처럼 Console창에 아주 예쁘게 뿌려준다.

Class 명 :  MitwServerStatusCheckerInterceptor

전문 제공

import org.springframework.lang.Nullable;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

/**
 * Mitw Server Status Checker Interceptor : for heap memory / request & response status / processing speed check
 *
 * @author
 * @version 1.0
 * @see <pre>
 *  Modification Information
 *
 *     수정일       / 수정자    / 수정내용
 *     ------------------------------------------
 *     2018-10-10 /  Mitw   / 최초 생성
 * </pre>
 * @since 2018-10-10
 */
public class MitwServerStatusCheckerInterceptor implements HandlerInterceptor {
    String process_name, memoryStr;
    long start_time, server_end_time, view_end_time;
    public static final String ANSI_RESET = "\u001B[0m";
    public static final String ANSI_YELLOW = "\u001B[33m";
    public static final String ANSI_PURPLE = "\u001B[35m";

    public String getProcess_name() {
        return process_name;
    }

    public void setProcess_name(String process_name) {
        this.process_name = process_name;
    }

    public long getStart_time() {
        return start_time;
    }

    public void setStart_time(long start_time) {
        this.start_time = start_time;
    }

    public long getServer_end_time() {
        return server_end_time;
    }

    public void setServer_end_time(long server_end_time) {
        this.server_end_time = server_end_time;
    }

    public long getView_end_time() {
        return view_end_time;
    }

    public void setView_end_time(long view_end_time) {
        this.view_end_time = view_end_time;
    }

    public void preHandle(HttpServletRequest request) {
        this.setProcess_name(String.valueOf(request.getRequestURL() + (request.getQueryString() != null ? ("?" + request.getQueryString()) : "")));
        this.setStart_time(System.currentTimeMillis());
    }

    public void postHandle() {
        heapCheck();
        this.setServer_end_time(System.currentTimeMillis());
    }

    public String getMemoryStr() {
        return memoryStr;
    }

    public void setMemoryStr(String memoryStr) {
        this.memoryStr = memoryStr;
    }

    public void heapCheck() {
        int mb = 1024 * 1024;
        Runtime runtime = Runtime.getRuntime();
        long nm = (runtime.totalMemory() - runtime.freeMemory()), nmp = ((nm * 100) / runtime.totalMemory());
        this.setMemoryStr(ANSI_YELLOW + "\uD83D\uDC38 Heap Status [ Now Memory : " + (double) (nm / mb) + "mb (" + (double) nmp + "%), Free Memory : " + runtime.freeMemory() / mb + "mb, Max Memory : " + runtime.maxMemory() / mb + "mb ]" + ANSI_RESET);

    }

    public String getRequestStatus(HttpServletRequest request) {
        return ANSI_YELLOW + "\uD83D\uDC38 Request Status [ method : " + request.getMethod() + ", contentLength : " + request.getContentLength() + ", request contentType : " + request.getContentType() + " ]" + ANSI_RESET;
    }

    public String getResponseStatus(HttpServletResponse response, @Nullable Exception ex) {
        String status = "HTTP statusCode : " + response.getStatus() + ", bufferSize : " + response.getBufferSize() + ", Response contentType : " + response.getContentType() + ", encoding : " + response.getCharacterEncoding();
        try {
            String[] ets = ex.toString().split(":", 2);
            status += ", throw Exception : " + ets[0];
        } catch (Exception e) {
        }
        return ANSI_YELLOW + "\uD83D\uDC38 Response Status [ " + status + " ]" + ANSI_RESET;

    }

    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, @Nullable Exception ex) {
        this.setView_end_time(System.currentTimeMillis());
        System.out.println(ANSI_PURPLE + "━━─*" + ANSI_RESET + " Mitw Server Status Checker " + ANSI_PURPLE + "*─━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━" + ANSI_RESET);
        System.out.println(this.getMemoryStr());
        System.out.println(this.toString());
        System.out.println(this.getRequestStatus(request));
        System.out.println(this.getResponseStatus(response, ex));
        System.out.println(ANSI_PURPLE + "────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────" + ANSI_RESET);
    }

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        preHandle(request);
        return true;
    }

    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, @Nullable Exception ex) throws Exception {
        afterCompletion(request, response, ex);
    }

    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
        postHandle();
    }

    @Override
    public String toString() {
        double total_process_time = (double) (view_end_time - start_time) / 1000;
        String status = "";
        if (total_process_time <= 0.5) {
            status = "Pleasant \uD83D\uDC4D";
        } else if (total_process_time > 0.5 && total_process_time <= 1.0) {
            status = "Good \uD83D\uDE42";
        } else if (total_process_time > 1.0 && total_process_time <= 1.9) {
            status = "normal \uD83D\uDE10";
        } else {
            status = "bad \uD83D\uDC80";
        }
        return ANSI_YELLOW + "\uD83D\uDC38 Process Speed [ Status : " + status + " , Request URL : " + process_name + ", Server Process Speed : " + (double) (server_end_time - start_time) / 1000 + "ms, View Rendering Speed : " + (double) (view_end_time - server_end_time) / 1000 + "ms, Server Total Process Speed : " + total_process_time + "ms ]" + ANSI_RESET;

    }
}

 

인터셉터에 등록. (아래는 인터셉터 등록의 예시)

import com.tistory.mitw.application.common.interceptor.MitwServerStatusCheckerInterceptor;

@Configuration
@EnableWebMvc
@EnableAsync
@EnableScheduling
@ComponentScan(basePackages = {"com.tistory.mitw.application"})
public class WebMvcConfig implements WebMvcConfigurer {

 .... 중략



   /**
    * 인터셉터 설정
    *
    * @param registry
    */
   @Override
   public void addInterceptors(InterceptorRegistry registry) {
      registry.addInterceptor(mitwServerStatusCheckerInterceptor())
              .addPathPatterns("/**")
              .excludePathPatterns("/resources/**", "/images/**", "/css/**", "/cmmn/**", "/js/**");
   }


   /**
    * SSC 등록
    * */
   @Bean
   public MitwServerStatusCheckerInterceptor mitwServerStatusCheckerInterceptor() {
      return new MitwServerStatusCheckerInterceptor();
   }



 .... 중략
 
 
 
}

 

Configure 설정이 변경되었으므로, HotSwap이 있더라도 재기동을 한번 때립시다.

 

Exception : Out Of Memory : 갓형욱 process 1979

 

자 다 등록했으면 이 사람의 상태를 체크해보자. 

 

 

다행히 gc가 돌아가고 있군요.

사람은 쉽게 죽지 않습니다. 

 

 

AOP 써라.

댓글