Fluentd access log 500 에러만 남기기
728x90

tomcat access log 에서 500에러만 추출해서 azure storage로 남기기로 했다.

시작

flunetd 설치는 이전에 올린 글을 참고해주길 바란다.

 

먼저 /etc/td-agent/td-agent.conf 파일을 연다.

sudo vi /etc/td-agent/td-agent.conf

그 후에 source -> parse -> filter 순서로 작성한다.

<source>
 @type tail
 @log_level warn
 <parse>
  @type regexp
  expression /^(?<client_ip>.*?) (?<identi_user>[^ ]*) (?<user>[^ ]*) \[(?<timestamp>\d{2}\/[a-zA-Z]{3}\/\d{4}\:\d{2}\:\d{2}\:\d{2} \+\d{4})\] \"(?<message>.*?)\" (?<response_code>\d+) (?<bytes_send>[0-9\-]+) (?<request_time>\d+)$/
 </parse>
 path /<access log path>/localhost_access_log.%Y-%m-%d.txt
 pos_file /tmp/td-agent/<path>/access_log/log_file.pos
 tag access
</source>

<filter access>
 @type grep
 <regexp>
  key response_code
  pattern /^500$/
 </regexp>
</filter>

먼저 access log 의 패턴을 파악하는게 중요하다. 패턴에 따라서 작성할 정규식이 달라진다.

 

access log 의 패턴을 알고 싶으면 현재 사용하고 있는 톰캣 폴더의 conf 폴더로 이동해서 server.xml 파일을 열어보면 된다.

cd /<path>/tomcat7/conf

sudo vi server.xml
...
   <!-- Access log processes all example.
             Documentation at: /docs/config/valve.html
             Note: The pattern used is equivalent to using pattern="common" -->
        <Valve className="org.apache.catalina.valves.AccessLogValve" directory="logs"
               prefix="localhost_access_log." suffix=".txt"
               pattern="%h %l %u %t &quot;%r&quot; %s %b %D" />
...

vim 에디터에서 찾기 키는 /이다. access 를 찾고 싶으면 /access 라고 입력하면 된다.

 

현재 위에서 나온 pattern은 "%h %l %u %t "%r" %s %b %D"이다.

패턴 의미
%h 원격 호스트 이름 (client IP)
%l identd의 원격 논리적 사용자 이름(항상 -을 반환한다.)
%u 인증된 원격 사용자, 아니라면 - 을 반환
%t 날짜와 시간
%r 요청의 첫번째 줄 ( 메소드와 요청 URI)
%s HTTP 상태 코드
%b HTTP 헤더를 제외한 전송 크기
%D response time 응답시간 (ms)

참조 : https://tomcat.apache.org/tomcat-9.0-doc/config/valve.html#Access_Logging

 

이제 정규식을 작성하면 된다.

 

현재 나의 access log 패턴은 "%h %l %u %t "%r" %s %b %D" 이므로 실제 나오는 log는

127.0.0.1 - - [23/Jun/2022:09:37:03 +0800] "POST /요청 uri HTTP/1.1" 200 75 18

이렇게 나오고 있다.

 

fluentd에서 apache2의 정규표현식을 확인해 보면

/^(?<host>[^ ]*) [^ ]* (?<user>[^ ]*) \[(?<time>[^\]]*)\] "(?<method>\S+)(?: +(?<path>(?:[^\"]|\\.)*?)(?: +\S*)?)?" (?<code>[^ ]*) (?<size>[^ ]*)(?: "(?<referer>(?:[^\"]|\\.)*)" "(?<agent>(?:[^\"]|\\.)*)")?$/

이런 식으로 나오는 것을 볼 수 있다.

 

<>안에 있는 것은 필드 명이라고 보면 된다.

 

저것을 참고하여 작성하게 되면 parse 태그의 정규식은 이렇게 된다.

expression /^(?<client_ip>.*?) (?<identi_user>[^ ]*) (?<user>[^ ]*) \[(?<timestamp>\d{2}\/[a-zA-Z]{3}\/\d{4}\:\d{2}\:\d{2}\:\d{2} \+\d{4})\] \"(?<message>.*?)\" (?<response_code>\d+) (?<bytes_send>[0-9\-]+) (?<request_time>\d+)$/

그러면 fluentd 에 쌓이는 로그의 형태는

2022-06-23T09:51:20+08:00    access    {"client_ip":"127.0.0.1","identi_user":"-","user":"-","timestamp":"23/Jun/2022:09:51:18 +0800","message":"GET / HTTP/1.1","response_code":"200","bytes_send":"75","request_time":"12"}

로 나온다.

 

이제 filter 에서 response_code가 500인 로그들만 필터링 해주는 것만 하면 된다.

<filter access>
 @type grep
 <regexp>
  key response_code
  pattern /^500$/
 </regexp>
</filter>

filter 태그의 type 은 grep으로 하고 regexp 부분의 파라미터 key 는 parse에서 빼온 필드 pattern은 정규식을 입력하면 된다.

 

pattern 은 시작과 끝을 / / 로 감싸줘야한다. ^은 문장의 시작 $은 문장의 끝이다.

 

500번대의 에러를 수집하고 싶으면 /^5\d\d$/ 를 입력해주면 된다.

 

참조 : https://docs.fluentd.org/parser/apache2

728x90

'Fluentd > 적용' 카테고리의 다른 글

Fluentd + Azure Loganalytics  (0) 2022.07.25
Fluentd Installation ( ruby gem )  (0) 2022.07.25
Fluentd + MongoDB  (0) 2022.05.10
Fluentd Test  (0) 2022.05.06
Fluentd + Newrelic  (0) 2022.04.29