스프링부트

logback을 이용한 spring boot 애플리케이션 syslog 전송하기

알쓸개잡 2024. 6. 7.

로그 관리는 애플리케이션 개발과 운영에서 매우 중요한 부분을 차지한다. 특히, 분산 시스템 환경에서는 중앙 집중식 로그 관리가 필요하다. syslog는 이러한 로그 관리를 위한 표준 프로토콜로, 다양한 시스템과 애플리케이션에서 널리 사용된다.

Spring boot 애플리케이션에서 syslog를 사용하면, 애플리케이션 로그를 중앙 로그 서버로 전송하여 쉽게 모니터링하고 분석할 수 있다. 이를 통해 시스템의 상태를 실시간으로 파악하고 문제 발생 시 신속하게 대응할 수 있다.

이번 포스팅에서는 spring boot와 logback을 사용하여 syslog로 로그를 전송하는 방법에 대해서 정리하고자 한다.

 

우선 spring logback 설정에 대해서는 아래 포스팅을 참고하면 도움이 될 것 같다.

2023.10.12 - [스프링부트] - spring boot logging

2023.10.14 - [스프링부트] - spring boot 로그백 (logback) 설정 방법

 

로컬 환경에 rsyslog 환경  구축

docker container로 syslog를 수신하는 환경을 구축할 수 있다.

docker-compose.yml

version: '3.8'

services:
  rsyslog:
    image: ubuntu:latest
    container_name: rsyslog_container
    ports:
      - "5140:514/tcp"
      - "15140:514/udp"
    command: >
      /bin/bash -c "
      apt-get update && 
      apt-get install -y rsyslog vim && 
      sed -i 's/module(load=\"imklog\"/#module(load=\"imklog\"/' /etc/rsyslog.conf &&
      sed -i 's/#module(load=\"imudp\")/module(load=\"imudp\")/' /etc/rsyslog.conf &&
      sed -i 's/#input(type=\"imudp\"/input(type=\"imudp\"/' /etc/rsyslog.conf &&
      sed -i 's/#module(load=\"imtcp\")/module(load=\"imtcp\")/' /etc/rsyslog.conf &&
      sed -i 's/#input(type=\"imtcp\"/input(type=\"imtcp\"/' /etc/rsyslog.conf &&
      echo 'local0.* /var/log/local0.log' > /etc/rsyslog.d/local0.conf &&
      touch /var/log/local0.log &&
      rsyslogd -n"
    volumes:
      - ./logs:/var/log

우분투 이미지에 rsyslog를 설정하는 docker compose 정의 파일이다.

  • 우분투에 rsyslog, vim 패키지를 설치한다.
  • local0 facilities에 대해서 /var/log/local0.log 파일에 분리하여 기록하도록 설정하고 tcp, udp 포트를 open 하도록 한다.
  • rsyslog_container docker 컨테이너의 /var/log 와 docker-compose.yml 이 위치한 경로의 logs 경로를 mount 한다.
  • 로컬호스트 5140 포트와 컨테이너의 514 tcp 포트를 연결한다.
  • 로컬호스트 15140 포트와 컨테이너의 514 udp 포트를 연결한다.

docker-compose.yml 파일이 위치한 경로에서 아래 명령을 실행하여 컨테이너를 구동시킨다.

docker compose up -d

 

logback-spring.xml 정의

logback을 통해서 syslog를 전송하기 위해서는 사용자 정의 logback을 설정해야 한다.

<?xml version="1.0" encoding="UTF-8" ?>
<configuration>
    <appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender">
        <!-- By default, encoders are assigned the type ch.qos.logback.classic.encoder.PatternLayoutEncoder -->
        <encoder>
            <charset>UTF-8</charset>
            <pattern>%date{ISO8601} %highlight([%-5level]) [%thread] [%logger{36}.%M\(%L\)] %msg%n</pattern>
        </encoder>
    </appender>
    <appender name="SYSLOG-UDP" class="ch.qos.logback.classic.net.SyslogAppender">
        <syslogHost>127.0.0.1</syslogHost>
        <port>15140</port>
        <facility>LOCAL0</facility>
        <suffixPattern>%msg%n</suffixPattern>
    </appender>

    <logger name="org.example.syslog.example.service.SyslogService" level="DEBUG" additivity="false">
        <appender-ref ref="SYSLOG-UDP" />
    </logger>
    <root level="INFO">
        <appender-ref ref="CONSOLE" />
    </root>
</configuration>
  • SyslogService logger에 대해서 syslog를 전송한다.
  • 아쉽게도 logback에서 제공하는 SyslogAppender는 UDP 프로토콜만 지원한다.
  • additivity=false를 지정하여 SyslogService logger는 root 로거 상속을 받지 않는다. 즉 콘솔 로그를 기록하지 않는다.
  • 그 외의 로그에 대해서는 CONSOLE appender에 정의된 데로 콘솔에 로그를 기록한다.

 

logback 관련 디펜던시

org.springframework.boot:spring-boot-starter 디펜던시에 logback이 포함되어 있어서 logback 관련 디펜던시를 추가할 필요는 없지만 다음과 같이 직접 추가해 줘도 무방하다.

dependencies {
    implementation 'org.springframework.boot:spring-boot-starter'
    implementation 'ch.qos.logback:logback-classic'
    implementation 'ch.qos.logback:logback-core'
    compileOnly 'org.projectlombok:lombok'
    annotationProcessor 'org.projectlombok:lombok'
    testImplementation 'org.springframework.boot:spring-boot-starter-test'
    testRuntimeOnly 'org.junit.platform:junit-platform-launcher'
    testCompileOnly 'org.projectlombok:lombok'
    testAnnotationProcessor 'org.projectlombok:lombok'
}
  • logback 이외에도 편의상 lombok 관련 디펜던시를 추가하였다.
  • logback 관련 디펜던시는 logback-classic, logback-core이다.

 

코드

org.example.syslog.example.service 패키지에 SyslogService 클래스를 정의한다.

@Service
@Slf4j
public class SyslogService {

    public void syslog(String message) {
        log.info( "send syslog message: {}", message );
    }
}

 

SyslogService를 이용하여 로그를 기록해 보자.

@SpringBootApplication
@RequiredArgsConstructor
public class SyslogExampleApplication implements CommandLineRunner {
    private final SyslogService syslogService;

    public static void main( String[] args ) {
        SpringApplication.run( SyslogExampleApplication.class, args );
    }

    @Override
    public void run( String... args ) {
        syslogService.syslog( "syslog message 1" );
        syslogService.syslog( "syslog message 2" );
        syslogService.syslog( "syslog message 3" );
        syslogService.syslog( "syslog message 4" );
    }
}

 

docker-compose.yml 파일이 있는 경로에서 logs/local0.log 파일을 확인해 보면 다음과 같이 로그가 기록되는 것을 확인할 수 있다.

참고로 logs/local0.log 파일은 rsyslog_container docker 컨테이너의 /var/log/local0.log 파일과 같다.

2024-06-07T15:43:03+00:00 MacBookPro.local send syslog message: syslog message 1
2024-06-07T15:43:03+00:00 MacBookPro.local send syslog message: syslog message 2
2024-06-07T15:43:03+00:00 MacBookPro.local send syslog message: syslog message 3
2024-06-07T15:43:03+00:00 MacBookPro.local send syslog message: syslog message 4

 

끝.

댓글

💲 추천 글