티스토리 뷰

Spring

[Spring] 메트릭 (metric)

hyuuny 2023. 4. 13. 18:09

서비스를 운영할 때는 애플리케이션의 CPU, 메모리, 커넥션 사용, 고객 요청수 같은 수 많은 지표들을 확인하는 것이 필요하다. 그래야 어디에 어떤 문제가 발생했는지 사전에 대응도 할 수 있고, 실제 문제가 발생해도 원인을 빠르게 파악해서 대처할 수 있다. 예를 들어서 메모리 사용량이 가득 찼다면 메모리 문제와 관련있는 곳을 빠르게 찾아서 대응할 수 있을 것이다.


세상엔 수 많은 모니터링 툴이 존재하며, 시스템의 다양한 정보를 이 모니터링 툴에 전달해서 사용하게 된다. 하지만 모니터링 툴이 작동하려면 시스템의 다양한 지표들을 각각의 모니터링 툴에 맞도록 만들어서 보내주어야 한다.


모니터링 툴에 지표 전달

예를 들어서 CPU, JVM, 커넥션 정보 등을 JMX 툴에 전달해야 한다면, 각각의 정보를 JMX 모니터링 툴이 정한 포멧에 맞추어 측정하고 전달해야 한다.


모니터링 툴 변경

만약 중간에 사용하던 모니터링 툴을 변경하면, 기존에 측정했던 코드를 모두 변경한 툴에 맞도록 다시 변경해야 한다. 개발자 입장에서는 단순히 툴 하나를 변경했을 뿐인데, 측정하는 코드까지 모두 변경해야 하는 문제가 발생한다.


마이크로미터 추상화

이런 문제를 해결하는 것이 바로 마이크로미터(Micrometer)라는 라이브러리이다.


마이크로미터 전체 그림

  • 마이크로미터는 애플리케이션 메트릭 파사드라고 불리는데, 애플리케이션의 메트릭(측정 지표)을 마이크로미터가 정한 표준 방법으로 모아서 제공해준다.
  • 즉, 마이크로미터가 추상화를 통해서 구현체를 쉽게 갈아끼울 수 있도록 해두었다.
  • 보통은 스프링이 이런 추상화를 직접 만들어서 제공하지만, 마이크로미터라는 이미 잘 만들어진 추상화가 있기 때문에 스프링은 이것을 활용한다. 스프링 부트 액츄에이터는 마이크로미터를 기본으로 내장해서 사용한다.
  • 개발자는 마이크로미터가 정한 표준 방법으로 메트릭(측정 지표)를 전달하면 된다. 그리고 사용하는 모니터링 툴에 맞는 구현체를 선택하면 된다. 이후에 모니터링 툴이 변경되어도 해당 구현체만 변경하면 된다. 애플리케이션 코드는 모니터링 툴이 변경되어도 그대로 유지할 수 있다.

마이크로미터 공식 메뉴얼


메트릭 확인하기

마이크로미터는 다양한 지표 수집 기능(CPU, JVM, 커넥션 사용 등)을 이미 만들어서 제공하고, 스프링 부트 액츄에이터는 마이크로미터가 제공하는 지표 수집을 @AutoConfiguration을 통해 자동으로 등록해준다. 즉, 스프링 부트 액츄에이터를 사용하면 수 많은 메트릭(지표)를 편리하게 사용할 수 있다.


metrics 엔드포인트(/actuator/metrics)를 사용하면 기본으로 제공되는 메트릭들을 확인할 수 있다.


localhost:8080/actuator/metrics 접속 결과

{
  "names": [
    "application.ready.time",
    "application.started.time",
    "disk.free",
    "disk.total",
    "executor.active",
    "executor.completed",
    "executor.pool.core",
    "executor.pool.max",
    "executor.pool.size",
    "executor.queue.remaining",
    "executor.queued",
    "hikaricp.connections",
    "hikaricp.connections.acquire",
    "hikaricp.connections.active",
    "hikaricp.connections.creation",
    "hikaricp.connections.idle",
    "hikaricp.connections.max",
    "hikaricp.connections.min",
    "hikaricp.connections.pending",
    "hikaricp.connections.timeout",
    "hikaricp.connections.usage",
    "http.server.requests.active",
    "jdbc.connections.active",
    "jdbc.connections.idle",
    "jdbc.connections.max",
    "jdbc.connections.min",
    "jvm.buffer.count",
    "jvm.buffer.memory.used",
    "jvm.buffer.total.capacity",
    "jvm.classes.loaded",
    "jvm.classes.unloaded",
    "jvm.compilation.time",
    "jvm.gc.live.data.size",
    "jvm.gc.max.data.size"
    ...
    ]
}  
  • 액추에이터가 마이크로미터를 통해서 등록한 기본 메트릭들을 확인할 수 있다.

metrics 엔드포인트는 패턴(actuator/metrics/{name}을 사용해서 더 자세히 확인할 수 있다.


localhost:8080/actuator/metrics/jvm.memory.used 접속 결과

{
  "name": "jvm.memory.used",
  "description": "The amount of used memory",
  "baseUnit": "bytes",
  "measurements": [
    {
      "statistic": "VALUE",
      "value": 175116296
    }
  ],
  "availableTags": [
    {
      "tag": "area",
      "values": [
        "heap",
        "nonheap"
      ]
    },
    {
      "tag": "id",
      "values": [
        "G1 Survivor Space",
        "Compressed Class Space",
        "Metaspace",
        "CodeCache",
        "G1 Old Gen",
        "G1 Eden Space"
      ]
    }
  ]
}
  • 현재 메모리 사용량을 확인할 수 있다.

Tag 필터

availableTags를 보면 다음과 같은 항목을 확인할 수 있다.

  • tag:area, values[heap, nonheap]
  • tag:id, values[G1 Survivor Space, ...]

tag=KEY:VALUE와 같은 형식을 사용해서 정보를 필터링해서 확인할 수 있다.


아래는 tag를 사용해서 힙 메모리와 힙이 아닌 메모리로 분류해서 데이터를 확인한 모습이다.


localhost:8080/actuator/metrics/jvm.memory.used?tag=area:heap 접속 결과

{
  "name": "jvm.memory.used",
  "description": "The amount of used memory",
  "baseUnit": "bytes",
  "measurements": [
    {
      "statistic": "VALUE",
      "value": 102384288
    }
  ],
  "availableTags": [
    {
      "tag": "id",
      "values": [
        "G1 Survivor Space",
        "G1 Old Gen",
        "G1 Eden Space"
      ]
    }
  ]
}

localhost:8080/actuator/metrics/jvm.memory.used?tag=area:nonheap 접속 결과

{
  "name": "jvm.memory.used",
  "description": "The amount of used memory",
  "baseUnit": "bytes",
  "measurements": [
    {
      "statistic": "VALUE",
      "value": 73109000
    }
  ],
  "availableTags": [
    {
      "tag": "id",
      "values": [
        "Metaspace",
        "CodeCache",
        "Compressed Class Space"
      ]
    }
  ]
}

HTTP 요청수 확인

/actuator/metrics/http.server.requests에 접속하면 HTTP 요청수를 확인할 수 있다.


localhost:8080/actuator/metrics/http.server.requests 접속 결과

{
  "name": "http.server.requests",
  "baseUnit": "seconds",
  "measurements": [
    {
      "statistic": "COUNT",
      "value": 8.0
    },
    {
      "statistic": "TOTAL_TIME",
      "value": 0.31012176
    },
    {
      "statistic": "MAX",
      "value": 0.0
    }
  ],
  "availableTags": [
    {
      "tag": "exception",
      "values": [
        "none"
      ]
    },
    {
      "tag": "method",
      "values": [
        "GET"
      ]
    },
    {
      "tag": "error",
      "values": [
        "none"
      ]
    },
    {
      "tag": "uri",
      "values": [
        "/actuator/metrics/{requiredMetricName}",
        "/actuator/metrics",
        "/**"
      ]
    },
    {
      "tag": "outcome",
      "values": [
        "CLIENT_ERROR",
        "SUCCESS"
      ]
    },
    {
      "tag": "status",
      "values": [
        "404",
        "200"
      ]
    }
  ]
}

다양한 메트릭

마이크로미터와 액츄에이터가 기본으로 제공하는 다양한 메트릭이 존재한다.

  • JVM 메트릭
  • 시스템 메트릭
  • 애플리케이션 시작 메트릭
  • 스프링 MVC 메트릭
  • 톰캣 메트릭
  • 데이터 소스 메트릭
  • 로그 메트릭
  • 기타 수 많은 메트릭이 있다.
  • 사용자 정의

JVM 메트릭
jvm.으로 시작한다.

  • 메모리 및 버퍼 풀 세부 정보
  • 가비지 수집 관련 통계
  • 스레드 활용
  • 로드 및 언로드된 클래스 수
  • JVM 버전 정보
  • JIT 컴파일 시간

시스템 메트릭
system., process., disk. 으로 시작한다.

  • CPU 지표
  • 파일 디스크립터 메트릭
  • 가동 시간 메트릭
  • 사용 가능한 디스크 공간

애플리케이션 시작 메트릭
애플리케이션 시작 시간 메트릭을 제공한다.

  • application.started.time: 애플리케이션을 시작하는데 걸리는 시간 (ApplicationStartedEvent로 측정)
  • application.ready.time: 애플리케이션이 요청을 처리할 준비가 되는데 걸리는 시간 (ApplicationReadyEvent로 측정)

스프링은 내부에 여러 초기화 단계가 있고, 각 단계별로 내부에서 애플리케이션 이벤트를 발행한다.

  • ApplicationStartedEvent: 스프링 컨테이너가 완전히 실행된 상태이다. 이후에 커맨드 라인 러너가 호출된다.
  • ApplicationReadyEvent: 커맨드 라인 러너가 실행된 이후에 호출된다.

스프링 MVC 메트릭
스프링 MVC 컨트롤러가 처리하는 모든 요청을 다룬다.


메트릭 이름: http.server.requests

  • TAG를 사용해서 다음 정보를 분류해서 확인할 수 있다.
  • uri: 요청 URI
  • method: GET, POST 같은 HTTP 메서드
  • status: 200, 400, 500 같은 HTTP Status 코드
  • exception: 예외
  • outcome: 상태코드를 그룹으로 모아서 확인 1xx:INFORMATIONAL, 2xx:SUCCESS, 3xx:REDIRECTION, 4xx:CLIENT_ERROR, 5xx:SERVER_ERROR

데이터소스 메트릭
jdbc.connections.로 시작하며, 최대 커넥션, 최소 커넥션, 활성 커넥션, 대기 커넥션 수 등을 확인할 수 있다. 그리고 히카리 커넥션 풀을 사용하면 hikaricp.를 통해 히카리 커넥션 풀의 자세한 메트릭을 확인할 수 있다.

localhost:8080/actuator/metrics/hikaricp.connections 접속 결과

{
  "name": "hikaricp.connections",
  "description": "Total connections",
  "measurements": [
    {
      "statistic": "VALUE",
      "value": 10.0
    }
  ],
  "availableTags": [
    {
      "tag": "pool",
      "values": [
        "HikariPool-1"
      ]
    }
  ]
}

로그 메트릭
logback.events로 logback 로그에 대한 메트릭을 확인할 수 있으며, trace, debug, info, warn, error 각각의 로그 레벨에 따른 로그 수를 확인할 수 있다.


톰캣 메트릭

tomcat. 으로 시작하며, 톰캣 메트릭을 모두 사용하려면 아래 옵션을 켜야한다.(옵션을 켜지 않으면 tomcat.session. 관련 정보만 노출)

server:
    tomcat:
      mbeanregistry:
        enabled: true

tomcat 옵션 설정 후, localhost:8080/actuator/metrics/tomcat.threads.config.max 접속 결과

{
  "name": "tomcat.threads.config.max",
  "baseUnit": "threads",
  "measurements": [
    {
      "statistic": "VALUE",
      "value": 200.0
    }
  ],
  "availableTags": [
    {
      "tag": "name",
      "values": [
        "http-nio-8080"
      ]
    }
  ]
}
  • measurements.value: 현재 tomcat 쓰레드가 200개의 요청을 처리할 수 있다.

메트릭 공식 메뉴얼




Reference
김영한. 스프링 부트 - 핵심 원리와 활용. 인프런.

'Spring' 카테고리의 다른 글

[Spring] 메트릭(metric)을 직접 등록해보자  (0) 2023.04.17
[Spring] 프로메테우스 (prometheus)  (0) 2023.04.14
[Spring] actuator (액츄에이터)  (0) 2023.04.10
[Spring] YAML , @Profile  (0) 2023.04.09
[Spring] 외부 설정 방법  (0) 2023.04.06
댓글
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
«   2025/04   »
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
글 보관함