string 필드에서 원하는 값만 가져와서 다른 필드로 매핑하고 싶은 일이 생겼다. 그래서 elasticsearch의 runtime과 painless 스크립트를 이용해 string에서 원하는 값만 추출해서 다른 필드로 뺴는 방법을 이용했다.
로그스태시에서는 grok이라는 필터 플러그인을 지원하는데 painless 스크립트에서 또한 grok을 사용할 수 있다.
kibana의 검색창에 dev라 검색하면 아래와 같이 dev tools가 뜨니 클릭해서 dev tools를 이용해 진행하자.
dev tools에서 ip, uri, username을 아래와 같이 추출하였다.
PUT log/_mapping
{
"runtime": {
"ip": {
"type": "keyword",
"script": {
"source": """
String field = grok('%{GREEDYDATA:start}ip":"%{GREEDYDATA:field}","uri%{GREEDYDATA:end}').extract(params._source['message'])?.field;
if (field != null) {
emit(field);
} else {
emit('none');
}
"""
}
},
"uri": {
"type": "keyword",
"script": {
"source": """
String field = grok('%{GREEDYDATA:start}uri":"%{GREEDYDATA:field}","username').extract(params._source['message'])?.field;
if (field != null) {
emit(field);
} else {
emit('none');
}
"""
}
},
"username": {
"type": "keyword",
"script": {
"source": """
String field = grok('%{GREEDYDATA:start}username":"%{GREEDYDATA:field}"}","thread').extract(params._source['message'])?.field;
if (field != null) {
emit(field);
} else {
emit('none');
}
"""
}
}
}
}
grok에선 다양한 패턴을 지원하는데 %{DATATYPE:field} 과 같은 문법으로 사용할 수 있다. grok 패턴에 대해서 더 궁금하다면 아래 링크를 확인해보자. 각 grok 패턴이 어떤 정규식으로 구현 되었는지 알 수 있다.
https://github.com/elastic/logstash/blob/v1.4.0/patterns/grok-patterns
아래는 ip를 추출하는 grok 코드이다.
String field = grok('%{GREEDYDATA:start}ip":"%{GREEDYDATA:field}","uri%{GREEDYDATA:end}')
.extract(params._source['message'])?.field;
json string의 데이터 형태는 아래와 같다.
{"message": "{"ip":"111.111.111.111, 10.1.1.11","uri":"/api/v1/category/detail","username":"choonsik"}","thread": "http-nio-8080-exec-3"}
GREEDYDATA는 모든 형태의 데이터를 뜻한다. 그러므로 위 스트링을 위 코드로 해석하면 아래와 같다.
- start: {"message": "{"ip":"
- field: 111.111.111.111, 10.1.1.11
- end: ","uri":"/api/v1/category/detail","username":"choonsik"}","thread": "http-nio-8080-exec-3"}
grok 패턴에서 start의 끝 부분이 [ip":"] end의 시작 부분이 [","uri] 부분과 매칭된다. 각 부분을 통해서 필요한 값을 분리, 추출해서 painless에서 emit() 하면 원하는 값을 추출해 매핑할 수 있다. 우리는 항상 json 형태가 아닌 단순 에러 스트링도 message에 담겨 오는 형태이므로 전처리에 용이하게 null 값일 때 none이란 스트링을 넣어주었다. none이 아니라 어떠한 스트링이 와도 상관 없지만 유니크하고 의미있는 스트링을 선택하는게 전처리에 유리하다.
'SRE > ELK' 카테고리의 다른 글
Kafka + Elasticsearch + Kibana + Docker-compose로 Xpack 보안 인증 구축 (0) | 2023.06.21 |
---|---|
[Elasticsearch] 인덱스 필드 정리 및 리인덱싱 (0) | 2023.06.20 |