티스토리 뷰

 

서버 배포와 함께 모니터링을 세팅하면서 다음과 같은 의문이 들었다.

Spring Actuator가 기본으로 제공하는 메트릭으로는 파악하기 어려운 부분을 모니터링할 수 없을까? 

 

특히나, 외부와 상호작용하거나 통신하는 부분을 모니터링하고 싶었다. 이러한 부분들에 대한 커스텀 메트릭을 만들기로 결정하였다.

 

다음과 같은 부분을 타겟으로 success, failure 횟수와 소요 시간을 메트릭화 하고자 한다.

  • OpenAPI
  • Internal API (core <-> alarm)
  • Redis Pub/Sub

 

모니터링을 위한 메트릭 추가를 횡단 관심사로 보았고, 각 메서드마다 이름을 주어 간편히 사용할 수 있도록 어노테이션과 AOP 기반으로 적용해보았다.

 

어노테이션, AOP 코드 예시

@Target({ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
public @interface OpenApiMonitored {

    String name() default "";
}
  • 위 어노테이션을 원하는 메서드에 적용하면 메트릭을 수집할 수 있게 구현했다.
  • String name() 으로 지표에 이름을 동적으로 넣어주도록 하였다.
@Aspect
@Component
public class OpenApiMetricAdvice {

    private final MeterRegistry meterRegistry;
    private final ConcurrentHashMap<String, Counter> successCounters = new ConcurrentHashMap<>();
    private final ConcurrentHashMap<String, Counter> failureCounters = new ConcurrentHashMap<>();
    private final ConcurrentHashMap<String, Timer> timers = new ConcurrentHashMap<>();

    public OpenApiMetricAdvice(MeterRegistry meterRegistry) {
        this.meterRegistry = meterRegistry;
    }

    @Around("@annotation(org.example.metric.OpenApiMonitored)")
    public Object monitorExecution(ProceedingJoinPoint joinPoint) throws Throwable {
        Method method = ((MethodSignature) joinPoint.getSignature()).getMethod();
        OpenApiMonitored annotation = method.getAnnotation(OpenApiMonitored.class);
        String name = annotation.name();

        Counter successCounter = successCounters.computeIfAbsent(
            name, key -> meterRegistry.counter("api.open.success." + name, "method", key)
        );

        Counter failureCounter = failureCounters.computeIfAbsent(
            name, key -> meterRegistry.counter("api.open.failure." + name, "method", key)
        );

        Timer timer = timers.computeIfAbsent(
            name,
            key -> Timer.builder("api.open.time." + name).tags("method", key).register(meterRegistry)
        );

        return MetricUtils.executeWithMetrics(timer, joinPoint, successCounter, failureCounter);
    }
}
  • 공통적으로 try - catch 문이 많아졌기에 MetricUtils 라는 유틸 클래스를 만들어 이를 처리하도록 코드를 개선했다.

 

  • 그 결과, 원하는 부분마다의 메트릭이 수집됨을 확인했다.
    • 위 코드의 api.open.success + name 부분을 아래와 같이 확인할 수 있었다.

 

  • 이제 Pub/Sub 의 유실이나 OpenAPI의 응답 속도 등을 바로 확인할 수 있게 되었다.
  • 성능 개선 작업 시 API Latency, 운영 시 API Status Code 분포 등을 확인하며 활용 중이다. 또한 서비스가 운영 중이므로 하드웨어 자원의 사용률, 스레드 block 여부 등등을 더 살펴보려고 한다.

 

PromQL을 통한 커스텀 메트릭 시각화

  • 여러 레퍼런스를 참고하며 원하는 지표에 대한 PromQL을 작성해봤다.

 

커스텀 메트릭 시각화 예시

추가 알람 설정 작업

 

공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
TAG
more
«   2025/02   »
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
글 보관함