LoggingFilter로 로그 남기기
Elasticsearch에 대해 알아보면서 ELK 스택도 함께 알게 되었고
ELK(ElasticSearch Logstash Kibana) 스택으로 로깅을 구현해보기로 했다.
구현 방법과 함께 어떤 모습으로 로그가 쌓이는지 확인해보고
Slack에 ERROR 로그 알람을 보내는 것까지 구현해보자.
1. Logback.xml
Spring에서 기본적으로 제공하는 로그가 있지만 Logstash에 로그를 쌓아
엘라스틱서치로 보내고 싶기 때문에 resource 에 다음 파일을 추가했다.
logback.xml
파일을 따로 생성해 설정해주지 않으면
스프링이 설정해둔 로그가 찍힌다.
2. Gradle
implementation 'net.logstash.logback:logstash-logback-encoder:6.6'
logstash 사용을 위해 위 의존성을 추가한다.
3. LoggingFilter.java
@Component
public class LoggingFilter extends OncePerRequestFilter {
@Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response,
FilterChain filterChain) throws IOException {
ContentCachingRequestWrapper requestWrapper = new ContentCachingRequestWrapper(request);
ContentCachingResponseWrapper responseWrapper = new ContentCachingResponseWrapper(response);
try {
filterChain.doFilter(requestWrapper, responseWrapper);
} catch (Exception e) {
logger.error(e);
} finally {
LoggingRequest loggingRequest = getLoggingRequest(requestWrapper);
String log = JsonUtils.toJson(loggingRequest);
logger.info(log);
}
responseWrapper.copyBodyToResponse();
}
private LoggingRequest getLoggingRequest(ContentCachingRequestWrapper request) {
String requestURI = request.getRequestURI();
String method = request.getMethod();
return new LoggingRequest(requestURI, method);
}
}
OncePerRequestFilter
는 모든 서블릿에 일관된 요청을 처리하기 위해 만들어진 필터이다.
이 추상 클래스를 구현한 필터는 사용자의 한번에 요청 당 딱 한번만 실행되는 필터를 만들 수 있다.
필터에 대한 자세한 이야기는 다른 포스팅에서 해보자.
필터에서 logger
로그를 남기면 kibana에서 로그를 확인할 수 있다.
4. docker-compose
https://github.com/deviantony/docker-elk
위 repository를 clone 받아서 설정을 마치고
docker-compose up
명령으로 elk를 띄운다.
설정해야 하는 부분
- 유료 기능인 X-Pack이 포함되어 있기 때문에 주석처리하거나 없애야 한다.
- logstash > pipeline > logstash.conf
input {
tcp {
port => 5000
codec => json_lines
}
}
filter {
json {
source => "message"
remove_field => ["message"]
}
}
output {
elasticsearch {
hosts => "elasticsearch:9200"
}
}
기본 포트
- 5044: Logstash 비트 입력
- 5000: Logstash TCP 입력
- 9600: Logstash 모니터링 API
- 9200: 엘라스틱서치 HTTP
- 9300: Elasticsearch TCP 전송
- 5601: 키바나
Error 로그 Slack으로 알림 받기
ELK 스택으로 로깅을 구현했다.
슬랙으로 알림을 받는건 더 쉽게 구현할 수 있다.
1. Logback.xml
<appender name="SLACK" class="com.github.maricn.logback.SlackAppender">
<webhookUri>${webhook-uri}</webhookUri>
<layout class="ch.qos.logback.classic.PatternLayout">
<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} %msg %n</pattern>
</layout>
<colorCoding>true</colorCoding>
</appender>
<appender name="ASYNC_SLACK" class="ch.qos.logback.classic.AsyncAppender">
<appender-ref ref="SLACK"/>
<filter class="ch.qos.logback.classic.filter.ThresholdFilter">
<level>WARN</level>
</filter>
</appender>
<logger name="com.example.loggingslack" level="ALL">
<appender-ref ref="ASYNC_SLACK"/>
</logger>
위에서 먼저 설정한 logstash 설정과 함께 Logback.xml
에 작성해주면 된다.
- ASYNC_SLACK 현재 추천하는 방식으로 appender를 비동기 방식으로 사용하는걸 권장하고 있다.
<filter>
레벨을 설정하는 부분이다.
<webhookUri>
SLACK webhookUri를 넣는 부분이다.application.yml
에서 값을 가져오고 있다.
2. Incoming Webhooks
슬랙 채널에서 Incoming Webhooks을 추가하여 원하는 형태로 설정하고
webhookUri를 복사해서 Logback.xml
에 넣어준다.
3. Gradle
salck 알람을 위해 다음 의존성을 추가해준다.
implementation "com.github.maricn:logback-slack-appender:1.4.0"
위 모든 설정이 끝나면 ERROR 로그가 찍힐 때마다
다음과 같이 내가 설정한 슬랙 채널에 알람이 온다.
지금 전송된 알람은 테스트한 것이기 때문에 “ERROR” 라는 메시지만 전송되었지만
에러가 발생한 원인과 원하는 메시지가 전송되도록 설정해놓으면 된다.