본문 바로가기

Database/MongoDB

MongoDB - Collect slow query using Fluentbit and Opensearch

개요

MongoDB는 audit log가 아닌 log는 단일 로그 파일로 로그를 남긴다. 이 때, 운영상 중요한 slow query 로그나, error 로그들도 단일 파일에 남기 때문에 이런 로그들의 관리가 어려워지는 경우가 종종 있다. 로그를 수집하여 Opensearch에 적재하는 경우 대량의 로그가 쌓이다보면 로그의 retention을 짧게 조정해야만 하는 경우가 생긴다. slow query나 error로그는 더 긴 기간동안 보고싶지만 하나의 Index에서 관리하다 보니 오래 보지 못하는 경우가 종종 생긴다. 

 

이 글에서는 Fluentbit와 opensearch를 사용해 MongoDB의 로그를 수집하는 방법을 설명한다. 이 때, slow query와 error로그는 별도의 Opensearch Index에 추가적으로 저장하여 일반적인 로그와 slow query 로그 + error 로그를 별도로 관리할 수 있는 방법을 설명한다. 

 

이번 글에서 Fluentbit 설치는 다루지 않는다. Fluentbit가 설치되어있다고 가정한다. 

Fluentbit

https://fluentbit.io/

 

fluentbit

Fluent Bit is a CNCF (Cloud Native Computing Foundation) graduated project under the umbrella of Fluentd. We are part of a large open source community. No vendor lock-in.

fluentbit.io

 

Fluentbit는 로그 수집기이다. 보통 수많은 서버를 운영하는 경우 로그파일을 하나의 저장소에 모은 뒤 해당 데이터 저장소에서 데이터를 관리한다. Fluentbit를 사용하면 서버에 남는 로그들을 다양한 데이터 저장소에 보낼 수 있다. 

 

 

이런식으로 구성된다. 

 

Opensearch

https://opensearch.org/

 

OpenSearch

OpenSearch is a community-driven, Apache 2.0-licensed open source search and analytics suite that makes it easy to ingest, search, visualize, and analyze data.

opensearch.org

 

많은 기업에서 로그를 저장하는 저장소로 Opensearch를 사용하고 있다. ElasticSearch의 포크본이며 기능이 거의 비슷하다. 검색이 매우 빠르며 확장성이 좋다. 

 

Fluentbit - Routing 

https://docs.fluentbit.io/manual/concepts/data-pipeline/router

Fluentbit는 Routing 기능을 제공한다. 
Routing 기능은 Tags와 Matching 기능을 기반으로 동작한다. 

Tag는 보통 사람이 수동으로 지어주는 속성이다. 
데이터를 routing할 곳을 정하기 위해서는 output configuration에 Match rule을 사용한다. 
Tag로 데이터에 속성을 달아주고, Match는 Tag를 어떤 Output으로 보낼 것인지를 정의한다. 

Fluentbit의 config는 보통 다음과 같이 구성된다. 

데이터가 INPUT에서 들어와서 OUTPUT으로 나간다. 

[INPUT]
    Name cpu
    Tag  my_cpu

[INPUT]
    Name mem
    Tag  my_mem

[OUTPUT]
    Name   es
    Match  my_cpu

[OUTPUT]
    Name   stdout
    Match  my_mem


이때 Match는 정규표현식을 사용해서 조건에 맞는 Tag를 설정할 수 있다.

 

Rewrite_tag

https://docs.fluentbit.io/manual/pipeline/filters/rewrite-tag

Filter의 rewrite_tag를 사용하면, 조건에 맞는 Input에 다시 Tag를 달아줄 수 있다. 
조건에 맞는 Record를 Re-emit, 즉 신규로 Record가 하나 생기는 방식이다. 

 

rewrite_tag 는 Rule, Emitter_Name, Emitter_Storage.type, Emitter_Mem_Buf_Limit 속성을 설정할 수 있다. 

 

RULE

rewrite_tag의 Rule은 다음과 같이 정한다. 

<KEY> <REGEX> <NEW_TAG> <KEEP>

 

KEY : 어떤 KEY의 
REGEX : 해당 정규표현식에 일치하는 Record라면 
TAG : 해당 태그를 붙인다. 
KEEP : 기존 Record는 유지할지 여부를 정한다. 

 

Emitter_Name

새로운 Tag를 붙인 Record를 발행할 때, 내부적으로 emit하는 job이 있다. 이 emitter(job)은 파이프라인의 다른 구성요소로 노출되기 때문에 이 속성을 사용해 이름을 붙여줄 수 있다. 

 

Emitter_Storage.type

새로운 Record 생성에 대한 매커니즘을 정의한다. 
memory 혹은 filesystem을 지원하며, new records를 보내는 latency가 길거나 network이 느리다면, 메모리 사용랑이 증가하는 현상을 맞이할 수 있다. 
이럴 때에는 filesystem 모드를 사용하길 강력하게 권장한다. 

 

Emitter_Mem_Buf_Limit

rewrite emitter가 사용하는 memory의 양을 조절할 수 있다. 
기본은 10M. emitter가 사용하는 memory 양이 10M를 초과하면 사용하는 메모리 양이 10M이하로 내려갈 때 까지 emitter 동작이 중지된다. 

 

MongoDB Logs 

MongoDB는 4.4 버전 이상부터 로그를 json 형식으로 남기기 때문에 로그를 파싱하기 위한 별도의 모듈이 필요하지 않다. 보통의 로그 수집기에서 제공하는 json 형식을 파싱하는 파서를 사용한다. 

 

MongoDB에서 slow query는 attr.durationMillis 라는 값을 가진다. 따라서, attr.durationMillis가 기준치가 넘는 값을 가지는지를 검사하여 별도의 인덱스에 적재해주면 된다. 

MongoDB에서 error 로그는 "s" 필드가 "E" 로 남게 된다. 따라서, s가 E인지를 검사하여 별도의 인덱스에 적재해주면 된다. 

 

Fluentbit Conf

서론이 길었다. 다음과 같이 Fluentbit의 Config를 설정하면 fluentbit에서 바로 Opensearch로 로그를 적재한다. 

이 때, Slow query와 error 로그는 별도의 인덱스에 적재하게 된다. 

 

[SERVICE]
    Flush         1
    Parsers_File  parsers.conf
    Log_File      /var/log/fluent-bit.log
    Log_Level     debug

[INPUT]
    Name          tail
    Path          <mongodb log path>
    Tag           mongodblog*
    DB            /var/log/flb_mongodb.db
    Parser        json
    Mem_Buf_Limit 5MB

[FILTER]
    Name type_converter
    Match *
    uint_key $attr['durationMillis'] attr.durationMillis string

[FILTER]
    Name rewrite_tag
    Match mongodlog*
    Rule attr.durationMillis "^\d+$" slowlogs true
    Emitter_name slow-log-emitted

[FILTER]
    Name rewrite_tag
    Match mongodlog*
    Rule s "E" errorlogs true
    Emitter_name error-log-emitted

[OUTPUT]
    Name          opensearch
    Match         slowlogs
    Host          <opensearch host address>
    Port          <opensearch port>
    Index         slowlogs
    Type          mongodblog
    TLS           On
    Suppress_Type_Name On
    Generate_ID   On
    Logstash_Format Off
    HTTP_User     <opensearch user>
    HTTP_Passwd   <opensearch password>

[OUTPUT]
    Name          opensearch
    Match         errorlogs
    Host          <opensearch host address>
    Port          <opensearch port>
    Index         errorlogs
    Type          mongodblog
    TLS           On
    Suppress_Type_Name On
    Generate_ID   On
    Logstash_Format Off
    HTTP_User     <opensearch user>
    HTTP_Passwd   <opensearch password>

[OUTPUT]
    Name          opensearch
    Match         mongodblog*
    Host          <opensearch host address>
    Port          <opensearch port>
    Index         generallogs
    Type          mongodblog
    TLS           On
    Suppress_Type_Name On
    Generate_ID   On
    Logstash_Format Off
    HTTP_User     <opensearch user>
    HTTP_Passwd   <opensearch password>

 

attr.durationMillis가 number type으로 수집되기 때문에, 정규표현식을 사용하기 위해서라면 string type으로 변경해주어야하는 것을 주의하자. 

'Database > MongoDB' 카테고리의 다른 글

MongoDB Task Executor Pool  (0) 2025.01.17
MongoDB Debug Mode로 빌드하기  (1) 2024.12.22
WiredTiger 직접 빌드해서 MongoDB 데이터파일 살펴보기  (5) 2024.11.09
MongoDB Journaling  (1) 2024.10.09
MongoDB Replication  (1) 2024.09.15