읽기 스키마 맛을 본 뒤론 가급적 런타임 필드를 사용하려고 한다. 다음은 URI 필드에서 url과 변수 정보를 런타임 필드로 추출하는 구문.
PUT test/_mapping{ "runtime": { "url": { "type": "keyword", "script": "emit(grok('(?<url>[^?]+)').extract(doc['uri.keyword'].value).url)" }, "param": { "type": "keyword", "script": "emit(grok('[^?]+\\\\??(?<param>.*)').extract(doc['uri.keyword'].value).param)" } }}
유효한 값이 아닌, empty 값을 갖는 필드가 존재하면 나중에 골치 아파질 수 있다. 값이 없는 필드를 만들고 싶지 않다면 조건을 줘야 함.
PUT test/_mapping{ "runtime": { "url": { "type": "keyword", "script": "emit(grok('(?<url>[^?]+)').extract(doc['uri.keyword'].value).url)" }, "param": { "type": "keyword", "script": """ if (doc['uri.keyword'].value.contains('?')) { emit(grok('.*\\?(?<param>.*)').extract(doc['uri.keyword'].value).param) } """ } }}
여러 개의 필드를 한 방(?)에 만들고 싶다면
원하는 만큼 캡쳐그룹을 지정해도 grok().extract().capture_group_name 구문은 한 번에 하나의 캡쳐그룹만을 필드로 추출할 수 있다. 이때 엘라스틱은 composite 타입을 이용해서 멀티 생성을 지원함.
PUT test/_mapping{ "runtime": { "url": { "type": "composite", "script": """ if (doc['uri.keyword'].value.contains('?')) { emit(grok('(?<url>[^?]+)\\??(?<param>.*)').extract(doc['uri.keyword'].value)) } else { emit(grok('(?<url>.*)').extract(doc['uri.keyword'].value)) } """, "fields": { "url": { "type": "keyword" }, "param": { "type": "keyword" } } } }}
장점인지 단점인지는 모르겠지만 '부모-자식' 구조의 필드만 만들 수 있다. 더 편한지도 잘 모르겠음 dissect 필터도 사용 가능.
PUT test/_mapping{ "runtime": { "url": { "type": "composite", "script": """ if (doc['uri.keyword'].value.contains('?')) { emit(dissect('%{url}?%{param}').extract(doc['uri.keyword'].value)) } else { emit(dissect('%{url}').extract(doc['uri.keyword'].value)) } """, "fields": { "url": { "type": "keyword" }, "param": { "type": "keyword" } } } }}
당연히 스플렁크도 멀티 생성을 지원한다. 예외처리도 필요 없고 간단.
| makeresults| eval uri="/path/a.php?a=1 /phth/b.php?b=2&c=3 /path/c.php"| makemv delim=" " uri| mvexpand uri| rex field=uri "(?<url>[^?]*)(\?(?<param>[^|]*))?"| table uri, url, param
관련 글
댓글 없음:
댓글 쓰기