지난번에 6주간 했던 푸드트럭 프로젝트는 Nginx를 이용하면서 액세스 로그를 쌓아왔기에, 이를 Kibana로 시각화하고 싶었다.
목표는 이용자들의 인기검색어를 Kibana로 모니터링 해보는 것.
이전글 (엘라스틱서치로 인기검색어 모니터링 해보자 (1) - 엘라스틱서치에 액세스로그 쌓기) 에서 액세스로그를 Elasticsearch로 저장하였고, Kibana로 저장된 데이터를 확인하였다.
이번 포스팅에서 해결할 것은 2가지다.
- 수많은 Document 중에서 검색을 수행한 Document만 가져와야 한다.
- 검색어가 무엇인지를 알아야 한다.
우리는 message 필드로 아래와 같은 정보를 알 수 있다.
/api/trucks/search로 시작하는 것은 검색을 수행한 Document 이다. (초록)
/api/trucks/search?q= 이후에 오는 것은 검색어 이다. (보라)
검색어를 보기 위해 필요한 정보들이 message 필드에 있다.
하지만 message 필드에는 너무나도 많은 정보들이 들어있다.
message 안에 짱박혀있는 유의미한 정보들을 각각 의미에 맞게 필드들로 추출하자!!
어떻게? => Logstash
Logstash 설정 파일 구성은 아래로 구성된다.
1
2
3
input {...} # 데이터를 가져온다.
filter {} # 데이터를 가공한다.
output {...} # 데이터를 내보낸다.
filter 에서 필드를 가공할 수 있다.
Version 1. message 필드 쪼개기
패턴 만들기
message에 들어간 양식에 맞게 패턴을 정의할 수 있다.
아래는 Nginx의 Access.log 의 패턴을 지정한다.
/usr/share/logstash/patterns/nginx.pattern
1
NGINX_ACCESS %{IPORHOST:remote_addr} - %{USERNAME:remote_user} \[%{HTTPDATE:time_local}\] \"%{DATA:verb} %{DATA:request} HTTP/%{NUMBER:httpversion}\" %{INT:status} %{NUMBER:bytes_sent} \"%{DATA:http_referer}\" \"%{DATA:http_user_agent}\"
- ${IPORHOST:remote_addr} : 타입: IP/Host, 이름: remote_addr
/etc/logstash/conf.d/logstash-test.conf
1
2
3
4
5
6
7
8
9
10
11
input {...}
filter {
grok {
patterns_dir => "/usr/share/logstash/patterns" # 1)
match => { "message" => "%{NGINX_ACCESS}" } # 2)
add_field => [ "received_at", "%{@timestamp}" ] # 3)
}
}
output {...}
- 1) 패턴을 가져올 디렉토리
- 2) message 필드를 NGINX_ACCESS 패턴을 사용하여 쪼개겠다.
- 3) ‘received_at’ 필드 추가 (value: @timestamp)
( Logstash 재실행 )
1
2
> sudo service logstash restart
> curl -XGET 'https://<<도메인>>/api/trucks/search?q=%EA%BC%AC%EC%A7%80' # 트래픽 1 발생
Logstash를 재실행 한 이후의 로그들은 위와 같이 나온다.
(DB가 죽어있어서 status가 499로 뜨는건 비밀)
Version 2. request 필드 쪼개기
message에서 필드들을 잘 쪼갠 것 같다.
아직 쪼개야 하는 필드가 보인다.
request 필드에는 URIPATH와 URIPARAM이 함께 들어가 있다.
/etc/logstash/conf.d/logstash-test.conf
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
input {...}
filter {
grok {
patterns_dir => "/usr/share/logstash/patterns"
match => { "message" => "%{NGINX_ACCESS}" }
add_field => [ "received_at", "%{@timestamp}" ]
}
# 새로 추가된 내용 1
grok {
match => { "request" => ["%{URIPATH:uri_path}"] }
}
# 새로 추가된 내용 2
grok {
match => { "request" => ["%{URIPARAM:uri_param}"] }
}
}
output {...}
기본적으로 사용 가능한 패턴에 대해서는 여기에서 볼 수 있는데, URIPATH 와 URIPARAM 으로 쪼갤 수 있는 것 같아 보인다.
( Logstash 재실행 )
1
2
> sudo service logstash restart
> curl -XGET 'https://<<도메인>>/api/trucks/search?q=%EA%BC%AC%EC%A7%80' # 트래픽 1 발생
uri_path와 uri_param으로 쪼개졌다.
Version 3. uri_param 필드 쪼개기
원하는 대로 잘 나눠졌지만.. url_param에 아쉬움이 남는다.
- ?, =는 불필요하며,
- key와 value를 나눌 수 있을 것 같고,
- 복수개의 params가 들어올 경우 이것도 나눠줘야 할 것 같다.
- 파라미터가 URL Encoding 되어있어서 읽기 불편하다. 읽기 편하게 UTF8로 바꾸고 싶다.
/etc/logstash/conf.d/logstash-test.conf
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
input {...}
filter {
grok {
patterns_dir => "/usr/share/logstash/patterns"
match => { "message" => "%{NGINX_ACCESS}" }
add_field => [ "received_at", "%{@timestamp}" ]
}
grok {
match => { "request" => ["%{URIPATH:uri_path}"] }
}
grok {
match => { "request" => ["%{URIPARAM:uri_param}"] }
}
# 새로 추가된 내용
kv {
source => "request"
field_split => "&?"
value_split => "="
target => "params"
}
# 새로 추가된 내용
urldecode {
charset => "UTF-8"
field => "params"
}
}
output {...}
- request 필드에서
- ?q=%EA%BC%AC%EC%A7%80&limit=10
- &과 ? 로 쪼개고
- [ q=%EA%BC%AC%EC%A7%80 , limit=10 ]
- 각각을 = 기준으로 쪼개서 왼쪽은 key, 오른쪽은 value
- {q: %EA%BC%AC%EC%A7%80}, {limit: 10}
- params 라는 필드에 저장해달라
- params = {q: %EA%BC%AC%EC%A7%80, limit: 10}
- params 필드 인코딩을 UTF-8로 바꿔달라
- params = {q: 꼬지, limit: 10}
( Logstash 재실행 )
1
2
> sudo service logstash restart
> curl -XGET 'https://<<도메인>>/api/trucks/search?q=%EA%BC%AC%EC%A7%80&limit=10' # 트래픽 1 발생
검색어 가져오기 끗
( 타입 설정 )
위 그림에서 필드의 타입이 ? 인 것들이 많다.
Elasticsearch로 부터 필드 타입 정보들을 받아올 수 있다.
Management - Index Patterns - nginx* - Refresh field list 클릭
검색한 Document만 가져오기
현재는 access.log의 모든 데이터를 보고 있다. 나는 검색한 데이터만 필요로 하다.
검색한 로그는 uri_path가 동일하다.
=> uri_path 가 /api/trucks/search 인 것만 가져오면 된다.
검색한 Document 가져오기 끗
TODO :: 필드 타입 설정 키바나에 반영, 인기검색어 Visualize, 형태소 분석상
Comments powered by Disqus.