마이크로미터는 애플리케이션 메트릭 파사드라고 불리며, 애플리케이션의 CPU, 메모리, 커넥션 사용, 요청 수 수많은 지표들을 확인할 때, 마이크로미터가 표준 방법으로 모아서 제공해준다.
스프링 부트 액츄에이터는 마이크로미터를 기본으로 내장하기에, 개발자는 마이크로미터가 정한 표준 방법으로 메트릭(지표)을 전달하면 된다.
앞서 말했듯이, 스프링 액츄에이터는 마이크로미터를 기본적으로 내장하고 있기에, 액츄에이터를 사용하면 매트릭을 편리하게 사용할 수 있다.
http://localhost:8080/actuator/metrics 으로 들어가면 액츄에이터가 마이크로미터를 통해서 기본으로 등록한 매트릭들을 확인할 수 있고 양이 매우매우 많다...
솔직히 다 모른다..
한 가지를 예를 든다면, http://localhost:8080/actuator/metrics/jvm.memory.used 로 들어가면
JVM 현재 메모리 사용량을 확인할 수 있다.
{
"name": "jvm.memory.used",
"description": "The amount of used memory",
"baseUnit": "bytes",
"measurements": [
{
"statistic": "VALUE",
"value": 131172848
} ],
"availableTags": [
{
"tag": "area",
"values": [
"heap",
"nonheap"
] },
{
"tag": "id",
"values": [
"G1 Survivor Space",
"Compressed Class Space",
"Metaspace",
"CodeCache",
"G1 Old Gen",
"G1 Eden Space"
] }
]
}
애플리케이션에서 발생한 메트릭을 그 순간만 확인하는 게 아니라, 우리는 과거 이력까지 함께 확인해야한다.
이럴려면 메트릭을 보관하는 DB가 필요한데, 이걸 프로메테우스가 담당해준다.
프로메테우스가 설치됐다는 전제 하에 프로메테우스는 애플리케이션의 메트릭을 가져오려면 아까 처럼 제이슨 형태가 아닌, 프로메테우스만의 포멧으로 가져와야한다.
하지만 앞서 말했듯이, 마이크로미터는 추상화를 잘해놓고 구현체만 알아서 갈아끼우면 되기에 이는 마이크로미터가 잘 해결해주고 있다.(편하다)
build.gradle에서 마이크로미터 프로메테우스 구현 라이브러리를 추가해주면 끝!
implementation 'io.micrometer:micrometer-registry-prometheus' //추가
http://localhost:8080/actuator/prometheus 로 들어가면 제이슨 형태가 아닌, 프로메테우스 포멧으로 정리된 것을 볼 수 있다.
# HELP tomcat_threads_config_max_threads
# TYPE tomcat_threads_config_max_threads gauge
tomcat_threads_config_max_threads{name="http-nio-8080",} 200.0
# HELP tomcat_sessions_alive_max_seconds
# TYPE tomcat_sessions_alive_max_seconds gauge
tomcat_sessions_alive_max_seconds 0.0
# HELP tomcat_cache_access_total
# TYPE tomcat_cache_access_total counter
tomcat_cache_access_total 0.0
# HELP jvm_info JVM version info
# TYPE jvm_info gauge
jvm_info{runtime="OpenJDK Runtime Environment",vendor="JetBrains
s.r.o.",version="17.0.3+7-b469.37",} 1.0
# HELP logback_events_total Number of events that made it to the logs
# TYPE logback_events_total counter
logback_events_total{level="warn",} 0.0
logback_events_total{level="debug",} 0.0
logback_events_total{level="error",} 2.0
logback_events_total{level="trace",} 0.0
logback_events_total{level="info",} 47.0
...
포멧의 차이로는 앞서 jvm.memory.used 이런식으로 포멧을 사용했지만, 프로메테우슨 jvm_memory_used 이렇게 언더바로 포멧을 활용한다.
긜고 로그 수 혹은 요청 수 처럼 누적되는 숫자에 대해서는 _total 을 붙여주는 것이 관례라고 한다.
프로메테우스가 개발 애플리케이션의 수집을 설정할 필요가 있는데, 프로메테우스를 다운 받았을 때, yml 파일이 있었을 것이다.
거기서
- job_name: "spring-actuator"
metrics_path: '/actuator/prometheus'
scrape_interval: 1m
static_configs:
- targets: ['localhost:8080']
이 부분을 추가해주는데
주의사항
yml 파일이기에 앞에 띄어쓰기 2칸에 유의하자!
job_name : 수집하는 이름이다. 아무거나 사용해도 된다.
metrics_path: 수집할 경로를 지정해준다.
scrape_interval: 수집할 주기를 설정한다 (보통은 1m으로 설정한다. 수집 주기가 짧으면 성능에 영향이 간다.)
targets: 수집할 IP, PORT를 지정해준다.
설정이 끝나면 프로메테우스 서버를 종료하고 다시 실행해준 뒤,
http://localhost:9090/config 에서 yml 파일에 내가 설정한 것이 제대로 들어갔는지 확인하고
http://localhost:9090/targets 에서 state가 UP인지 확인을 하자 DOWN이면 연동이 안된것이다.
간단한 기능을 알아보자
프로메테우스 검색창에 http_server_requests_seconds_count를 검색하면
이렇게 테이블을 볼 수 있다.
여기서 좀 더 자세히 메트릭을 살펴보기 위해서는 마이크로미터에서 사용하는 단어는 태그라 하고 프로메테우스에서는 레이블이라고 하는데 레이블을 기준으로 필터를 사용해서 특정한 메트릭을 볼 수 있다.
필터는 중괄호 문법을 사용한다.
예를 들어
/actuator/prometheus 라는 메트릭을 보고 싶으면
http_server_requests_seconds_count{uri="/actuator/prometheus"}
"=" (제공된 문자열과 정확히 동일한 레이블 선택) 연산자를 이용
혹은
/actuator/prometheus 라는 메트릭을 제외하고 보고싶으면
http_server_requests_seconds_count{uri!="/actuator/prometheus"}
"!=" (제공된 문자열과 같지 않은 레이블 선택) 연산자를 이용
또는 method가 GET, POST인 경우를 포함해서 보고 싶다면
http_server_requests_seconds_count{method=~"GET|POST"}
"=~" (제공된 문자열과 정규식이 일치하는 레이블 선택) 연산자를 이용
혹은 /log 로 시작하는 uri를 제외하는 조건으로 필터를 하고싶으면
http_server_requests_seconds_count{uri!~"/Log.*"}
"!~" (제공된 문자열과 정규식이 일치하지 않는 레이블 선택) 연산자를 이용
이렇듯 =, !=, =~, !~ 연산자가 있다.
그리고
count(http_server_requests_seconds_count)
메트릭 자체의 수 카운트를 해주는 함수
topk(3,http_server_requests_seconds_count)
상위 3개의 메트릭을 조회해주는 함수
http_server_requests_seconds_count[1m]
범위 벡터 선택기를 통해서 지난 1분간의 기록값을 선택하는 것이 있다.
앞서 말했듯이, 로그 수 혹은 요청 수 처럼 단순하게 쌓이는 누적 값은 카운터 라 부르고
임의로 오르내리락 하는 값을 게이지 라 할 수 있다.
그러나 카운터에는 치명적인 점이 있다.
예를 들어
http_server_requests_seconds_count{uri="/log"}
/log HTTP 요청 수를 표현하는 그래프에서 카운터는 계속해서 누적되는 값이다.
따라서 이렇게 계속 우상향 하는 차트를 보여주게 된다(내 코인이 이렇다면..)
이 문제를 해결하기위해 increase() 함수와, rate()함수를 사용하게된다.
increase(http_server_requests_seconds_count{uri="/log"}[1m])
increase()는 내가 설정한 시간당 얼마의 요청이 증가했는지를 파악할 수 있다.
increase()는 숫자를 직접 카운트 한다면, rate()는 초당 평균을 나누어서 계산하게 된다.
rate(data[1m])은 60초가 기준이 되므로 60을 나눈 수이고,
rate(data[2m])은 120초가 기준이 되기에 120을 나눈 수이다.
초당 얼마나 증가하는지 나타내는 지표로 보면 된다.
rate()와 유사한데, 초당 순간 증가율로 알아두자.
앞서 프로메테우스를 봤듯이, 지난 과거 메트릭들을 보관하고 그것들을 볼 수 있었다.
근데 한 눈에 들어오지 않는 게 치명적인 단점이다.
이는 그라파나가 해결해준다.
그라파나가 설치되었단 전제하에 연동을 해보자
그라파나는 프로메테우스를 데이터소스로 사용해서 데이터를 읽어와야한다.
그라파나 데이터소스를 추가하기 위해서
왼쪽 하단에 설정 버튼을 통해서 데이터 소스를 선택하고 add를 선택한 뒤, 프로메테우스를 선택해준다.
프로메테우스의 URL은 http://localhost:9090이다. 그리고 세이브!
이러면 연동 끝
new dashboard를 클릭하고,
패널을 새로 만든 뒤,
PromQL 부분에 프로메테우스 쿼리를 넣어주면 된다.
한 가지 예로 cpu 사용량을 쿼리를 날렸는데 쿼리를 입력하고 Run quries를 눌러주자
그리고 밑에 Option을 클릭해서 Legend에서 custom을 통해서 해당 지표의 이름을 만들어 줄 수 있다.
사실 내가 이렇게 대시보드를 하나하나 만드는 것 보다 공유 대시보드를 활용하는 게 좋다
https://grafana.com/grafana/dashboards 에서 내가 원하는 대시보드를 선택해서 사용해보도록 하면 된다
출처 - 영한님의 스프링부트 핵심 원리와 활용