Notice
Recent Posts
Recent Comments
Link
«   2025/09   »
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
Tags
more
Archives
Today
Total
관리 메뉴

코딩 이래요래

Spring Boot + Prometheus + Grafana 대시보드 만들기 본문

JAVA

Spring Boot + Prometheus + Grafana 대시보드 만들기

강범호 2025. 6. 17. 14:53

1. 프로메테우스(Prometheus)?

  • 시간의 흐름에 따라 변동 되는 데이터를 메트릭(Metric)이라고 한다.
  • SpringBoot는 Actuator가 metric 수집을 담당하고 있다.
  • 문제는, 메트릭은 시간이 흐를수록 대량의 데이터가 쌓이는데 Application의 메모리만으로 metric의 데이터를 모두 감당할 수 없다.
  • 이때, 시계열 데이터베이스(Time Series Database)인 프로메테우스를 사용하여 데이터를 저장한다.

SpringBoot에서는 Actuator 엔드포인트의 접근 권한을 설정할 수 있어, 일반 사용자와 Prometheus와 같은 외부 시스템의 접근 경로를 분리할 수 있다.

예를 들어 /actuator/health, /actuator/info는 공개하고, /actuator/prometheus는 Prometheus만 접근할 수 있도록 제한할 수 있다.

Prometheus는 이 엔드포인트를 통해 Actuator가 수집한 메트릭 정보를 일정 주기로 pull 방식으로 가져간다.

 

이제 프로메테우스를 연동시켜 보자

1. 프로메테우스 설치

 

Download | Prometheus

Downloads for the latest releases of the Prometheus monitoring system and its major ecosystem components.

prometheus.io

  • 해당 링크로 접속 후 다운로드

  • 프로메테우스를 설치하고 터미널을 열어 설치한 폴더로 이동 후 프로메테우스 서버를 실행한다.
    • 명령어 ./prometheus

2. 서버 실행 확인

  • localhost:9090으로 접속 후 해당 화면이 열리면 프로메테우스 서버가 실행된 것.

3. SpringBoot 설정

build.gradle

  • actuator와 prometheus 의존성을 추가한다.

application.yml

  • actuator는 민감한 정보를 포함하고 있기 때문에 개발 환경에서만 *로 설정해야 한다.

대시보드에 필요한 Metric 설정

@Component
public class LibraryMetrics {

    private static final Logger log = LoggerFactory.getLogger(LibraryMetrics.class);

    private final MeterRegistry meterRegistry;
    private final BookRepository bookRepository;
    private final MemberRepository memberRepository;
    private final LoanRepository loanRepository;
    private final ReviewRepository reviewRepository;

    // 카운터 메트릭
    private Counter bookCreatedCounter;
    private Counter loanCreatedCounter;
    private Counter reviewCreatedCounter;
    private Counter errorCounter;

    // 타이머 메트릭
    private Timer bookSearchTimer;
    private Timer loanProcessTimer;

    // 게이지용 원자적 변수
    private final AtomicLong totalBooksGauge = new AtomicLong(0);
    private final AtomicLong activeMembersGauge = new AtomicLong(0);
    private final AtomicLong activeLoanGauge = new AtomicLong(0);

    @Autowired
    public LibraryMetrics(MeterRegistry meterRegistry, BookRepository bookRepository, 
                         MemberRepository memberRepository, LoanRepository loanRepository,
                         ReviewRepository reviewRepository) {
        this.meterRegistry = meterRegistry;
        this.bookRepository = bookRepository;
        this.memberRepository = memberRepository;
        this.loanRepository = loanRepository;
        this.reviewRepository = reviewRepository;
    }

    @PostConstruct
    public void initMetrics() {

        log.info("[s4][LibraryMetrics] 도서관 시스템 커스텀 메트릭 초기화 시작");

        // 카운터 메트릭 초기화
        bookCreatedCounter = Counter.builder("library.books.created")
                .description("생성된 도서 수")
                .tag("system", "library")
                .register(meterRegistry);

        loanCreatedCounter = Counter.builder("library.loans.created")
                .description("생성된 대출 수")
                .tag("system", "library")
                .register(meterRegistry);

        reviewCreatedCounter = Counter.builder("library.reviews.created")
                .description("생성된 리뷰 수")
                .tag("system", "library")
                .register(meterRegistry);

        errorCounter = Counter.builder("library.errors.total")
                .description("발생한 오류 수")
                .tag("system", "library")
                .register(meterRegistry);

        // 타이머 메트릭 초기화
        bookSearchTimer = Timer.builder("library.books.search.duration")
                .description("도서 검색 소요 시간")
                .tag("system", "library")
                .register(meterRegistry);

        loanProcessTimer = Timer.builder("library.loans.process.duration")
                .description("대출 처리 소요 시간")
                .tag("system", "library")
                .register(meterRegistry);

        // 게이지 메트릭 초기화
        Gauge.builder("library.books.total", this, LibraryMetrics::getTotalBooks)
                .description("전체 도서 수")
                .tag("system", "library")
                .register(meterRegistry);

        Gauge.builder("library.members.active", this, LibraryMetrics::getActiveMembers)
                .description("활성 회원 수")
                .tag("system", "library")
                .register(meterRegistry);

        Gauge.builder("library.loans.active", this, LibraryMetrics::getActiveLoans)
                .description("활성 대출 수")
                .tag("system", "library")
                .register(meterRegistry);

        Gauge.builder("library.reviews.total", this, LibraryMetrics::getTotalReviews)
                .description("전체 리뷰 수")
                .tag("system", "library")
                .register(meterRegistry);

        // 초기 데이터 로드
        updateGaugeMetrics();

        log.info("[s4][LibraryMetrics] 도서관 시스템 커스텀 메트릭 초기화 완료");
    }
    // 도서 생성 카운트 증가 메서드..
    
    // 도서 대출 생성 카운드 증가 메서드..
    
    ...
}

 

4. 프로메테우스 데이터 포맷의 메트릭 데이터 확인

  • http://localhost:8080/actuator/prometheus로 접속하면 직접 추가한 Metric 데이터를 확인할 수 있다.
  • SpringBoot는 micrometer 라이브러리를 통해 수집된 메트릭을 Actuator에 노출하고, 프로메테우스는 /actuator/prometheus 엔드포인트를 통해 해당 메트릭을 pull 방식으로 주기적으로 수집한다.
  • 이때 Micrometer가 Prometheus에서 이해할 수 있는 형식으로 데이터를 출력 해주며 이를 위해 아래 의존성을 추가한 것이다.  
    • implementation 'io.micrometer:micrometer-registry-prometheus'

5. 프로메테우스로 데이터 가져오기

  • prometheus.yaml 파일을 열어 아래 설정을 추가한다.
  - job_name: "spring-actuator"
    metrics_path: '/actuator/prometheus'
    scrape_interval: 1s
    static_configs:
      - targets: ['localhost:8080']
  • scrape_interval을 1초로 설정하여, metrics_path의 경로로 메트릭 데이터를 1초마다 접근하여 데이터를 수집한다.

6. 프로메테우스 연동 확인

  • Status -> Target health 이동

  • 아까 등록한 spring-actuator가 State UP 상태로 보인다면 연동이 완료된 것을 확인할 수 있다.

7. Metric 데이터 시각화 하기

 

그라파나(Grafana)?

  • 프로메테우스로 수집한 metric 데이터를 시각화하는데 특화된 툴(tool)이다.
 

Download Grafana | Grafana Labs

Overview of how to download and install different versions of Grafana on different operating systems.

grafana.com

  • 위 링크를 통해 Grafana를 설치한다.
  • 설치 후 bin 폴더로 이동하여 Grafana 서버를 실행한다.
    • ./grafana-server

  • localhost:3000 접속하면 로그인 창이 뜰텐데 admin/admin 으로 로그인하면 해당 화면이 열리면 서버가 정상적으로 동작중이다.

  • Add new connections를 클릭하여 프로메테우스와 그라파나를 연동해야한다.

  • 검색을 통해 프로메테우스를 클릭하여 새로운 커넥션을 만든다.

    • URL에 프로메테우스 로컬서버 주소인 http://localhost:9090을 입력하고 저장한다.

    • 대시보드 탭을 클릭하여 새로운 대시보드를 만들어 준다.

  • 아래 Select metric에 프로메테우스에서 가져온 데이터중 원하는 데이터를 입력후 Run queries를 클릭하면 panel에 시각화된 데이터가 표시된다.


대시보드 테스트

 

'JAVA' 카테고리의 다른 글

Spring Data JPA  (1) 2025.05.30
Spring Framework 핵심 개념  (0) 2025.04.29
자료구조 - Tree, Binary Tree  (0) 2025.04.16
자료구조 - Stack, Queue, Deque  (0) 2025.04.13
자료구조 - List  (0) 2025.04.13