Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Step3-3] observability 추가. #111

Open
wants to merge 5 commits into
base: Sung-Heon
Choose a base branch
from

Conversation

Sung-Heon
Copy link
Collaborator

  1. 관측성 스택 구성 (Docker Compose)
    Zipkin: 분산 트레이싱 (포트: 9411)
    Prometheus: 메트릭 수집 (포트: 9090)
    Grafana: 대시보드 시각화 (포트: 3000)
    네트워크 및 볼륨 설정
  2. 요청 로깅 필터 추가
    RequestLoggingFilter 클래스 구현
    모든 HTTP 요청 메서드, URI, 상태 코드, 처리 시간, IP 주소 로깅
    POST/PUT/PATCH 요청의 본문(body) 내용 로깅
    ContentCachingRequestWrapper를 사용하여 요청 본문 캡처

@Sung-Heon Sung-Heon requested a review from Hyune-c March 11, 2025 04:53
if (clientIp == null || clientIp.isEmpty() || "unknown".equalsIgnoreCase(clientIp)) {
clientIp = request.getRemoteAddr();
}
return clientIp;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

이 로직 의도가 무엇인가요?

  • if 문 3개의 조건이 같습니다?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ip를 찾기 위한 겁니다.

  1. 같은 조건이 3번 반복하는 이유는 헤더가 X-Forwarded-For 일지, Proxy-Client-IP일지, WL-Proxy-Client-IP
    일지 모르기 때문입니다. 비율이 높은 순으로 되어있습니다.
  2. 음.. 저도 첨에 봤을땐 더 좋은 방법이 없나 고민을 했었는데 for문을 돌리는것보다 이게 직관적이라고 생각했고, 영어로든 한국어로든 ip를 찾는 코드스니펫으로 많이 나오는 코드더라구요.
    그렇다면 커뮤니케이션 비용상 굳이 더 창의적인 방법을 고안하거나 효율적인 방법을 고민할 필요가 없겠다는 생각이었습니다.
    클라이언트 ip를 가져오는게 그렇게 대단한 로직이 필요한것은 아니니까요.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

사실 저는 이런 코드를 작성해본 적은 없습니다.

  • 실무에서는 보통 솔루션을 (datadog, newrelic, sentry) 사용하기 때문 입니다.
    private String getClientIp(HttpServletRequest request) {
        String clientIp = request.getHeader("X-Forwarded-For");
        if (clientIp == null || clientIp.isEmpty() || "unknown".equalsIgnoreCase(clientIp)) {
            clientIp = request.getHeader("Proxy-Client-IP"); // clientIp 가 이 값으로 retrun 되는 경우가 발생할 수 있는가?
        }
        if (clientIp == null || clientIp.isEmpty() || "unknown".equalsIgnoreCase(clientIp)) {
            clientIp = request.getHeader("WL-Proxy-Client-IP"); // clientIp 가 이 값으로 retrun 되는 경우가 발생할 수 있는가?
        }
        if (clientIp == null || clientIp.isEmpty() || "unknown".equalsIgnoreCase(clientIp)) {
            clientIp = request.getRemoteAddr(); // 앞의 if 문에서 true 가 나오면 여기도 true 가 나오기 때문에 항상 이 값으로 나오는거 아닌가?
        }
        return clientIp;
    }

근데 전 아무리 읽어봐도 해당 로직이 이해가 잘 안되요.
제가 주석 단 것에 답변을 주실 수 있나요?


통상적으로 쓰이는 코드 스니펫이라는 것은 이해하는데, 그것을 가져와서 내 애플리케이션에 붙이면 이제 내 코드가 되는 것 입니다.

  • 향후 이것으로 이슈가 되도 원본 글 작성자를 탓할 수는 없으니까요.
  • 관련되어 자체 테스트라도 진행 해보셨나요?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

curl -s -H "X-Forwarded-For: 123.456.789.0" http://localhost:8080/shorten-url/search

인경우,
첫번째 clientIp에 담김.
세가지 조건문 다 false.
그대로 return
Screenshot 2025-03-12 at 8 33 26 PM

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

curl -s -H "Proxy-Client-IP: 123.456.789.0" http://localhost:8080/shorten-url/search 

인경우,
첫번째 clientIp ==null
첫번째 조건문 true
clientIp = request.getHeader("Proxy-Client-IP"); // clientIp 가 이 값으로 retrun 되는 경우가 발생할 수 있는가?
여기서 clientIp= 123.456.789.0
이제 null 아니므로 두번째 세번째 조건문 pass
Screenshot 2025-03-12 at 8 33 59 PM

Copy link
Collaborator Author

@Sung-Heon Sung-Heon Mar 12, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Screenshot 2025-03-12 at 8 34 40 PM

마찬가지로 3번째도 잘나옵니다.

Copy link
Collaborator Author

@Sung-Heon Sung-Heon Mar 12, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

통상적으로 쓰이는 코드 스니펫이라는 것은 이해하는데, 그것을 가져와서 내 애플리케이션에 붙이면 이제 내 코드가 되는 것 입니다.

네 그렇게 생각하고 있습니다.

관련되어 자체 테스트라도 진행 해보셨나요?

네 진행한거 첨부하였습니다.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

private String getClientIp(HttpServletRequest request) {
    // 확인할 헤더 목록을 우선순위 순서대로 배열에 저장
    String[] headerNames = {
        "X-Forwarded-For", 
        "Proxy-Client-IP", 
        "WL-Proxy-Client-IP"
    };
    
    // 각 헤더를 순차적으로 확인
    for (String headerName : headerNames) {
        String headerValue = request.getHeader(headerName);
        // 유효한 IP 주소가 있는 경우 즉시 반환
        if (isValidIp(headerValue)) {
            return headerValue;
        }
    }
    
    // 모든 헤더가 유효하지 않은 경우 remoteAddr 반환
    return request.getRemoteAddr();
}

/**
 * IP 주소가 유효한지 확인
 * null이 아니고, 비어있지 않고, "unknown"이 아닌 경우 유효함
 */
private boolean isValidIp(String ip) {
    return ip != null && !ip.isEmpty() && !"unknown".equalsIgnoreCase(ip);
}

흠.. 이렇게 하는게 나을뻔했네요.
(사실 ip주소가져오는 코드를 볼일이 별로없으니..그냥 직관적으로 이해되게.)

@Sung-Heon
Copy link
Collaborator Author

다시보니까 filter랑 logger랑 분리하는게 나을것 같아서 그부분도 살짝(?) 리팩토링했습니다.

@Sung-Heon Sung-Heon requested a review from Hyune-c March 12, 2025 00:22
if (clientIp == null || clientIp.isEmpty() || "unknown".equalsIgnoreCase(clientIp)) {
clientIp = request.getRemoteAddr();
}
return clientIp;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

사실 저는 이런 코드를 작성해본 적은 없습니다.

  • 실무에서는 보통 솔루션을 (datadog, newrelic, sentry) 사용하기 때문 입니다.
    private String getClientIp(HttpServletRequest request) {
        String clientIp = request.getHeader("X-Forwarded-For");
        if (clientIp == null || clientIp.isEmpty() || "unknown".equalsIgnoreCase(clientIp)) {
            clientIp = request.getHeader("Proxy-Client-IP"); // clientIp 가 이 값으로 retrun 되는 경우가 발생할 수 있는가?
        }
        if (clientIp == null || clientIp.isEmpty() || "unknown".equalsIgnoreCase(clientIp)) {
            clientIp = request.getHeader("WL-Proxy-Client-IP"); // clientIp 가 이 값으로 retrun 되는 경우가 발생할 수 있는가?
        }
        if (clientIp == null || clientIp.isEmpty() || "unknown".equalsIgnoreCase(clientIp)) {
            clientIp = request.getRemoteAddr(); // 앞의 if 문에서 true 가 나오면 여기도 true 가 나오기 때문에 항상 이 값으로 나오는거 아닌가?
        }
        return clientIp;
    }

근데 전 아무리 읽어봐도 해당 로직이 이해가 잘 안되요.
제가 주석 단 것에 답변을 주실 수 있나요?


통상적으로 쓰이는 코드 스니펫이라는 것은 이해하는데, 그것을 가져와서 내 애플리케이션에 붙이면 이제 내 코드가 되는 것 입니다.

  • 향후 이것으로 이슈가 되도 원본 글 작성자를 탓할 수는 없으니까요.
  • 관련되어 자체 테스트라도 진행 해보셨나요?

@Sung-Heon Sung-Heon requested a review from Hyune-c March 12, 2025 11:55
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants