| 일 | 월 | 화 | 수 | 목 | 금 | 토 |
|---|---|---|---|---|---|---|
| 1 | 2 | 3 | 4 | 5 | 6 | |
| 7 | 8 | 9 | 10 | 11 | 12 | 13 |
| 14 | 15 | 16 | 17 | 18 | 19 | 20 |
| 21 | 22 | 23 | 24 | 25 | 26 | 27 |
| 28 | 29 | 30 | 31 |
- CKA
- 코틀린 코루틴의 정석
- golang
- 정보처리기사 실기 기출문제
- AI
- Pinpoint
- kotlin querydsl
- CKA 기출문제
- kotlin
- 티스토리챌린지
- Kubernetes
- SRE
- 오블완
- CloudWatch
- aws
- APM
- 기록으로 실력을 쌓자
- 바이브코딩
- kotlin coroutine
- MySQL
- tucker의 go 언어 프로그래밍
- Spring
- minikube
- Linux
- go
- AWS EKS
- 컨텍스트 엔지니어링
- 공부
- PETERICA
- Java
- Today
- Total
피터의 개발이야기
[Fluentd] multiline parser, 로그병합과 필터링 본문
ㅁ 들어가며
Kibana에서 시스템 로그를 분석하는 과정에서 일부 로그가 누락되는 현상을 발견하였다. Fluentd로그에서 parser 오류를 발견하고 이를 해결하는 과정에서 multiline parser에 대해서 공부한 내용을 정리하였다.
에러 확인: fluent-plugin-concat을 사용하고 있어, multiline_start_regexp와 multiline_stop_regexp 수정 과정,
개념정리: Fluentd의 multiline 공식 문서를 통해 개념을 정리하였다.
ㅁ Fluentd 에러 확인
2025-09-05 05:30:36 +0000 [warn]: #0 dump an error event: error_class=Fluent::Plugin::Parser::ParserError error="pattern not matched with data
ㅁ 에러 원인 분석
<filter **>
@type concat
key log
separator ""
multiline_end_regexp /\n$/
flush_interval 2s
</filter>
<filter **>
@type parser
key_name log
reserve_data true
<parse>
@type regexp
expression /^(?<logtime>\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}\.\d{3})/
time_key logtime
time_format %Y-%m-%d %H:%M:%S.%L
timezone +09:00
keep_time_key true
<record>
time ${Time.parse(record["logtime"]).strftime('%Y-%m-%dT%H:%M:%S.%LZ')}
</record>
</parse>
</filter>
ㅇ fluent.conf의 filter 부분이다.
expression /^(?<logtime>\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}\.\d{3})/
ㅇ 현재 파서의 expression은 맨 앞에 시간을 캡처하도록 되어 있다.
\tat com.kaka....(JsWorkerRunner.scala:152)\n
ㅇ 하지만 문제의 라인은 "\tat"로 시작하고, 시간/레벨/로거 같은 헤더가 없었다.
ㅁ Fluentd ParserError 해결
[이전]
multiline_end_regexp /\n$/
[수정]
multiline_start_regexp /^(?:\d{4}-\d{2}-\d{2}|\d{8})[ T]\d{2}:\d{2}:\d{2}(?:[.,]\d{3})?\b/
ㅇ 멀티라인 결합을 “끝 패턴”이 아닌 “시작 패턴”**으로 전환해,
^\d{4}\d{2}\d{2} ...로 시작하는 줄에서만 새 이벤트를 시작하도록 했다.
ㅇ 이어지는
\tat ..., Caused by: ...
같은 줄은 모두 이전 이벤트에 이어붙인다.
ㅇ 이렇게 결합된 하나의 블록만 정규식 파서에 넘기면,
파서는 첫 줄에서 시간/레벨/로거만 파싱하고 나머지 스택트레이스는 메시지로 포함되어 정상 처리된다.
ㅇ 정리하면
\tat ... 줄이 잘못된 게 아니라,
단독으로 한 줄 파서에 들어가 실패했던 것.
따라서 “시작 패턴 기반 멀티라인으로 묶고 → 파싱” 순서로 바꾸면 해결된다.
ㅁ Fluentd 멀티라인 이란?
멀티라인의 정의 및 특징
ㅇ 여러 줄에 걸쳐 하나의 로그 이벤트가 기록되는 현상으로, 자주 발생하는 예시로는 Java Stack Trace, 서비스 오류 로그 등이 있다.
ㅇ 멀티라인 로그는 시작 줄과 이어지는 줄의 패턴이 있어, 이를 적절히 감지해서 하나의 이벤트로 묶는다.
멀티라인으로 처리해야 하는 실무적 이유
ㅇ 각 줄을 개별 이벤트로 인식할 경우 실질적인 오류의 맥락이 분리되어, 원인 분석과 모니터링이 어려워진다.
ㅇ 로그의 일관된 집계, 분석, 저장을 위해 반드시 논리적으로 병합하는 작업이 필요하다.
ㅇ 멀티라인 결합이 누락되면 이벤트 지연, 로그 손실, 정상적인 적재 불가, 성능 저하 등 다양한 문제가 발생할 수 있다.
Fluentd에서 멀티라인 설정 및 conf 예시
<source>
@type multiline
# ...
<parse>
# ...
</parse>
</source>
ㅇ <source>의 @type tail에 <parse> 블록을 두고 @type multiline을 명시한다.
ㅇ Fluentd 공식 문서 > Config: Parse Section
<parse>
@type multiline
format_firstline /\d{4}-\d{1,2}-\d{1,2}/
format1 /^(?<time>\d{4}-\d{1,2}-\d{1,2} \d{1,2}:\d{1,2}:\d{1,2}) \[(?<thread>.*)\] (?<level>[^\s]+)(?<message>.*)/
</parse>
ㅇ format_firstline, format1 등 정규식 패턴으로 시작 줄 및 이어지는 줄 포맷을 정의하여 이벤트를 분리/결합한다.
ㅇ multiline_flush_interval 등 파라미터로 집계 주기를 세밀하게 제어하여 성능과 데이터 정확성을 최적화한다.
ㅁ 함께 보면 좋은 사이트
'DevOps' 카테고리의 다른 글
| [Kibana] Kibana Saved Objects 관리와 백업 (0) | 2025.09.06 |
|---|---|
| 하이브리드 인증서란? RSA와 ECC를 모두 아우르는 인증서 (4) | 2025.08.05 |
| RTO와 RPO: 재해 복구 계획의 핵심 지표 (0) | 2025.02.28 |
| Ubuntu 버전 및 EOL(End of Life) 날짜 정리 (0) | 2025.02.05 |
| [DevOps] Bamboo: DevOps와 CI/CD를 위한 강력한 도구 (0) | 2024.12.17 |
