Tech 기록지/Elastic Stack

[ElasticStack-22] Vector data indexing via Logstash & Elasticsearch

Lio Grande 2020. 6. 29. 10:43

다음과 같은 vector data 파일이 있다고 하자.

[
	1.2,
    1.3,
    1.4,
    1.5
]

일반적인 JSON 형태가 아니므로, Logstash에서 접근할만한 방법으로는 multiline codec을 생각해볼 수 있다.

input{
	path => "FILE_PATH"
    start_position => "beginning"
    sincedb_path => "/dev/null"
    codec => multiline {
    	pattern => "^\\n"
        negate => true
        what => "previous"
        auto_flush_interval => 1
    }
}

이것을 기반으로 바로 인덱싱을 수행해보았으나 Doc가 생성되지 않았다. 그래서 쿼리로 인덱스를 생성하고, vector 타입을 가지는 필드를 매핑한 후 Logstash를 실행하기로 하였다.

PUT index/_doc/vec ## index_name/doc_type/id 의 형태
{
	"mappings": {
    	"properties": {
        	"message": {
            	"type": "dense_vector",
                "dims": 4	## 차원 수 (dims)는 [1.2, 1.3, ..] 리스트의 값 개수와 동일
            },
            "vec_s" {
            	"type": "dense_vector",
                "dims": 4
            }
        }
    }
}

vector data의 라인이 아주 길다면 기본 input 세팅만으로는 데이터가 한번에 인덱싱되지 않는다. 그럴때는 다음과 같은 옵션을 사용해주자.

input{
        file{
                path => "FILE_PATH"
                start_position => "beginning"
                sincedb_path => "/dev/null"
                codec => multiline {
                        pattern => "^\\n"
                        negate => "true"
                        what => "previous"
                        auto_flush_interval => 1
                        max_lines => 10000	## DEFAULT IS 500
                        max_bytes => 100000 ## DEFAULT IS 1000
                }
        }
}

Logstash로 인덱싱하게되는 데이터들은 기본적으로 "message" 필드에 인덱싱된다. filter 옵션을 사용하여 특수문자(대괄호 등)를 제거하고, 새로운 필드에 값들을 넣어주자

filter{
	mutate{
    	gsub => ["message", "\[", ""] ## [ 제거
        gsub => ["message", "\]", ""] ## ] 제거
        gsub => ["message", "\n", ""]
        gsub => ["messgae", "  ", ""] ## 두 칸 공백을 공백없는 칸으로
        
        add_field => { "vec_s" => "%{message}" } ## 임의의 필드 생성
        copy => { "message" => "vec_s" } ## 필드의 값을 복사
        gsub => ["vec_s", "\[", ""]
        gsub => ["vec_s", "\]", ""]
        
        remove_field => ["message", "path", "@timestamp", "host", "tags"]
	}
}

### message의 값을 vec_s로 값 할당

위의 과정들을 종합한 conf 파일 내역은 다음과 같다.

input{
        file{
                path => "FILE_PATH"
                start_position => "beginning"
                sincedb_path => "/dev/null"
                codec => multiline {
                        pattern => "^\\n"
                        negate => "true"
                        what => "previous"
                        auto_flush_interval => 1
                        max_lines => 10000
                        max_bytes => 100000
                }
        }
}

filter{
        mutate{
                gsub => ["message", "\[", ""]
                gsub => ["message", "\]", ""]
                gsub => ["message", "\n", ""]
                gsub => ["message", "  ", ""]

                add_field => {"vec_s" => "%{message}"}
                gsub => ["vec_s", "\[", ""]
                gsub => ["vec_s", "\]", ""]
                #convert => { "vec_s" => float }

                remove_field => ["message", "path", "@timestamp", "host", "tags"]
        }
}

output{
        elasticsearch{
                hosts => "localhost:9200"
                index => "INDEX_NAME"
        }
        stdout{
                codec => rubydebug
        }
}

 

P.S - 2020.06.30 기준 테스트 결과 위 과정으로 테스트 시 대괄호 ( ' ] ') 가 입력되지 않는 상황(무시)이 발생함

해결법을 찾아보려고 하였으나 Logstash 자체 문제인것으로 판단 (마지막줄 무시)