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 "%r" %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$/ 를 입력해주면 된다.
'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 |
Comment