6.데이터 가공

Edit

6.1search

문법

search [limit=숫자] [표현식]

조건 표현식에 따라 로그를 필터링합니다. 표현식이 참인 경우에만 로그가 다음 쿼리 명령어로 전달됩니다. limit 옵션이 주어지는 경우, 주어진 갯수만큼 표현식이 참이 되면 쿼리 전체가 완료됩니다.

사용 예

1) line 필드에 game 문자열을 포함하는 로그 (와일드카드 지원)

search line == "*game*"

2) 상태 코드가 200이 아닌 로그

search status != 200

3) src_ip가 1.2.3.4 이고 dst_port가 22인 경우

search src_ip == "1.2.3.4" and dst_port == 22

6.2mpsearch

문법

mpsearch 스캔대상필드 [ 패턴조회 서브쿼리 ]

수천 개 이상의 키워드 패턴을 고속으로 한 번에 검색합니다. 서브쿼리에서 지정된 패턴이 스캔대상필드에서 검출되면, _mp_result 필드에 검출된 모든 패턴 목록을 포함하여 출력합니다.

스캔대상필드

멀티 패턴을 검색할 대상 필드의 이름을 지정합니다.

패턴조회 서브쿼리

검색할 키워드 패턴의 목록을 조회하는 쿼리를 입력합니다. 이 쿼리의 출력은 expr, expr2, rule 문자열 필드를 포함해야 합니다. expr 필드는 문자열을 불린식으로 조합하여 작성하는데, 스캔대상 필드의 문자열 값에서 해당되는 문자열을 고속으로 검출한 후, 불린식과 일치하는지 확인합니다. expr2 필드는 expr 필드의 문자열 불린식이 참인 경우, 추가적으로 다른 필드의 값을 이용하여 필터링할 수 있는 기회를 선택적으로 제공합니다. rule 필드에는 패턴 식별자 혹은 이름을 기입합니다.

패턴의 예시는 아래와 같습니다:

표 6-1패턴 예시

expr (필수)

expr2 (선택)

rule (필수)

키워드 패턴: 1차 고속 탐지

불린 표현식: 2차 필터링

패턴 이름

"addextendedproc" and "xp_cmdshell"


xp_cmdshell

"REMOTE_ADDR" and ("fputs" or "fwrite")

path == "lib.php"

zb now_connect

만약 xp_cmdshell 패턴만 탐지되었다면, _mp_result 필드의 값은 아래와 같습니다:

[ { "expr": "\"addextendedproc\" and \"xp_cmdshell\"", "rule": "xp_cmdshell" } ]

사용 예

1) 외부 DB에서 패턴 목록을 로딩하여 signature 필드를 대상으로 멀티 패턴매칭

mpsearch signature [ 
    dbquery RULE_DB select rule, expr, expr2 from web_rules ]

6.3flowsearch

문법

flowsearch [ 플로우 규칙 조회 서브쿼리 ]

이 커맨드는 IP 네트워크 대역, 포트, 프로토콜 조건으로 구성된 규칙을 서브쿼리로 읽어들여서 입력 레코드와 대조하고, 검색된 모든 플로우 식별자를 _flow 필드에 배열로 출력합니다. 플로우 규칙은 파일, 테이블, 원격 RDBMS 등 임의의 위치에서 읽어올 수 있으며, 필드 구성과 타입이 일치해야 유효한 규칙으로 인식됩니다.

플로우 규칙은 최대 10000개까지 허용됩니다. 서브쿼리 결과가 1만개를 넘는 경우 최초 1만개 이후의 레코드는 무시됩니다. 서브쿼리가 실패하는 경우, _flowsearch_error 필드에 에러 원인 문자열이 포함되어 출력됩니다. 따라서 스트림 쿼리에서 flowsearch 커맨드를 사용하는 경우, flowsearch 커맨드 뒤에 _flowsearch_error 필드 값이 존재하는지 검사하는 예외처리를 수행해야 의도하지 않은 동작을 차단할 수 있습니다.

표 6-2입력 레코드 필드 정의

필드 이름

타입

필수 여부

설명

src_ip

IP

필수

출발지 IP

src_port

정수

선택 (null 허용)

출발지 포트

dst_ip

IP

필수

목적지 IP

dst_port

정수

선택 (null 허용)

목적지 포트

protocol

문자열

선택 (null 허용)

프로토콜 문자열

입력 레코드의 필드가 타입이 일치하지 않거나 필수 필드가 누락된 경우에는, 플로우 규칙을 검사하지 않고 레코드를 원본 그대로 출력합니다.

표 6-3플로우 규칙 필드 정의

필드 이름

타입

필수 여부

설명

src_ip

IP

필수

출발지 IP 주소

src_cidr

정수

필수

출발지 넷마스크

(0-32 범위의 정수)

src_port

정수

선택 (null 허용)

출발지 포트 번호

(0-65535 범위의 정수)

dst_ip

IP

필수

목적지 IP 주소

dst_cidr

정수

필수

목적지 넷마스크

(0-32 범위의 정수)

dst_port

정수

선택 (null 허용)

목적지 포트 번호

(0-65535 범위의 정수)

protocol

문자열

선택 (null 허용)

프로토콜 문자열

(TCP, UDP, ICMP 등)

flow

임의 타입

필수

플로우 식별자

즉, flowsearch 커맨드에 레코드가 1개 입력될 때마다 입력된 5-튜플 값을 플로우 규칙과 대조하여, 일치하는 플로우 식별자를 _flow 필드에 목록으로 출력합니다. 플로우 규칙의 ip와 cidr 필드는 모두 필수 입력이지만, 규칙의 src_ip가 0.0.0.0 이고 src_cidr이 0인 경우 모든 출발지 IP에 대해 참이 되므로, 출발지 혹은 목적지에 대해 모든 값을 허용하려면 규칙에 0.0.0.0/0을 설정하면 됩니다.

예를 들어 아래의 플로우 규칙에 대해, 입력 레코드가 src_ip=106.75.11.63, src_port=57776, dst_ip=106.246.20.67, dst_port=80, protocol=TCP 인 경우, flow2가 일치하므로 출력 레코드에는 _flow=["flow2"] 필드가 추가됩니다.

표 6-4플로우 규칙 예시

src_ip

src_cidr

src_port

dst_ip

dst_cidr

dst_port

protocol

flow

211.36.133.0

24

null

106.246.20.67

32

80

TCP

flow1

106.75.11.0

24

null

106.246.20.67

32

null

TCP

flow2

사용 예

json "{}" 
| eval src_ip=ip("106.75.11.63"),  src_port=57776
| eval dst_ip=ip("106.246.20.67"), dst_port=80, protocol="TCP" 
| flowsearch [
    union [ json "{}" | eval src_ip=ip("211.36.133.0"), dst_ip=ip("106.246.20.67"), flow="flow1" ] 
  | union [ json "{}" | eval src_ip=ip("106.75.11.0"),  dst_ip=ip("106.246.20.67"), flow="flow2" ] 
  | eval src_cidr=24, dst_cidr=32
] 
| fields src_ip, src_port, dst_ip, dst_port, protocol, _flow

6.4eval

문법

eval 필드이름 = 표현식

우변의 표현식을 평가하여 새로운 필드를 할당하거나 기존의 필드 값을 대체합니다. 우변에는 값으로 평가될 수 있는 모든 조합의 표현식을 입력할 수 있습니다.

사용 예

1) 문자열의 정수 변환

eval num = int("100")

2) 특정 필드의 타입 출력

eval type = typeof("string")
eval type = typeof(100)

3) 필드 값 합산

eval total = sent + rcvd

4) 문자열 조립

eval msg = concat("hello", ", world")

6.5evalc

문법

evalc 변수이름 = 표현식

우변의 표현식을 평가하여 새로운 쿼리 매개변수를 할당하거나 기존의 쿼리 매개변수 값을 대체합니다. set 쿼리 명령어와 다르게 입력되는 쿼리 실행 시점에 모든 데이터에 대해 평가됩니다. 우변에는 값으로 평가될 수 있는 모든 조합의 표현식을 입력할 수 있습니다.

사용 예

1) count가 임계치가 넘는 경우 alert 값을 true로 설정

evalc alert = if(count > 100000, true, $("alert"))

모든 입력 데이터에 대해 우변 표현식 평가 후 대입되므로, 임계치를 넘지 않는 경우 $ 함수를 이용하여 기존 변수 값을 그대로 다시 대입하도록 해야합니다.

6.6fields

문법

fields [-] 필드1 [, 필드2, ...]

특정한 필드만 출력하거나, 특정한 필드만 선택적으로 제외합니다. - 부호를 사용한 경우에는 뒤에 나열되는 필드만 제거하고, - 부호가 생략된 경우에는 뒤에 나열되는 필드만 출력합니다.

사용 예

1) src_ip와 action 필드만 출력

fields src_ip, action

2) line 필드만 제거

fields – line

6.7sort

문법

sort [limit=숫자] [-]필드1, [-]필드2, … [by 파티션필드1, 파티션필드2, …]

주어진 필드를 기준으로 정렬합니다. 필드 이름 앞에 – 부호가 붙은 경우 내림차순, 그렇지 않으면 오름차순으로 정렬합니다. limit 옵션이 지정된 경우 정렬된 결과에서 순서대로 N개를 추출합니다. by 문을 사용할 경우, 파티션 필드 값을 기준으로 파티셔닝 후 파티션별 정렬을 수행합니다. limit 옵션과 by 문을 같이 사용할 경우, 각 파티션마다 N개를 추출합니다.

사용 예

1) count 기준으로 상위 10개 내림차순 추출

sort limit=10 -count

2) bytes와 pkts 기준으로 상위 10개 내림차순 추출

sort limt=10 -bytes, -pkts

3) 각 src와 dst에 대해 bytes와 pkts 기준으로 상위 10개 내림차순 추출

sort limt=10 -bytes, -pkts by src, dst

6.8stats

문법

stats [parallel=t] 그룹함수1 [as 출력이름1] [, 그룹함수2 [as 출력이름2], ...] [by 필드1, 필드2, ...]
parallel

t로 설정 시, 쿼리를 병렬 처리합니다. 이 옵션을 사용하면 처리 속도가 증가하지만, 데이터의 순서를 보장하지 않습니다.

그룹을 대상으로 동작하는 집계 함수의 평가 결과를 출력합니다. by 절이 지정되지 않은 경우 이전 쿼리 명령어에서 넘어오는 전체 로그를 하나의 그룹으로 계산합니다. 그룹 필드를 기준으로 정렬되는 부수적인 효과가 있습니다.

사용 예

1) 계수

stats count

2) src_ip 단위 계수

stats count by src_ip

3) src_ip와 dst_ip 쌍에 대한 계수

stats count by src_ip, dst_ip

4) src_ip와 dst_ip 쌍에 대한 bytes 총합과 계수

stats sum(bytes) as bytes, count by src_ip, dst_ip

6.9timechart

문법

timechart span=시간단위 그룹함수1 [as 출력이름1] [, 그룹함수2 [as 출력이름2], ...] [by 필드]

시간단위는 s(초), m(분), h(시), d(일), w(주), mon(월), y(년)으로 지정할 수 있습니다. 가령, 10m은 10분 단위입니다. 월 단위를 사용하는 경우에는 12의 소인수만 지정할 수 있습니다. 즉, 3mon은 허용되지만 5mon은 허용되지 않습니다.

by 절이 생략되는 경우에는 시간단위만 적용하여 집계됩니다. by 절이 지정되면 필드 값 별로 그룹이 만들어집니다. 가령, by dst_port가 지정되면 80, 443 등 dst_port 필드의 값이 필드의 이름이 되고 시간 단위로 통계가 산출됩니다.

사용 예

1) 10분 단위 로그 발생량

timechart span=10m count

2) 1분 단위 bytes 변화 추이

timechart span=1m sum(bytes)

3) 각 목적지 포트의 1시간 단위 로그 발생 갯수

timechart span=1h count by dst_port

6.10rex

문법

rex field=필드 "정규표현식"

지정된 필드에서 정규표현식을 이용하여 필드를 추출합니다. 이 때 사용되는 정규표현식은 필드 이름을 부여할 수 있도록 확장된 정규표현식입니다. 정규표현식 그룹을 만들 때 (?<field>.*) 형식으로 지정하면 그룹에 매칭된 문자열이 field 이름으로 추출됩니다.

사용 예

1) line 필드에서 GET이나 POST, 그리고 /game/flash/로 시작되는 경로의 파일 이름을 filename으로 추출

rex field=line "(GET|POST) /game/flash/(?<filename>([^ ]*))"

2) line 필드에서 타임스탬프 패턴의 문자열 추출

rex field=line "(?<timestamp>\d+-\d+-\d+ \d+:\d+:\d+)"

3) line 필드에서 url과 querystring 동시 추출

rex field=line "(GET|POST) (?<url>[^ ]*) (?<querystring>[^ ]*) "

6.11parse

문법

parse [overlay=t] 파서이름
parse [overlay=t] [field=line] "시작텍스트*끝텍스트" as 필드이름, ...

overlay 옵션을 t로 주면, 원본 필드에 파싱된 필드를 덧씌운 결과를 출력으로 내보냅니다. 별도로 overlay 옵션을 지정하지 않으면, 파서가 원본 필드를 파싱하여 반환하는 필드들만 출력으로 내보냅니다.

사용 예

1) openssh 파서를 이용하여 파싱

parse openssh

2) 시작과 끝 텍스트를 지정하여 필드 추출

Nov 11 00:00:00 session: Proto:17, Policy:pass, Rule:9000, Type:open, Start_Time:Nov 11 00:00:00, End_Time:-

아래 명령으로 위와 같은 원본에서 session, proto, policy, rule, end_time 필드를 추출할 수 있습니다.

parse "session:* " as session, "Proto:*," as proto, "Policy:* as policy, "Rule:*," as rule, "End_Time:*" as end_time

6.12parsecsv

문법

parsecsv [overlay=t] [tab=t] [strict=t] [field=대상필드] [필드이름1, 필드이름2, ...]

쉼표나 탭으로 구분된 CSV 문자열을 파싱합니다. 필드 이름 목록을 지정하지 않으면 column0부터 순서대로 번호를 부여한 필드 이름을 사용합니다.

overlay

t로 설정 시 원본 데이터를 보존합니다.

tab

t로 설정 시 구분자를 탭 문자로 인식합니다.

strict

t로 설정 시, RFC4180 표준안을 엄격히 따르는 CSV 파싱 규칙을 수행합니다. 엑셀로 CSV파일을 열었을 때의 파싱 동작과 같습니다. f로 설정 시에는 CSV파일을 유연한 규칙으로 파싱합니다. 미지정 시 기본 값은 f입니다.

field

지정된 필드의 값을 파싱합니다. 미설정 시 line 필드를 대상으로 파싱합니다.

사용 예

1) 쉼표로 구분된 텍스트 파싱

json "{'line': '\"foo\",\"bar\"'}" | parsecsv

2) 쉼표로 구분된 텍스트를 파싱하여 앞에서부터 순서대로 name1, name2 필드 이름을 부여

json "{'line': '\"foo\",\"bar\"'}" | parsecsv name1,name2

strict 옵션 예

1) 구분자와 컬럼 사이에 공백이 있는 데이터

strict가 t일 때, 구분자와 컬럼 사이에 공백이 있으면 "는 문자로 인식되어 의도한대로 파싱되지 않습니다. strict가 f일 때는 "의 짝이 맞으면 "사이의 문자열만 컬럼으로 인식하기 때문에 의도한대로 파싱됩니다.

원본 데이터

"Chevy", "Venture ""Extended Edition, Very Large""", "MUST SELL! air, moon roof, loaded", "5000.00"

strict=t

[Chevy],[ "Venture ""Extended Edition],[ Very Large"""],[ "MUST SELL! air],[ moon roof],[ loaded"],[ "5000.00"]

strict=f

[Chevy],[Venture "Extended Edition, Very Large"],[MUST SELL! air, moon roof, loaded],[5000.00]

2) 구분자와 컬럼 사이에 공백이 없는 데이터

strict 값에 관계없이 구분자와 컬럼 사이에 공백이 없으므로 의도한대로 파싱됩니다.

원본 데이터

"Chevy","Venture ""Extended Edition, Very Large""","MUST SELL! air, moon roof, loaded","5000.00"

strict=t

[Chevy],[Venture "Extended Edition, Very Large"],[MUST SELL! air, moon roof, loaded],[5000.00]

strict=f

[Chevy],[Venture "Extended Edition, Very Large"],[MUST SELL! air, moon roof, loaded],[5000.00]

3) "의 표기로 \"를 사용한 데이터

strict가 t일 때, \는 문자로 인식하기 때문에 "로 감싸인 컬럼에서 \"를 사용하여 "을 표기한 데이터는 의도한대로 파싱되지 않습니다. strict가 f일 때는 ""뿐만 아니라 \"로도 표기하기 때문에 의도한대로 파싱됩니다.

원본 데이터

"Chevy","Venture \"Extended Edition, Very Large\"","MUST SELL! air, moon roof, loaded","5000.00"

strict=t

[Chevy],[Venture \Extended Edition],[Very Large\""],[MUST SELL! air, moon roof, loaded],[5000.00]

strict=f

[Chevy],[Venture "Extended Edition, Very Large"],[MUST SELL! air, moon roof, loaded],[5000.00]

4) "의 표기로 ""를 사용한 데이터

strict 값에 관계없이 "로 감싸인 컬럼에서 """를 사용하여 표기하기 때문에 의도한대로 파싱됩니다.

원본 데이터

"Chevy","Venture ""Extended Edition, Very Large""","MUST SELL! air, moon roof, loaded","5000.00"

strict=t

[Chevy],[Venture "Extended Edition, Very Large"],[MUST SELL! air, moon roof, loaded],[5000.00]

strict=f

[Chevy],[Venture "Extended Edition, Very Large"],[MUST SELL! air, moon roof, loaded],[5000.00]

6.13parsejson

문법

parsejson [overlay=t] [field=대상필드]
overlay

t로 주면, 원본 필드에 JSON에서 추출된 필드를 덧씌운 결과를 출력으로 내보냅니다. 별도로 overlay 옵션을 지정하지 않으면, JSON 문자열을 파싱한 결과만 출력으로 내보냅니다.

field

대상 필드를 별도로 지정하지 않는 경우 기본값은 line입니다.

사용 예

1) line 필드의 JSON 텍스트를 파싱

json "{'line': ' {\"foo\": \"bar\"}'}" | parsejson

6.14parsexml

문법

parsexml [overlay=t] [field=대상필드]

XML 문서를 복합 객체의 집합으로 파싱합니다. 루트 XML 엘리먼트에 속한 자식 XML 엘리먼트는 필드로 추출됩니다. 파싱 시 XML 엘리먼트가 문자열만 포함한다면 필드 값으로 문자열을 할당하지만, XML 어트리뷰트가 존재한다면 맵을 할당하고 XML 엘리먼트의 텍스트 내용을 _text 키로 저장하며, 각 XML 어트리뷰트 이름/값 쌍을 맵의 키/값 쌍으로 저장합니다.

예를 들어, <doc><id>sample</id></doc> 형태의 XML을 parsexml로 파싱한다면, id 필드에 sample 문자열 값이 할당됩니다. 그러나 <doc><id>sample</id><name locale="ko">로그프레소</name></doc> 형태의 XML이라면 name 필드에는 locale=ko, _text=로그프레소 2개의 키/값을 포함한 맵이 할당됩니다. 이후에 설명할 parsemap 명령어를 조합하면 복합 객체 안에 있는 맵에서 쉽게 필드를 추출할 수 있습니다.

overlay

t로 주면, 원본 필드에 XML에서 추출된 필드를 덧씌운 결과를 출력으로 내보냅니다. 별도로 overlay 옵션을 지정하지 않으면, XML 문자열을 파싱한 결과만 출력으로 내보냅니다.

field

대상 필드를 별도로 지정하지 않는 경우 기본값은 line입니다.

사용 예

1) xml 필드의 XML를 파싱하여 id와 name 필드 추출

json "{'xml': '<record><id>1</id><name>Logpresso</name></record>'}" | parsexml

2) XML에서 id, title, summary 필드 추출

json "{'line': '<feed><id>urn:uuid:60a76c80-d399-11d9-b91C-0003939e0af6</id><entry><title>Atom Feed</title><summary>Some Text</summary></entry></feed>'}"
| parsexml | parsemap field=entry overlay=t

6.15parsekv

문법

parsekv [field=대상필드] [overlay=true] [pairdelim=필드구분자] [kvdelim=키값구분자]

키와 값의 쌍으로 이루어진 로그를 파싱합니다.

field

키, 값 쌍으로 파싱할 대상 필드 이름을 지정합니다. 미설정 시 line으로 지정됩니다.

overlay

true로 지정하는 경우 입력으로 들어온 원본 필드에 파싱된 필드를 덮어씁니다. 미설정 시 파싱된 필드만 출력됩니다.

pairdelim

필드 쌍 구분자를 지정합니다. 미설정 시 공백 문자로 지정됩니다.

kvdelim

키, 값 구분자를 지정합니다. 미설정 시 = 문자로 지정됩니다.

사용 예

json "{'line': 'src=1.2.3.4 src_port=55324 dst=5.6.7.8 dst_port=80'}" | parsekv

6.16parsemap

문법

parsemap [overlay=t] field=대상필드

지정한 대상필드의 값이 맵 타입인 경우, 해당 맵의 모든 키/값을 새로운 필드로 할당합니다. 대상필드의 값이 null이거나 맵 타입이 아닌 경우, 원본 데이터를 그대로 전달합니다.

overlay

t로 주면, 원본 필드에 맵에서 추출된 필드를 덧씌운 결과를 출력으로 내보냅니다. 별도로 overlay 옵션을 지정하지 않으면, 맵을 파싱한 결과만 출력으로 내보냅니다.

field

맵을 포함하고 있는 파싱 대상 필드를 지정합니다.

사용 예

1) complex 필드의 모든 키/값 쌍을 필드로 추출

json "{'complex': {'id':100, 'name':'Logpresso'} }" | parsemap field=complex

6.17rename

문법

rename 원본필드 as 변경필드

원본 필드 이름을 as 뒤에 지정된 필드 이름으로 변경합니다.

사용 예

1) src_ip 필드 이름을 Source로 변경

rename src_ip as Source

6.18limit

문법

limit [건너뛸갯수] 최대갯수
건너뛸 갯수

쿼리 결과에서 앞부분 N개를 건너뜁니다. 생략하면 0으로 지정됩니다.

최대 갯수

쿼리 결과에서 가져올 최대 갯수를 지정합니다.

지정한 쿼리 입력 갯수에 도달하면 쿼리를 취소시킵니다. 일부 명령어의 경우 중간에 쿼리가 취소되면서 의도한대로 동작하지 않을 수 있으므로 주의해야 합니다.

사용 예

1) 가장 먼저 입력으로 들어오는 5건만 조회하고 쿼리 취소

table sys_cpu_logs | limit 5

2) 첫번째 레코드는 제외하고 2건만 조회한 후 쿼리 취소

table sys_cpu_logs | limit 1 2

6.19repeat

문법

repeat count=반복횟수
반복횟수

지정한 숫자 만큼 결과를 반복합니다.

지정한 횟수만큼 결과를 반복해서 보여줍니다. 반복 순서는 일관되지 않아, 각 로우별로 반복되는 경우도 있고 전체 집합별로 반복되는 경우도 있습니다.

사용 예

1) 최근 cpu 사용율 10건을 3번씩 표시

table sys_cpu_logs | limit 10 | repeat count=3

2) 임의의 데이터 100건 생성

json "{}" | repeat count=100 | eval seq=seq() | eval rand_value=rand(100)

6.20boxplot

문법

boxplot 표현식 [by 그룹키1, 그룹키2, ...]

상자 그림(box plot)을 그리는데 필요한 최소, 최대, 사분위수 (five number summary)를 계산합니다.

표현식

통계 대상이 되는 계산 수식을 입력합니다.

그룹키

그룹 단위로 나누어 최소, 최대, 사분위수를 구하려면 그룹을 구분하는 기준이 될 필드 이름을 쉼표로 구분하여 입력합니다.

출력 필드는 아래와 같습니다:

그룹키

by 절에 입력된 그룹 키의 값이 출력됩니다.

min

그룹별 최소값

iqr1

그룹별 제1사분위수

iqr2

그룹별 제2사분위수 (중앙값)

iqr3

그룹별 제3사분위수

max

그룹별 최대값

사용 예

1) 전체 CPU 부하에 대한 통계 요약

table sys_cpu_logs | eval usage = kernel + user | boxplot usage

2) 일자별 CPU 부하에 대한 통계 요약

table sys_cpu_logs 
| eval day = string(_time, "yyyy-MM-dd") 
| eval usage = kernel + user 
| boxplot usage by day

6.21explode

문법

explode 필드이름

지정된 배열의 각 원소마다 대응되는 행을 생성합니다. 일반적으로 배열(가로)을 열(세로) 방향으로 축 변환하려는 경우에 사용합니다. 지정된 필드가 존재하지 않거나, 배열이 아니거나, null인 경우 입력 행을 보존합니다.

필드이름

배열을 포함하는 필드의 이름을 지정합니다.

사용 예

1) IP 통계 추출

json "[{'line': '10.0.0.1 10.0.0.2'},{'line':'10.0.0.2 10.0.0.3'}]"
| eval ip = split(line, " ")
| explode ip
| stats count by ip
  1. eval 명령어로 split 함수를 사용하면 1행은 ["10.0.0.1", "10.0.0.2"], 2행은 ["10.0.0.2", "10.0.0.3"] 배열을 ip 필드에 할당합니다.

  2. explode 함수는 ip 필드의 배열을 기준으로 4개의 행을 생성합니다.

  3. 최종적으로 stats 명령어는 ip 필드를 기준으로 10.0.0.1, 10.0.0.2, 10.0.0.3에 대한 통계를 출력합니다.

6.22signature

문법

signature

line 필드로부터 특수문자의 집합으로 구성된 시그니처를 추출합니다. 보통 파서를 개발하기 전에 패턴 유형별 로그 샘플을 추출하기 위한 용도로 사용합니다.

사용 예

1) 각 시그니처별 첫번째 샘플 로그 추출

signature | stats first(line) by signature

6.23tojson

문법

tojson [output=출력 대상 필드] [출력필드1, 출력필드2, ...]

주어진 필드 값들을 json 포맷의 텍스트로 변환합니다.

출력 대상 필드

json 포맷으로 변환한 결과물이 저장될 필드를 지정합니다. 지정하지 않을 경우 _json 필드에 저장합니다.

출력필드

필드 이름 목록을 지정하면 해당 필드만 json 으로 변환합니다. 출력 필드를 입력하지 않는 경우 모든 필드를 출력합니다.

사용 예

1) 전체 필드를 json 포맷으로 변환해 _json 필드로 출력

tojson

2) 전체 필드를 json 포맷으로 변환해 result 필드로 출력

tojson output=result

3) _time, line 필드를 json 포맷으로 변환해 jsonlog 필드로 출력

tojson output=jsonlog _time, line

6.24prev

문법

prev [입력필드1, 입력필드2, ... ]

prev 명령어의 입력 레코드에서 지정된 필드를 추출하고, 다음 입력 레코드에 직전 레코드의 필드 값을 "prev_필드" 이름의 필드로 추가합니다. 예를 들어, "prev count" 명령어를 사용하는 경우, 출력에 "prev_count" 필드가 추가됩니다. 이 명령어는 주로 데이터의 변화량을 추출하는 용도로 사용됩니다.

사용 예

1) 1분 단위로 GC 횟수의 변화량 계산

table sys_gc_logs 
| timechart span=1m count 
| prev count 
| eval delta = count - prev_count

2) GC 발생 간격이 10초 이내인 GC 로그 조회

table order=asc sys_gc_logs 
| prev _time 
| eval interval = datediff(prev__time, _time, "sec") 
| search interval < 10

6.25curvefit

문법

curvefit [degree=다항 함수의 차수] 독립변수필드, 종속변수필드

최대 1만개의 입력 레코드 값에 대하여 최소제곱법을 이용한 선형회귀분석을 수행합니다. 독립변수 값 및 종속변수 값은 숫자형이어야 합니다. 입력이 완료된 후 선형회귀분석을 수행하고, 주어진 독립변수필드 값을 _x 필드로, 그리고 계산된 함수 값을 _p 필드로 출력합니다. 1만 개 이후의 레코드는 무시되며 쿼리가 종료됩니다.

degree

입력값을 근사시킬 다항 함수의 차수를 의미합니다. 미설정 시 3차 함수로 근사합니다.

사용 예

1) 최근 1시간의 CPU 사용율 추이를 10차 다항함수로 근사

table duration=1h sys_cpu_logs 
| eval x = datediff(dateadd(now(), "hour", -1), _time, "sec")
| eval total = kernel + user 
| curvefit degree=10 x, total

6.26kmeans

문법

kmeans [k=클러스터 수] [iter=반복횟수] 필드1, 필드2, ...

유클리디안 거리를 기반으로 입력 레코드를 K개의 클러스터로 분류합니다. 최대 1만개의 입력 레코드를 허용하며, _cluster 필드에 1부터 증가하는 번호로 클러스터를 분류하여 출력합니다. 필드 값은 숫자형이어야 하며, 지정된 필드 값이 숫자가 아닌 입력 레코드는 무시됩니다. 유효 입력 레코드가 1만개를 넘으면 클러스터링을 수행하고 쿼리가 종료됩니다.

k

클러스터 수, 미설정 시 3개로 지정됩니다.

iter

계산 반복 횟수, 미설정 시 10000번으로 지정됩니다.

사용 예

1) iris 데이터 분류

흔히 인용되는 iris 데이터를 이용하여 kmeans 분류를 시험할 수 있습니다. 길이와 너비를 이용하여 분류를 수행한 후, 실제 종 (species) 이름과 비교해봅니다.

https://raw.githubusercontent.com/uiuc-cse/data-fa14/gh-pages/data/iris.csv
csvfile iris.csv
| eval sepal_length = double(sepal_length), sepal_width = double(sepal_width)
| kmeans k=4 iter=100000 sepal_length, sepal_width

6.27lof

문법

lof [k=이웃노드수] 필드1 [, 필드2, ...] [by 그룹필드1, 그룹필드2, ... ]
k

밀도 계산에 사용할 이웃 노드의 수를 설정합니다. 미지정 시 기본값은 10입니다.

가장 인접한 K개의 이웃을 기준으로 각 점의 밀도를 계산하고, 인접한 이웃과 상대적인 밀도의 비율을 계산하여 LOF (Local Outlier Factor) 지수를 계산합니다. 필드 값은 정수, 실수, 날짜처럼 숫자형 데이터만 허용됩니다. by 절을 사용하는 경우, 그룹 필드로 구분된 각 그룹별로 LOF 지수를 계산합니다. 각 레코드마다 _lof 필드가 출력되는데 이 LOF 값은 아래와 같이 분류할 수 있습니다:

_lof > 1

군집의 바깥쪽에 위치합니다. 1보다 클수록 이상치일 가능성이 높습니다.

_lof = 1

군집의 경계에 위치합니다.

_lof < 1

군집의 내부에 위치합니다.

그룹별 스코어링을 사용하는 경우 각 그룹의 레코드 수는 이웃노드 수 (k 값) 보다 많아야 합니다. 이웃노드 수보다 그룹의 레코드 수가 적으면 모든 점이 하나의 군집으로 잡히기 때문에 이상지수 (_lof 출력값) 가 의도한대로 계산되지 않습니다.

사용 예

1) iris 이상치 탐지

sepal_length와 sepal_width 필드 값을 기준으로 이상치를 계산합니다.

https://raw.githubusercontent.com/uiuc-cse/data-fa14/gh-pages/data/iris.csv
csvfile iris.csv
| eval sepal_length = double(sepal_length), sepal_width = double(sepal_width)
| lof sepal_length, sepal_width
| search _lof > 2

6.28stl

문법

stl [period=시간단위] 필드

STL은 seasonal-trend decomposition procedure base on loess 의 약어로, 시계열 데이터를 추세 (trend), 계절적 변동 (seasonality), 잔차 (error)로 분해합니다. period가 생략된 경우, 스펙트럼 분석을 통해 자동으로 계절변동 주기를 계산합니다. 필드 값은 정수, 실수, 날짜처럼 숫자형 값만 허용됩니다.

stl 커맨드는 시계열 데이터를 분석하여 _trend, _seasonal, _error 필드를 출력하는데, 시계열 데이터가 주기성이 없는 경우 _seasonal 필드를 출력하지 않습니다. period를 설정한 경우 지정된 주기로 시계열 데이터가 반복성을 가진다고 가정하고 분석하며, 강제로 period를 0m으로 지정한 경우에는 주기성이 없으므로 _seasonal 필드를 출력하지 않습니다.

6.29pivot

문법

pivot [parallel=t] 그룹함수1 [as 출력이름1] [, 그룹함수2 [as 출력이름2], ...] [by/rows 필드1, 필드2, ...] [for/cols 필드1, 필드2, ...]
parallel

t로 설정 시, 쿼리를 병렬 처리합니다. 이 옵션을 사용하면 처리 속도가 증가하지만, 데이터의 순서를 보장하지 않습니다.

그룹을 대상으로 동작하는 집계 함수의 평가 결과를 출력합니다. by/rows 절이나 for/cols 절이 지정되지 않은 경우 이전 쿼리 명령어에서 넘어오는 전체 로그를 하나의 그룹으로 계산합니다. 그룹 필드를 기준으로 정렬되는 부수적인 효과가 있습니다.

사용 예

1) 계수

pivot count

2) src_ip 단위 계수

pivot count by src_ip

3) src_ip와 dst_ip 쌍에 대한 protocol별 계수

pivot count by src_ip, dst_ip for protocol

4) src_ip와 dst_ip 쌍에 대한 protocol별 bytes 총합과 계수

pivot sum(bytes) as bytes, count rows src_ip, dst_ip cols protocol

6.30rollup

문법

rollup [label=라벨명] 그룹함수1 [as 출력이름1] [, 그룹함수2 [as 출력이름2], ...] [by 필드1, 필드2, ...]

그룹 함수 사용 시 항목별 합계가 필요한 경우 rollup 함수를 사용합니다. by 절에 여러 필드가 있을 경우 필드 순서대로 합계값을 표시합니다.

label

집계값에 표시할 라벨명을 입력합니다. 미설정시 null값으로 표시합니다.

사용 예

1) action 필드별 계수 및 전체 계수

rollup count by action

2) action, status 필드별 계수와 size 합계 및 action 필드별 계수와 size 합계 (라벨은 "TOTAL"로 표시)

rollup label=TOTAL count, sum(size) as size by action, status

6.31cube

문법

cube [label=라벨명] [parallel=t] 그룹함수1 [as 출력이름1] [, 그룹함수2 [as 출력이름2], ...] [by 필드1, 필드2, ...]

그룹 함수 사용 시 모든 항목별 합계가 필요한 경우 cube 함수를 사용합니다. by 절에 여러 필드가 있을 경우 모든 필드 조합에 대한 합계값을 표시합니다.

label

집계값에 표시할 라벨명을 입력합니다. 미설정시 null값으로 표시합니다.

parallel

t로 설정 시, 쿼리를 병렬 처리합니다. 이 옵션을 사용하면 처리 속도가 증가하지만, 데이터의 순서를 보장하지 않습니다.

사용 예

1) action 필드별 계수 및 전체 계수

cube count by action

2) action, status 필드별 계수와 size 합계 및 action 필드별 계수와 size 합계 (라벨은 "TOTAL"로 표시)

cube label=TOTAL count, sum(size) as size by action, status

6.32forecast

문법

forecast [period=N] [count=M] [time=시간필드] [seed=고정시드] 필드명 [by 파티션1, 파티션2, ...]

주어진 시계열 데이터에 대해 예측 데이터를 출력합니다. timechart 커맨드 등으로 시간 필드의 데이터의 간격이 일정하도록 설정한 후 forecast 커맨드를 사용하는 것을 권장합니다. 입력 데이터는 파티션 별로 4건 이상 있어야하며, period값은 입력데이터 건수의 반 이하여야 합니다.

period

데이터의 주기를 입력합니다. 미입력시 자동으로 주기를 계산합니다.

count

출력할 데이터 로우 수를 입력합니다. 미입력시 5건을 출력합니다.

time

시간 필드로 사용할 필드명을 입력합니다. 미입력시 _time 필드를 사용합니다.

seed

고정시드 값을 입력합니다. 같은 입력에 대해 같은 결과를 유지하고 싶은 경우 고정시드값을 지정해서 입력하면 됩니다.

사용 예

1) count 필드의 forecast값 추출

forecast count

2) 주기가 5, 시간 필드가 set_time, 고정 시드가 1234인 필드 traffic의 forecast값 추출

forecast period=5 time=set_time seed=1234 traffic

3) sent_bytes 필드의 region 필드별 forecast값을 10건씩 추출

forecast count=10 sent_bytes by region

6.33alertmsg

문법

alertmsg locale=로케일명

경보 알림 메세지를 사용자 세션의 언어에 맞추어 변환합니다.

locale

경보 알림 메세지의 언어를 지정합니다.

사용 예

1) 경보 알림 메세지를 한국어로 변환

table sys_alerts | alertmsg locale=ko

6.34auditmsg

문법

auditmsg locale=로케일명

감사 메세지를 사용자 세션의 언어에 맞추어 변환합니다.

locale

감사 메세지의 언어를 지정합니다.

사용 예

1) 감사 메세지를 한국어로 변환

table sys_audit_logs | auditmsg locale=ko

6.35order

문법

order 필드1, [필드2], ...

결과 데이터 집합에서 특정 필드만 맨 앞으로 출력해 줍니다. fields 커맨드는 결과 데이터 셋에서 필드의 포함 여부까지 결정되지만 order 커맨드는 쿼리 결과에 있는 필드는 order 필드 순으로 정렬하고 order에 없는 필드는 order 필드들 뒤에 사전순으로 정렬해서 표시합니다.

사용 예

1) sys_cpu_logs 테이블의 필드 출력 순서를 kernel, idle, user, _time, _table, _id 순서로 정렬

table sys_cpu_logs | order kernel, idle, user, _time, _table, _id

2) sys_cpu_logs 테이블의 필드 출력 순서를 idle, kernel을 가장 먼저 출력하고 나머지는 사전순으로 정렬

table sys_cpu_logs | order idle, kernel

6.36bypass

문법

bypass

모든 입력 값을 그대로 출력합니다. 모든 입력 필드에 대해 필드 인덱스를 생성하거나 스트림 쿼리에서 모든 결과를 그대로 통과시키는 목적으로 사용합니다.

Count of comments [0]