2017-11-24 27 views
0

내가하려는 일은 다음과 같습니다. 로그 라인에서 사용자 ID와 요청 ID를 기록하도록 로그백을 수정하십시오. 예 :요청이 필터의 초기 요청이 아닌지 확인하는 방법은 무엇입니까?

2017-11-24 [userid:abcd123 - requestId:12345679] [ClassA:MethodA1] message... 
2017-11-24 [userid:abcd123 - requestId:12345679] [ClassA:MethodA2] message... 
2017-11-24 [userid:abcd123 - requestId:12345679] [ClassB:MethodB1] message... 

requestId는 최종 사용자가 시스템에 한 요청의 모든 부분과 동일하게 유지됩니다.

필자는 MDC에 값을 설정하는 방법을 보여주는 몇 가지 예제를 기반으로 필터를 만들었습니다. 나는 휴식 서비스에 요청을하면 예를 들어,은 (https://logback.qos.ch/manual/mdc.html1)

... 
@Component 
public class RequestFilter implements Filter { 

    @Override 
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { 
     try { 
      String mdcData = String.format("[userId:%s | requestId:%s] ", user(), requestId()); 
      MDC.put("mdcData", mdcData); //Referenced from logging configuration. 
      chain.doFilter(request, response); 
     } finally { 
      MDC.clear(); 
     } 
    } 

    private String requestId() { 
     return UUID.randomUUID().toString(); 
    } 

    private String user() { 
     return "tux"; 
    } 

    @Override 
    public void init(FilterConfig filterConfig) throws ServletException { 
    } 

    @Override 
    public void destroy() { 
    } 
} 
... 

는이 정보 자체에 추가 요청을 시스템없이 한 번 실행합니다. 이것은 내가 예상했던 것입니다. 그리고 그들 모두가 동일한 requestId를 포함하는 로그 항목을 볼 수 있습니다. Swagger 페이지 중 하나에 브라우저 페이지 요청을하면 웹 페이지는 페이지에 표시 될 추가 정보를 여러 번 요청합니다. 로깅은 페이지가 렌더링해야하는 정보에 대한 모든 추가 요청으로 인해 웹 페이지 요청을로드하여 약 20 건의 요청을 캡처합니다. 이것이 발생하면 내부 요청 각각이 고유 요청을 생성하고 각 요청에 대해 requestId가 기록되는 X 개의 로그 항목으로 끝납니다. 이것은 내 의도가 아니 었습니다.

생성 된 내부 요청 호출을 통해 시작 부분에 대한 시스템 요청을 어떻게 결정합니까?

requestId에 대한 MDC 값을 반복해서 설정하지 않아도됩니다. 외부 사용자가 요청한 첫 번째 요청을 토대로 한 번 호출 할 때마다 한 번만 설정하면됩니다.

요청의 수명주기 이외에 이것을 무엇이라고 부르는지 모르겠지만 답변을 찾을 수 없습니다.

모든 안내를 이해합니다. 감사.

EDIT : original user request을 식별하는 것 외의 다른 질문으로 연결하십시오.

+1

"서브 콜"이란 무엇을 의미합니까? 주어진 요청이 여러 번 전달된다는 것을 의미합니까? 필터가 모든 전달에서 호출됩니다. 그렇다면 요청에 속성을 저장하고 속성이 이미 설정된 경우 필터링하지 않아도됩니다. 필터의 발송자 유형 (https://docs.oracle.com/javaee/7/api/javax/servlet/annotation/WebFilter.html#dispatcherTypes--)을 설정할 수도 있습니다. 그것이 "하위 호출"의 의미가 아니라면 설명하십시오. –

+0

하위 호출을 통해 시스템이 필터를 트리거하는 다른 많은 호출을 자체에서 수행하고 있습니다. 모든 발송자 유형이 요청으로 표시되는지 확인했습니다. 애트리뷰트의 설정을 살펴보고 필요한 간단한 픽스가 될 것 같은데요. – Elijah

+0

"시스템"과 "호출"이 의미하는 바는 여전히 분명하지 않습니다. 프론트 엔드가 서버에 많은 요청을 보내는 경우 "서브 호출"과 같은 것은 없습니다.이들은 단지 요청이며, 서로 독립적입니다. –

답변

1

이 문제를 해결하는 한 가지 방법은 RequestFilter를 "/ *"이 아닌 기록하려는 서비스의 URL 패턴으로 매핑하는 것입니다.

EDIT : 필터를 "/ *"로 매핑하는 것이지만 doFilter 방법에서는 URL에 "swagger"가 포함 된 요청을 MDC하지 마십시오. 실험 중에는 Swagger 페이지에서 생성 된 모든 URL을 포함시켜야 할 수도 있습니다. 일부 URL에는 'Swagger'라는 단어가 포함되어 있지 않을 수 있습니다.

@Override 
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { 

    if (isRequestSwaggerUrl(request)) { 
     chain.doFilter(request, response); 
     return; 
    } 

    try { 
     String mdcData = String.format("[userId:%s | requestId:%s] ", user(), requestId()); 
     MDC.put("mdcData", mdcData); //Referenced from logging configuration. 
     chain.doFilter(request, response); 
    } finally { 
     MDC.clear(); 
    } 
} 
+0

시스템을 모르거나로드 할 수있는 모든 끝점 또는 페이지를 모르는 상태에서이 작업을 수행하지 않으려 고했으나보다 일반적인 작업을 수행 할 수 없다면이 작업을 수행해야하는 것처럼 보입니다. . 의견을 보내 주셔서 감사합니다. – Elijah