1. 개요

이 문서에서는 Spring Boot 애플리케이션에서 JSON 형태의 로그를 출력하고, OpenTelemetry Collector를 통해 이를 수집하는 설정 방법을 다룬다.

2. 환경

  • Java: 1.8
  • Spring Boot: 2.5.1
  • OpenTelemetry Collector: contrib 버전

3. 로그 형식을 JSON으로 변경

3-1. 기존 방식의 문제점

기존에는 Logback을 활용해서 문자열(String) 형태의 로그를 출력했다. 이러한 방식은 다음과 같은 문제점이 있었다.

  • 파싱 정확도 문제: 필드들을 분리하려면 정규식을 이용해야 하는데, 이는 로그 포맷이 조금만 변경되어도 파싱에 실패할 수 있다.
  • 리소스 낭비: 복잡한 정규식 패턴 매칭은 CPU와 메모리를 과도하게 소모한다.
  • 유지보수의 어려움: 로그 포맷이 변경될 때마다 파싱 규칙도 함께 수정해야 한다.

이러한 이유로 로그 형식을 JSON으로 변경하기로 결정했다.

3-2. logstash-logback-encoder 의존성 추가

JSON 형태의 로그를 출력하기 위해서는 logstash-logback-encoder 라이브러리가 필요하다. 이 라이브러리는 자바 버전, Jackson 버전, logback-classic 등의 버전 호환성을 고려해야 한다.

INFO

Spring Boot Starter에 기본적으로 포함된 logback-classic과 버전 충돌이 발생할 수 있어서 exclude 처리를 해줘야 할 수 있다.

Java 1.8 환경에 맞춰 logstash-logback-encoder 7.0 버전을 사용했다.

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter</artifactId>
    <version>2.5.1</version>
    <exclusions>
        <exclusion>
            <groupId>ch.qos.logback</groupId>
            <artifactId>logback-classic</artifactId>
        </exclusion>
    </exclusions>
</dependency>
 
<dependency>
    <groupId>ch.qos.logback</groupId>
    <artifactId>logback-classic</artifactId>
    <version>1.2.11</version>
</dependency>
<dependency>
    <groupId>net.logstash.logback</groupId>
    <artifactId>logstash-logback-encoder</artifactId>
    <version>7.0</version>
</dependency>

Spring Boot Starter에 포함된 기본 logback-classic 을 제외하고, 호환되는 버전으로 명시적으로 추가하는 방식이다.

3-3. Logback 설정 변경

의존성 추가 후에는 logback-spring.xml 파일에서 JSON 인코더를 사용하도록 설정한다.

<appender name="LOGGER" class="ch.qos.logback.core.ConsoleAppender">
    <encoder class="net.logstash.logback.encoder.LogstashEncoder"/>
</appender>

이 설정을 통해 애플리케이션 로그가 JSON 형태로 출력되며, 각 필드를 구조화된 데이터로 쉽게 파싱할 수 있다.

4. OpenTelemetry Collector 수집 설정

4-1. FileLog Receiver 선택 이유

로그를 수집하는 방식에는 여러 가지가 있으며, 단순성을 고려해서 OpenTelemetry Collector Contribfilelogreceiver를 선택했다.

4-2. FileLog Receiver 설정

receivers:
  filelog/test-app:
    include: 
    - "/var/log/pods/test-app-java-backend-1*/*/*.log"
    - "/var/log/pods/test-app-java-backend-2*/*/*.log"
    include_file_name: false
    include_file_path: true
    start_at: beginning # 또는 end
    operators:
    - type: container
      add_metadata_from_filepath: true
    - type: json_parser
      id: parse_json
      parse_from: body
      parse_to: attributes
    - type: move
      from: attributes.message
      to: body

각 설정 항목의 의미는 다음과 같다.

  • include: 수집할 로그 파일 경로 패턴을 지정한다.
  • include_file_path: 로그 레코드에 파일 경로 정보를 포함할지 여부다.
  • start_at: 컬렉터 시작 시 로그 파일의 어느 지점부터 읽을지 결정한다.
  • operators: 로그 데이터를 처리하는 파이프라인을 정의한다.

IMPORTANT

json_parser 오퍼레이터가 핵심인데, 이것이 JSON 형태의 로그를 파싱해서 구조화된 속성(attributes)으로 변환해준다.

5. 설정 검증 및 확인

OpenTelemetry Collector 파이프라인을 구성한 후에는 다음과 같이 로그 수집이 정상적으로 동작하는지 확인한다.

  1. 애플리케이션 로그 출력 확인: JSON 형태로 로그가 출력되는지 확인한다.
  2. 컬렉터 로그 확인: 컬렉터가 파일을 정상적으로 읽어들이는지 확인한다.
  3. 파싱 결과 확인: JSON 필드가 올바르게 파싱되어 속성으로 변환되는지 확인한다.

전체 OpenTelemetry Collector 설정 예시는 여기에서 확인할 수 있다.

6. 참고