[MSA] Logging Filter

jineey·2024년 11월 5일

MSA

목록 보기
5/36

API Gateway

Logging Filter

📌 Logging Filter란?

  • 필터 수행 과정중 발생하는 행위에 대한 로그를 남기기 위한 필터

✅ 필터 실행 순서

  • Global Filter ➡ Custom Filter ➡ Logging Filter

✅ 필터 종료 순서

  • Logging Filter ➡ Custom Filter ➡ Global Filter

⭐ 필터 실행 순서와 종료 순서는 역순

📌 전체적인 Gateway 흐름


📌 소스코드

  • LoggingFilter.java 추가
package com.example.apigatewayservice.filter;

import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import org.springframework.cloud.gateway.filter.GatewayFilter;
import org.springframework.cloud.gateway.filter.OrderedGatewayFilter;
import org.springframework.cloud.gateway.filter.factory.AbstractGatewayFilterFactory;
import org.springframework.core.Ordered;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.http.server.reactive.ServerHttpResponse;
import org.springframework.stereotype.Component;
import reactor.core.publisher.Mono;

@Component
@Slf4j
public class LoggingFilter extends AbstractGatewayFilterFactory<LoggingFilter.Config> {

    public LoggingFilter() {
        super(Config.class);
    }

    @Override
    public GatewayFilter apply(Config config) {

        GatewayFilter filter = new OrderedGatewayFilter((exchange, chain) -> {
            ServerHttpRequest request = exchange.getRequest();
            ServerHttpResponse response = exchange.getResponse();

            log.info("Logging Filter basemessage: {}", config.getBaseMessage());

            if(config.isPreLogger()){
                log.info("Logging Pre Filter : request_id = {}", request.getId());
            }

            //Custom Post Filter
            return chain.filter(exchange).then(Mono.fromRunnable(()-> {
                if (config.isPostLogger()) {
                    log.info("Logging Post Filter : request_code = {}", response.getStatusCode());
                }
            }));

        }, Ordered.HIGHEST_PRECEDENCE);
        return filter;
    }

    @Data
    public static class Config {
        private String baseMessage;
        private boolean preLogger;
        private boolean postLogger;
    }

}

💡 OrderedGatewayFilter

  • GatewayFilter는 인스턴스이므로 직접 사용 불가능하기 때문에 OrderedGatewayFilter를 사용.OrderedGatewayFilter 내부
  • 생성자 구현을 위해 GatewayFilterorder 지정 필요하여 filter() 메서드 구현
  • 객체 ServerWebExchange는 Server Request, Response를 사용하게 도와줌 ➡ Response, Request 정보를 알 수 있음

💡 Ordered.HIGHEST_PRECEDENCE

  • application.yml 수정
spring:
  application:
    name: apigateway-service
  cloud:
    gateway:
      routes:
        - id: first-service
          uri: http://localhost:8081/
          predicates:
            - Path=/first-service/**
          filters:
            - CustomFilter
#              - AddRequestHeader=first-request,first-request-header2
#              - AddResponseHeader=first-response,first-response-header2
        - id: second-service
          uri: http://localhost:8082/
          predicates:
            - Path=/second-service/**
          filters:
            - name: CustomFilter
            - name: LoggingFilter
              args:
                baseMessage: Hi, there.
                preLogger: true
                postLogger: true
#              - AddRequestHeader=second-request,second-request-header2
#              - AddResponseHeader=second-response,second-response-header2
      default-filters:
        - name: GlobalFilter
          args:
            baseMessage: Spring Cloud Gateway Global Filter
            preLogger: true
            postLogger: true


server:
  port: 8000

eureka:
  client:
    register-with-eureka: false
    fetch-registry: false
    service-url:
      defaultZone: http://localhost:8761/eureka
  • Logging Filter는 Second-service에만 적용
  • 파라미터값이 있을 경우에는 - 를 사용하여 구분 필요
# 파라미터값 없음
spring:
  cloud:
    gateway:
      routes:
        - id: second-service
          uri: http://localhost:8082/
          predicates:
            - Path=/second-service/**
          filters:
            name: CustomFilter
            name: LoggingFilter
# 파라미터값 있음
spring:
  cloud:
    gateway:
      routes:
        - id: second-service
          uri: http://localhost:8082/
          predicates:
            - Path=/second-service/**
          filters:
            - name: CustomFilter
            - name: LoggingFilter
              args:
                baseMessage: Hi, there.
                preLogger: true
                postLogger: true

📌 실행결과

  • first-service 실행 시
    ✅ first-service에는 Logging Filter를 적용하지 않았기 때문에 콘솔에 Logging 관련하여 메시지가 뜨지 않음
  • second-service 실행 시
    ✅ Logging Filter가 먼저 실행된 이유?
    Ordered.HIGHEST_PRECEDENCE 를 사용하여 Logging Filter의 우선순위를 가장 높게 설정했기 때문에 가장 먼저 실행됨
profile
새싹 개발자

0개의 댓글