2022-06-23,   김수민

이번 포스팅에서는 Grok에 대해 알아보겠습니다.


Grok

grok은 메세지의 형태를 정의하고, 정의된 형식대로 데이터를 추출하기 위한 방식 입니다.

Logstash에서 해당 방식을 데이터의 구조를 도출하고, 처리하는 방법으로 사용하고 있습니다.

  • Logstash : 서버의 데이터를 처리하는 파이프라인 오픈소스

grok는 데이터를 key-value 형태로 적재해 이후 과정에서 사용하기 용이하게 해줍니다.

다만, 올바르게 최적화 되지 않은 경우 처리 속도가 느려질 수 있어 주의가 필요합니다.


Grok 형태

앞서 말했듯, grok은 데이터를 key-value 형태로 적재하게 되는데, 이를 위해 다음의 일정한 형식으로 작성됩니다.

%{SYNTAX : SEMANTIC}

  • SYNTAX

    • logstash input에서 감지해야하는 정규식 패턴

    • 기본 패턴 사전과 커스텀 패턴 사전 두 종류가 들어갈 수 있음

      • 기본 패턴 사전 : logstash 기본 패턴 사전에 이미 등록되어 있는 패턴

        ​ (USERNAME, USER, INT, NUMBER, WORD 등)

      • 커스텀 패턴 사전

        • /usr/share/logstash/pipeline/patterns 디렉토리에 설정파일을 생성해 사용 합니다.
        • 파일은 확장자가 없이 생성하며, 해당 디렉토리 내의 모든 파일이 logstash에 import 됩니다.
        • SYNTAX명 정규표현식(혹은 값, 문자열)‘의 형태로 작성합니다.
        • 적용 전 패턴 테스트를 수행할 수 있는 사이트가 있으니 참고 바랍니다. (http://grokconstructor.appspot.com/do/match)
  • SEMANTIC

    • 감지된 패턴 데이터를 할당할 변수 명(식별자)

Pygrok

python에서 위에 설명한 grok을 사용하기 위한 패키지 입니다.

기본적으로 사용되는 패턴들은 이미 내장되어 있어 추가로 선언할 필요가 없습니다.

(WORD, NUMBER, BASE10NUM, IP, HOSTNAME, URIPATH, DATE 등)

패턴명 설명
WORD 단일 단어에 일치하는 패턴
NUMBER 양이나 음의 정수 또는 부동 소수점에 일치하는 패턴
POSINT 양의 정수와 일치하는 패턴
IP IPv4 또는 IPv6 IP 주소와 일치하는 패턴
NOTSPACE 스페이스가 아닌 모든 것과 일치하는 패턴
SPACE 모든 수의 연속적 스페이스와 일치하는 패턴
DATA 제한된 양의 모든 종류의 데이터와 일치하는 패턴
GREEDYDATA 모든 남아 있는 데이터와 일치하는 패턴

이외에 내장 패턴을 참고하기 위해서는 다음을 참고하세요.

https://github.com/garyelephant/pygrok/tree/master/pygrok/patterns


Pygrok 예제

우선 사용을 위해 pygrok을 설치해 줍니다.

pip install pygrok

기본적으로 pygrok은 패턴 모양을 원하는 변수와 타입을 정해 %{타입:변수명}으로 입력해줍니다.

from pygrok import Grok

text = '2022-05-30T19:20:30.45+01:00 DEBUG This is a sample log‘

# 패턴
pattern = '%{TIMESTAMP_ISO8601:time} %{LOGLEVEL:logLevel} %{GREEDYDATA:logMessage}

# Grok 객체 생성 및 패턴 입력
grok = Grok(pattern)

# match 수행
print (grok.match(text))
<출력결과>
{'time': '2022-05-30T19:20:30.45+01:00', 'logLevel': 'DEBUG', 'logMessage': 'This is a sample log'}

이때, 원하는 패턴이 기본 패턴 사전에 없는 경우 사용자가 정의해 삽입하면 됩니다.

사용자 정의 방법에는 코드 내부에 선언하는 방법과 파일로 분리하는 방법이 있습니다.

두 방법 모두 Grok 객체를 생성할 때 파라미터로 생성한 패턴을 전달하면 됩니다.

# 예문
text = 'gary is male, 25 years old and weighs 68.5 kilograms and phonenum=010-1234-1234'

pattern = '%{WORD:name} is %{WORD:gender}, %{NUMBER:age} years old and weighs %{NUMBER:weight} kilograms and phonenum=%{PHONENUMBER:phone}'

# 방법1. 패턴을 코드 내부에 작성
pat={"PHONENUMBER": '\d{3}-\d{3,4}-\d{4}'}
grok = Grok(pattern,custom_patterns=pat)	

print(grok.match(text))
<출력결과>
{'name': 'gary', 'gender': 'male', 'age': '25', 'weight': '68.5', 'phone': '010-1234-1234'}

다음은 파일로 생성했을 때의 예시 입니다.

파일은 다음과 같이 patterns라는 디렉토리를 생성하고, 그 안에 원하는 패턴을 넣어줍니다.

이때, 디렉토리 명은 꼭 patterns여야 하는 것은 아닙니다.

그림1

파일 내부 내용은 다음과 같이 ‘패턴명(space)정규표현식’ 형태로 정의되어 있습니다.

PHONENUMBER \d{3}-\d{3,4}-\d{4}
# 예문
text = 'gary is male, 25 years old and weighs 68.5 kilograms and phonenum=010-1234-1234'

pattern = '%{WORD:name} is %{WORD:gender}, %{NUMBER:age} years old and weighs %{NUMBER:weight} kilograms and phonenum=%{PHONENUMBER:phone}'

# 방법2. 패턴을 파일로 저장 후 파일 저장된 디렉터리 불러오기
grok = Grok(pattern, custom_patterns_dir=./patterns)

print(grok.match(text))
<출력결과>
{'name': 'gary', 'gender': 'male', 'age': '25', 'weight': '68.5', 'phone': '010-1234-1234'}

참고로, pattern과 맞지 않은 경우, pattern과 맞는 일부만 출력되는 것이 아닌, None이 return되게 되니 주의가 필요합니다.

# 예문
text = 'gary is male, 25 years old and weighs 68.5 kilograms and sentence=nottestline'

pattern = '%{WORD:name} is %{WORD:gender}, %{NUMBER:age} years old and weighs %{NUMBER:weight} kilograms and sentence=%{DEBUG:test}'

pat={"DEBUG": 'testline'}		# 정규표현식이 아닌 경우에도 grok 패턴으로 선언 가능
grok = Grok(pattern,custom_patterns=pat)

print(grok.match(text))
<출력결과>
None

이번 포스팅 에서는 grok에 대한 소개와 pygrok에서 이미 내장된 패턴을 사용하는 방법과 커스텀 패턴을 생성해 사용하는 방법에 대해 알아보았습니다.


참고자료

[1] https://a3magic3pocket.github.io/posts/logstash-grok-pattern/#logstash-%EC%A0%95%ED%98%95%ED%99%94-%EB%B0%A9%EB%B2%95

[2] https://www.infoking.site/72

[3] https://medium.com/analytics-vidhya/groks-in-python-b0ad4b6946c8

[4] https://ontheterrace.tistory.com/entry/logstash-grok-%EC%9E%91%EC%84%B1%ED%95%98%EA%B8%B0

업데이트: