카테고리 없음

모니터링 도입 트러블슈팅

kjw81024 2026. 5. 27. 18:18

옛날에 작성했던 모니터링은 

application 을 따로 Docker 로 띄우거나 Local 환경에서 실행하는 형식을 사용했기 때문에 yml 설정값들을 다시 작성해두기 

 

파일 변경 사항 

root/
├── docker-compose.yml              # ← Prometheus, Grafana 서비스 추가
├── monitoring/
│   ├── prometheus.yml              # ← Prometheus 수집 대상 설정
│   └── grafana/
│       ├── provisioning/
│       │   ├── datasources/
│       │   │   └── datasource.yml  # ← Grafana 데이터소스 자동 등록
│       │   └── dashboards/
│       │       └── dashboard.yml   # ← 대시보드 로드 설정
│       └── dashboards/
│          ├── for-pets-application.json # ← 실제 대시보드 JSON (export한 것)
│          └── for-pets-business.json

dashboards 의 .json 파일에 dash board 에 만들어둔 panel , 설정 정보들이 저장되기 때문에 꼭 꼭 만들어두기 ...

이번엔 대시보드를 business 랑 application 를 분리했기 때문에 dashboards/ 폴더에 2개가 들어간다.

어차피 dashboard.yml 이 dashboards/ 폴더 전체를 보고 만들기 때문에 상관 없음 

 

더보기

docker-compose.yml

변경사항: network 랑 연결해줄 필요가 없어짐 : kafka 에서 이벤트를 발행해서 metrics 를 계산하고 있지 않기 때문

extra_hosts 도 application 파일이 for pets project 내부에 다 있기 때문에 삭제 

# --------------------------
# Prometheus
# --------------------------
prometheus:
image: prom/prometheus
container_name: prometheus
ports:
  - "9090:9090"
volumes:
  - ./monitoring/prometheus.yml:/etc/prometheus/prometheus.yml

# --------------------------
# Grafana
# --------------------------
grafana:
image: grafana/grafana
container_name: grafana
ports:
  - "3000:3000"
environment:
  - GF_SECURITY_ADMIN_PASSWORD=admin
volumes:
  - grafana_data:/var/lib/grafana
  - ./monitoring/grafana/provisioning:/etc/grafana/provisioning
  - ./monitoring/grafana/dashboards:/var/lib/grafana/dashboards
depends_on:
  - prometheus
  
  
volumes:
mysql-data:
redis-data:
grafana_data:

 

monitoring/prometheus.yml

변경 사항: spring boot 를 docker 밖에서 찾아줄 필요 없기 때문에 targets 를 'host.docker.internal:8080' 에서 변경 

# monitoring/prometheus.yml
global:
  scrape_interval: 15s

scrape_configs:
  - job_name: 'coffee-service'
    metrics_path: '/actuator/prometheus'
    static_configs:
      - targets: ['for-pets-app:8080']
        # Spring Boot 앱을 도커 내부에서 찾음

최종 프로젝트 구현 부분 

 

이번엔 사실 초기세팅만 하기로 한거라서 

저번에 구현했던 부분을 그대로 구현했다.

title description PromQL
endpoint 별 RPS 느린 API 식별 및 트래픽 패턴 파악 rate(http_server_requests_seconds_count[1m])
endpoint 별 평균 응답 시간  병목 감지 rate(http_server_requests_seconds_sum[1m])
/ rate(http_server_requests_seconds_count[1m])
JVM 힙 메모리 메모리 누수 감지 jvm_memory_used_bytes{area="heap"}
HikariCP 커넥션 커넥션 고갈 및 Deadlock 감지  hikaricp_connections_active
 hikaricp_connections_idle
 hikaricp_connections_pending

 

저번에는 method 실행에 걸리는 시간을 측정할 때 MeterRegistry 를 사용했었다 

@Service
@RequiredArgsConstructor
public class PaymentService {

    private final MeterRegistry meterRegistry;

    public void confirmPayment(...) {
        Timer.Sample sample = Timer.start(meterRegistry);
        try {
            // 실제 로직
        } finally {
            sample.stop(Timer.builder("payment.confirm.duration")
                .tag("method", "confirm")
                .register(meterRegistry));
        }
    }
}

요런느낌 -> lock 걸리는 구간 정확하게 시작/끝 지점 지정 가능 근데 복잡함 

 

@Timed(value = "payment.confirm.duration", description = "결제 확인 소요시간")
public void confirmPayment() {
}

Timed 어노테이션 달기 -> 편함 근데 Spring Bean method 에만 적용 

상관없긴 하지만 같은 클래스 내부 호출이나 트랜잭션 프록시 안쪽은 못 잡는 경우가 생긴다고 해서 패스

 

@Slf4j
@Aspect
@Component
@RequiredArgsConstructor
public class ExecutionTimeAspect {

    private final MeterRegistry meterRegistry;

    /*
     * @TrackExecutionTime이 붙은 메서드의 실행 시간 측정
     * 성공/실패 여부도 tag로 함께 기록 -> 실패 케이스만 따로 분석 가능
     */
    @Around("@annotation(trackExecutionTime)")
    public Object measure(ProceedingJoinPoint joinPoint, TrackExecutionTime trackExecutionTime) throws Throwable {
        Timer.Sample sample = Timer.start(meterRegistry);
        String metricName = trackExecutionTime.value();
        String methodName = joinPoint.getSignature().getName();
        String status = "success";

        try {
            return joinPoint.proceed();
        } catch (Throwable e) {
            status = "failure";
            throw e;
        } finally {
            sample.stop(Timer.builder(metricName + ".duration")
                    .description(metricName + " 메서드 실행 시간")
                    .tag("method", methodName)
                    .tag("status", status)
                    .register(meterRegistry));
        }
    }
}

TrackExecutionTime 어노테이션을 직접 만들고 

@TrackExecutionTime("payment.confirm")
@Transactional
public ConfirmPaymentResponse confirm(Long memberId, ConfirmPaymentRequest request) {
}

위에 붙여서 사용하면 된다 


그라파나 접속

 

그라파나... 들어가보기 (팀원 공유용)

이 화면에서 3000:3000 되어있는... 저거 클릭 

이런 화면이 뜹니다!

email, username: admin

password: admin 으로 들어가면

password 바꾸라는데 그냥 skip

 

Home 의 Data sources 에서 Prometheus 다운받아서 9090 포트 연결하고 test 해줘요 

저는 이미 연결했었어서 default 로 설정되어있습니다

 

(사실 지금 설정을 해둬서 docker compose 로 실행시키면 제가 만든 dashboard 세팅이 뜨기때문에 거기다 대고 postman 요청같은거 보내보면 panel 들이 자동으로 업데이트 되어요 하하)

 

Dashboard 를 보면

이미 For pets 가 만들어져있습니다 

provisioning/dashboards/dashboard.yml 파일에 folder << 라고 적혀있는곳의 이름으로 뜸

눌러서 create dashboard 를 눌러서 

panel 을 추가하면 그 때 부터 추가가 되고, 이후 dashboard 이름을 수정해주고 .... 저장하는게 나와요 

add panel 파트에서는

프로메테우스랑 연결하고 PromQL query 랑 필요하다면 options 를 수정해주면 됨

 

변수는 {{ }} 안에 넣어서 작성해주면 됨

여러개 query를 넣어줄 수도 있다 

 

확인하고 싶은 쿼리 이름 + PromQL 과 이걸 모니터링 해야하는 이유, Options, 추천하는 visualization 을 알려줘 

라고 gpt 에게 요청하면 친절하게 알려주니 사용해보기 ㅎㅎ.

친절하시네요...


트러블슈팅

 

문제

다 만들었는데... 데이터가 안 뜬다 

 

1. target 확인 

http://localhost:9090/targets

down 으로 뜬다 

http://localhost:8080/actuator/prometheus

왜지? 싶어서 actuator 확인 

{
  "success": false,
  "data": null,
  "error": {
    "timestamp": "2026-05-27T14:32:27.495331196",
    "status": 404,
    "error": "NOT_FOUND",
    "code": "NOT_FOUND",
    "message": "요청한 리소스를 찾을 수 없습니다.",
    "path": "/actuator/prometheus"
  }
}

아예 프로메테우스를 못찾고 있다

 

분명 build.gradle 과 application.yml 설정에서 잘 되어있다

management:
  endpoints:
    web:
      exposure:
        include: health, info, metrics, prometheus
implementation 'io.micrometer:micrometer-registry-prometheus'
implementation 'org.springframework.boot:spring-boot-starter-actuator'

... 

혹시나 해서 

actuator/health 를 체크해봤는데 health 는 되는걸로 보아

이후에 추가한 prometheus 가 docker 에 반영이 안 됨

 

해결방법

docker rmi for-pets-project-app   # 기존 이미지 삭제
docker-compose build --no-cache app   # 캐시 없이 새로 빌드

도커를 volume 까지 삭제하고 

이미지와 캐시 없이 새로 build 를 진행했다.

정상출력됨!


저번에 volume 과 json 파일을 저장해두지 않아서 다 날라가는... 대참사가 있었는데 

http://localhost:3000/api/dashboards/uid/{uid}

이 명령어를 사용해서 뜨는 화면을 복사한다음 ai 에게 json 파일로 사용할 수 있도록 수정해달라고 하면 된다.

요런식으로 뜨는걸 복사해서 ai 한테 얘기하면 필요한 부분만 남겨서 바꿔준다 

뭐 이런식으로 친절히 알려주는 모습....

 

근데 이제 uid 를 어디서 확인할 수 잇는지 몰라서 좀 헤맸는데!! 

curl http://admin:admin@localhost:3000/api/search

uid 를 검색하면 뭔가 잔뜩 뜬다

 

이 때 7글자 짜리 고르면 된다... ㅎ 야매 방법

나는 이번에 json 파일이 두개니까 

요기있음 

 

이 uid 를 아까 위에서 말한 {uid} 자리에 넣어주면 잘 뜬다! ㅎㅎ