Bronto에서의 AI를 활용한 로그 파싱 (Log Parsing)
요약
Bronto는 다양한 형식의 비구조화 및 반구조화 로그를 자동으로 구조화하기 위해 AI를 활용한 혁신적인 로그 파싱 접근 방식을 제안합니다. 실시간 성능을 보장하기 위해 오프라인 탐지와 온라인 파싱을 분리한 하이브리드 모델을 사용하며, 고성능 Java 기반 파서를 통해 효율적인 데이터 처리를 구현합니다.
핵심 포인트
- 로그 형식의 다양성 문제: syslog, Apache, nginx, Java 앱 등 기술 스택마다 로그 형식이 상이하여 표준화가 어려움
- 하이브리드 파싱 전략: 실시간 성능을 위해 온라인 파싱과 오프라인 탐지를 분리하여 병목 현상 방지
- 자동 파서 생성: AI를 활용하여 복잡한 정규 표현식 작성 없이도 로그를 자동으로 구조화
- 고성능 Java 파서 활용: 가장 빈번한 로그 형식에 최적화된 고속 Java 라이브러리를 통해 처리 속도 극대화
Gary Nicholls 작성. 이 포스트는 작은 LLM(Large Language Models)이 로그 분석 작업에서 어떻게 성능을 발휘하는지 탐구했던 우리의 AWS Nova 로그 벤치마킹 기사에 이어지는 내용입니다. 이전 포스트에서는 LLM이 로그를 파싱하는 데 놀라울 정도로 뛰어나다는 점을 강조했습니다. 이전 작업이 로그를 이해하는 데 중점을 두었다면, 이번 포스트는 그 이전 단계인 AI를 사용하여 로그를 자동으로 구조화하는 문제를 다룹니다.
로그의 기원
로그는 가장 오래된 — 그리고 여전히 가장 가치 있는 — 관측성 (Observability) 형태 중 하나입니다. 메인프레임과 초기 Unix 시스템은 이미 시스템 활동을 기록하기 위해 로그를 사용하고 있었으며, syslog와 같은 도구는 1980년대 초반까지 거슬러 올라갑니다. 시스템이 더욱 분산되고 복잡해졌음에도 불구하고, 로그는 특히 문제가 발생했을 때 원인을 조사하는 데 있어 여전히 기초적인 역할을 합니다. 로그는 일반적으로 로컬 파일에 기록된 후, OpenTelemetry 또는 Fluent Bit와 같은 에이전트를 사용하여 현대적인 관측성 플랫폼으로 전송됩니다.
왜 이렇게 형식이 다양한가?
OpenTelemetry (OTel) 프로젝트는 구조화된 JSON 로그의 채택을 권장하고 있으며, 이는 좋은 현상입니다. 구조화된 로그는 검색이 더 쉽고, 사람이 읽기 더 편하며, 조작하기 더 안전하고, 더 클라우드 네이티브 (Cloud-native) 합니다. 하지만 현실은 그렇게 단순하지 않습니다. 많은 시스템이 여전히 자유 형식의 텍스트 메시지 안에 key=value 쌍이 포함된 비구조화(Unstructured) 또는 반구조화(Semi-structured) 로그를 생성합니다. 또한 구조화된 형식 사이에서도 차이가 매우 심하며, 타임스탬프(Timestamp) 하나만 해도 수십 가지의 서로 다른 형식으로 나타납니다.
로그는 각 기술 스택의 고유한 지문을 반영합니다:
- syslog — 여전히 널리 사용되지만, 타임스탬프 형식에 독특한 특징이 있음
- Apache — Common Log Format을 사용함
- nginx — 자체적인 커스텀 변형을 사용함
- Java 앱 — logback, log4j 또는 slf4j를 사용함
- AWS 서비스 — 종종 구조화된 JSON 또는 텍스트와 JSON의 혼합 형태를 출력함
단일 표준이 없는 상황에서, Bronto는 사용자가 일반적으로 직면하는 수고와 복잡성을 줄이기 위해 AI를 사용하여 파서를 자동으로 생성하는 혁신적인 방식으로 이 문제를 해결하고자 했습니다.
자동 로그 파싱
로그를 실시간으로 파싱하는 것은 성능이 매우 중요한 작업입니다.
초당 수백만 개의 이벤트를 수집할 때는 매 밀리초(millisecond)가 중요합니다. 정규 표현식 (Regex) 기반의 파싱은 복잡하고 유지보수가 어려울 수 있으며, Grok이나 Dissect와 같은 도구에 대한 전문 지식을 요구합니다. 또한, 무분별하게 적용될 경우 규모가 커짐에 따라 병목 현상 (bottleneck)이 될 수 있습니다. Bronto에서는 오프라인 탐지 (offline detection)와 온라인 파싱 (online parsing)을 분리하는 다층적 접근 방식을 사용합니다. 온라인 파싱은 수집 파이프라인 (ingestion pipeline)의 일부로서 실시간으로 수행되며, 오프라인 탐지는 짧은 지연 시간과 함께 파이프라인 외부에서 발생합니다. 이러한 하이브리드 접근 방식은 유연성을 희생하지 않으면서도 속도를 보장하며, 사용자의 수고 (toil)를 줄여줍니다.
Layer 1: 큐레이션된 Java 파서 (Curated Java Parsers)
우리는 여러 고객사에서 대량으로 발생하는 가장 일반적인 형식에 최적화된 고성능 Java 기반 파서 라이브러리를 유지 관리합니다. 이들은 속도에 특화되어 제작되었으며, 예상되는 형식과 일치하지 않는 로그를 만날 경우 즉시 실패 (fail fast)하도록 설계되었습니다. Java 파서를 적용한 후에는 주요 필드를 정규화 (normalize)하기 위해 다음과 같은 추가적인 경량 프로세서 (lightweight processors)를 실행합니다:
- 타임스탬프 파서 (Timestamp parser) — 다양한 타임스탬프 형식을 자동 감지하고 정규화합니다.
- 로그 레벨 파서 (Log level parser) — 다양한 심각도 (severity) 키워드를 5개의 표준 레벨로 매핑합니다.
- KVP 파서 (KVP parser) — 메시지나 본문에서 키=값 (key=value) 쌍을 추출하며, 일부 이벤트에만 존재하는 경우에도 작동합니다.
Layer 2: Dissect 및 Grok 폴백 (Dissect and Grok Fallback)
덜 일반적이지만 여전히 중요한 형식의 경우, Dissect 또는 Grok으로 폴백 (fallback)합니다:
- Dissect — 빠르며, 구분자 (delimiter) 기반의 구조화된 로그에 매우 적합합니다.
- Grok — 더 유연하고 정규 표현식 (regex) 기반의 파싱을 지원하지만, 성능 비용 (performance cost)이 발생합니다.
Bronto는 Dissect와 Grok 패턴 모두에 대해 방대한 데이터베이스를 유지하고 있습니다. 런타임 비용 (runtime cost) 때문에, 모든 패턴을 모든 이벤트에 온라인으로 적용하려고 시도하지는 않습니다.
대신 다음과 같은 방식을 사용합니다: 오프라인에서 로그 이벤트를 샘플링합니다. 이를 전체 패턴 라이브러리와 대조합니다. 매칭되는 패턴이 발견되면, 해당 데이터셋에 파서 힌트 (parser hint)를 자동으로 할당합니다. 해당 데이터셋의 향후 이벤트들은 매칭된 패턴을 사용하여 파싱됩니다. 데이터셋별 파싱 품질에 대한 메트릭 (metrics)을 수집하고 주기적으로 힌트를 재검증합니다.
레이어 3: AI 생성 파싱 (AI-Generated Parsing) 알 수 없는 형식이나 독자적인 형식을 만났을 때, 다른 도구들은 사용자가 UI를 통해 정규 표현식 (regex)을 직접 수동으로 작성하도록 요구할 수 있습니다. Bronto에서는 AI가 이 작업을 수행하도록 합니다. 이 기능이 활성화되면, 데이터셋의 샘플을 내부 AI 엔진으로 전송하여 로그 구조를 분석하고 맞춤형 디섹트 패턴 (dissect pattern)을 생성합니다. 생성된 패턴을 더 넓은 범위의 샘플로 테스트합니다. 만약 높은 비율의 이벤트와 일치하면, 사용자에게 패턴과 샘플 결과를 제시합니다. 사용자는 원하는 경우 필드 이름을 수정할 수 있으며, 승인되면 파서가 저장되어 해당 데이터셋의 모든 향후 이벤트에 자동으로 적용됩니다.
실제 사례 여러분의 애플리케이션 로그가 다음과 같다고 가정해 보겠습니다:
[IMG:1]
수백 줄을 분석한 후, AI는 다음과 같은 디섹트 패턴을 생성합니다:
[IMG:2]
파싱된 결과는 다음과 같습니다:
app_name timestamp log_level message
APP01 2024-07-03 12:50:59 WARN Invalid sessionId: sessionId=expired
APP01 2024-07-03 12:49:41 INFO Authentication token issued
APP01 2024-07-03 12:48:27 INFO User logout: userId=14141
APP01 2024-07-03 12:47:10 INFO New login attempt
APP01 2024-07-03 12:45:37 INFO Form submitted: formId=contact-us
그 후 KVP 파서가 message 값에서 sessionId, userId, formId와 같은 필드를 추가로 추출합니다.
내부 작동 원리: AWS Bedrock 우리는 LLM (Claude 포함)에 접근하기 위한 관리형 서비스로 AWS Bedrock을 사용합니다. 우리의 인프라는 각 애플리케이션에 가장 적합한 모델을 선택하고 구조화된 프롬프트 (structured prompts)를 전송합니다. 예를 들어, LLM에 어떤 패턴을 피해야 하는지, 타임스탬프 (timestamps)와 같은 키를 어떻게 처리해야 하는지 지시합니다. 사용자는 모델이나 프롬프트에 대해 걱정할 필요가 없으며, 그저 애플리케이션을 사용하기만 하면 됩니다.
Bedrock은 또한 다음과 같은 중요한 SaaS급 보장 사항을 제공합니다:
- 유해한 콘텐츠를 탐지하고 필터링하기 위한 내장된 안전 장치 (Safeguards)
- 모델 학습을 위해 당사의 데이터를 저장하거나 사용하지 않음
- 모든 데이터는 AWS 네트워크 내에 유지됨
- Lambda 및 S3와 원활하게 작동 — 플랫폼 재설계 (Rearchitecting)가 필요 없음
향후 전망
Bronto에서 우리는 파싱 (Parsing)이 빠르고, 정확하며, 수동 작업이 필요 없어야 한다고 믿습니다. 현재 우리는 AI를 사용하여 Dissect 패턴을 생성하고 있습니다. 곧 Grok 패턴도 생성할 예정이며, 이를 통해 더욱 복잡하고 비정형화된 형식에도 AI를 적용할 것입니다. OTel (OpenTelemetry)이 JSON 기반의 구조화된 로깅 (Structured Logging)을 지속적으로 추진함에 따라, 시간이 흐를수록 로그 파싱이 덜 고통스러운 문제가 되기를 희망합니다. 하지만 그때까지 자동화되고 적응형인 파싱은 단순한 편의를 넘어 필수 요소입니다.
요약
Bronto는 엄선된 Java 파서 (Parsers), 유연한 Dissect/Grok 매칭, 그리고 AI 기반 패턴 생성을 결합하여 구조화되었든 그렇지 않든 모든 로그 형식을 파싱할 수 있는 통합 파이프라인을 제공합니다. 만약 귀하의 로그가 이상하거나 지저분하더라도 — 저희가 해결해 드립니다.
Bronto의 AI 기능 살펴보기
AI 자동 생성 콘텐츠
본 콘텐츠는 Dev.to AI tag의 원문을 AI가 자동으로 요약·번역·분석한 것입니다. 원 저작권은 원저작자에게 있으며, 정확한 내용은 반드시 원문을 확인해 주세요.
원문 바로가기