서비스를 운영할 때는 애플리케이션의 CPU, 메모리, 커넥션 사용, 고객 요청수 같은 수 많은 지표들을 확인하는 것이 필요하다. 그래야 문제가 발생하기 전에 미리 대응을 할 수 있고, 문제 발생시 발빠른 대처가 가능해진다.
이러한 모니터링 툴을 작동하려면 다양한 지표들을 각각의 모니터링 툴에 맞도록 보내주어야 한다. 이때 애플리케이션의 메트릭(측정 지표)을 마이크로미터가 정한 표준 방법으로 모아서 제공해준다.

메트릭의 과거 이력까지 함께 확인하기 위해서는 보관할 DB가 필요하다. 프로메테우스는 메트릭을 지속해서 수집하고 DB에 저장하는 역할을 한다.
프로메테우스가 DB라고 하면, 그라파나는 수집된 데이터를 보기 편하게 대시보드로 만들어주는 역할을 한다.

prometheus.yml에 추가
#추가
- job_name: "spring-actuator"
metrics_path: '/actuator/prometheus'
scrape_interval: 1s
static_configs:
- targets: ['localhost:8080']
예제에서는 수집 주기를
1s로 했지만, 기본 값은1m이다. 수집 주기가 너무 짧으면 애플리케이션에 영향을 줄 수 있으므로 운영에서는10s ~ 1m정도를 권장한다.

중괄호{} 문법을 사용하여 필터를 사용
= 제공된 문자열과 정확히 동일한 레이블 선택!= 제공된 문자열과 같지 않은 레이블 선택=~ 제공된 문자열과 정규식 일치하는 레이블 선택!~ 제공된 문자열과 정규식 일치하지 않는 레이블 선택sum by(method, status)(http_server_requests_seconds_count)
SQL의 group by 기능과 유사
count(http_server_requests_seconds_count)
메트릭 자체의 수 카운트
topk(3, http_server_requests_seconds_count)
상위 3개 메트릭 조회
http_server_requests_seconds_count offset 10m
현재를 기준으로 특정 과거 시점의 데이터를 반환

http_server_requests_seconds_count[1m]
마지막에 [1m] , [60s] 와 같이 표현한다. 지난 [시간]의 모든 기록값을 반환

지정한 시간 단위별로 증가를 확인할 수 있다.
마지막에 [시간] 을 사용해서 범위 벡터를 선택해야 한다.
예) increase(http_server_requests_seconds_count{uri="/log"}[1m])

범위 백터에서 초당 평균 증가율을 계산한다.
increase() 가 숫자를 직접 카운트 한다면, rate() 는 여기에 초당 평균을 나누어서 계산한다.
예) rate(http_server_requests_seconds_count{uri="/log"}[1m])에서 [1m] 이라고 하면 60초가 기준이 되므로 60을 나눈 수이다.

rate 와 유사한데, 범위 벡터에서 초당 순간 증가율을 계산한다. 급격하게 증가한 내용을 확인하기 좋다.

그라파나는 프로메테우스를 통해 데이터를 조회하고 보여주는 대시보드의 역할을 한다.
https://grafana.com/grafana/dashboards
실무에서 주로 발생하는 다음 4가지 대표적인 예시를 확인해보자.
@Slf4j
@RestController
public class TrafficController {
@GetMapping("/cpu")
public String cpu() {
log.info("cpu");
long value =0;
for (long i = 0; i < 100000000000L; i++) {
value++;
}
return "ok value=" + value;
}
}

private List<String> list = new ArrayList<>();
@GetMapping("/jvm")
public String jvm() {
log.info("jvm");
for (int i = 0; i < 1000000; i++) {
list.add("hello jvm!" + i);
}
return "ok";
}

@Autowired DataSource dataSource;
@GetMapping("/jdbc")
public String jdbc() throws SQLException {
log.info("jdbc");
Connection conn = dataSource.getConnection();
log.info("connection info={}", conn);
//conn.close(); //커넥션을 닫지 않는다.
return "ok";
}

@GetMapping("/error-log")
public String errorLog() {
log.error("error log");
return "error";
}

메트릭을 보는 것의 목적은 정확한 값을 보는 것이 아닌, 추세를 확인하는 것이 주 목적이다.