woodisco 2024. 5. 22. 10:26

 
♧ 전체 코드 : https://github.com/woodisco/feign-client

GitHub - woodisco/feign-client: feign-client 공부

feign-client 공부. Contribute to woodisco/feign-client development by creating an account on GitHub.

github.com

 

Logger 구현

① FeignCustomLogger 작성

@RequiredArgsConstructor
public class FeignCustomLogger extends Logger {

    @Override
    protected void log(String configKey, String format, Object... args) {
        System.out.println(String.format(methodTag(configKey) + format, args));
    }

    @Override
    protected void logRequest(String configKey, Level logLevel, Request request) {
        System.out.println(request);
    }

    @Override
    protected Response logAndRebufferResponse(String configKey, Level logLevel, Response response, long elapsedTime) throws IOException {
        String protocolVersion = resolveProtocolVersion(response.protocolVersion());
        String reason = response.reason() != null
                && logLevel.compareTo(Level.NONE) > 0 ? " " + response.reason() : "";
        int status = response.status();
        log(configKey, "<--- %s %s%s (%sms)", protocolVersion, status, reason, elapsedTime);
        if (logLevel.ordinal() >= Level.HEADERS.ordinal()) {

            for (String field : response.headers().keySet()) {
                if (shouldLogResponseHeader(field)) {
                    for (String value : valuesOrEmpty(response.headers(), field)) {
                        log(configKey, "%s: %s", field, value);
                    }
                }
            }

            int bodyLength = 0;
            if (response.body() != null && !(status == 204 || status == 205)) {
                // HTTP 204 No Content "...response MUST NOT include a message-body"
                // HTTP 205 Reset Content "...response MUST NOT include an entity"
                if (logLevel.ordinal() >= Level.FULL.ordinal()) {
                    log(configKey, ""); // CRLF
                }
                byte[] bodyData = Util.toByteArray(response.body().asInputStream());
                bodyLength = bodyData.length;
                if (logLevel.ordinal() >= Level.HEADERS.ordinal() && bodyLength > 0) {
                    log(configKey, "%s", decodeOrDefault(bodyData, UTF_8, "Binary data"));
                }
                // elapsedTime이 지정한 시간보다 오래 걸릴 경우, 로그 출력
                if (elapsedTime > DEFAULT_SLOW_API_TIME) {
                    log(configKey, "[%s] elapsedTime : %s", SLOW_API_NOTICE, elapsedTime);
                }
                log(configKey, "<--- END HTTP (%s-byte body)", bodyLength);
                return response.toBuilder().body(bodyData).build();
            } else {
                log(configKey, "<--- END HTTP (%s-byte body)", bodyLength);
            }
        }
        return response;
    }
}
▷ log 메소드 : log의 형식을 결정한다.

▷ logRequest 메서드 :
여기서 logLevel 은 aplication.yaml 에서 정의한 것이며 동작순서는 logRequest 메서드 진입 -> 외부 요청 -> logAndRebufferResponse 메서드 진입순으로 이루어진다. 

▷ logAndRebufferResponse 메서드 :
처리 내용은 상위 Logger 클래스에서 복사한 내용으로 logAndRebufferResponse 메서드 내에선 Request, Response에 대한 정보를 log로 남길 수 있다.

② FeignConfig 작성
FeignCustomLogger는 글로벌한 설정값이기 때문에 FeignConfig에 추가하여 선언하기.

@Configuration
public class FeignConfig {
    @Bean
    public Logger feignLogger() {
        return new FeignCustomLogger();
    }
}

 

출처 : 패스트캠퍼스 10개 프로젝트로 완성하는 백엔드 웹개발(Java/Spring) 초격차 패키지 Online