Skip to main content

NestJS 메트릭 기반 모니터링 시스템 구축 (prom-client, Prometheus, Grafana)

•3 min•641 words

사전 지식

Prometheus 환경 세팅

Prometheus 설정

prometheus.yml

global:
  scrape_interval:     15s
  evaluation_interval: 15s

rule_files:
  # - "first.rules"
  # - "second.rules"

scrape_configs:
  - job_name: prometheus
    static_configs:
      - targets: ['localhost:9090']
  • 예제 구성 파일에는 세 가지 구성 블록이 있다.
  1. global****: 프로메테우스 서버의 글로벌 설정
    • scrape_interval
      • 데이터를 수집하는 주기
      • Prometheus가 타겟에 가서 메트릭을 긁어오는 간격
      • 예시: 15초마다 서버에 가서 현재 CPU, 메모리 등의 값을 가져옴
    • evaluation_interval
      • 규칙을 계산하는 주기
      • 예시: “CPU가 80% 넘었나?”
  2. rule_files****: Prometheus 서버가 로드할 규칙의 위치를 지정
    • 지금은 주석 처리
  3. scrape_configs****: Prometheus가 감시할 서버 목록
    • 기본값은 Prometheus가 자기 자신을 모니터링
    • Prometheus는 모든 타겟이 기본적으로 /metrics 경로에 메트릭을 노출한다고 가정

도커 컴포즈 설정

docker-compose.yml

prometheus:
  image: prom/prometheus
  ports:
    - '9090:9090'
  volumes:
    - ./infra/prometheus/prometheus.yml:/etc/prometheus/prometheus.yml
    - prometheus_data:/prometheus

실행:

docker compose up prometheus -d

Prometheus UI 접속

image.png

PromQL 테스트

  1. 수집 정상 여부 확인

    up

    결과:

    up{job="prometheus", instance="localhost:9090"}  1
  2. Prometheus HTTP 요청 수

    prometheus_http_requests_total

    결과:

    image.png

  3. 메모리 사용량

    process_resident_memory_bytes

    결과:

    image.png

NestJS metrics 생성

https://github.com/willsoto/nestjs-prometheus

의존성 설치

npm install @willsoto/nestjs-prometheus prom-client

AppModule 수정

import { Module } from "@nestjs/common";
import { PrometheusModule } from "@willsoto/nestjs-prometheus";

@Module({
  imports: [PrometheusModule.register()],
})
export class AppModule {}

도커 컴포즈 설정

docker-compose.yml

app:
  volumes:
    - .:/app
    - /app/node_modules
  ports:
    - '3000:3000'

실행:

docker compose up app -d

/metrics 엔드포인트 테스트

# HELP process_cpu_user_seconds_total Total user CPU time spent in seconds.
# TYPE process_cpu_user_seconds_total counter
process_cpu_user_seconds_total 3.92215

# ... 중략

Node.js 기본 메트릭(defaultMetrics)

  1. 프로세스(Process) 메트릭

    메트릭현재 값단위의미
    process_cpu_user_seconds_total3.92seconds사용자 영역 CPU 사용 시간
    process_cpu_system_seconds_total1.20seconds시스템 영역 CPU 사용 시간
    process_cpu_seconds_total5.12seconds전체 CPU 사용 시간
    process_resident_memory_bytes130,191,360bytes실제 물리 메모리 사용량
    process_virtual_memory_bytes925,908,992bytes가상 메모리
    process_heap_bytes407,281,664bytes힙 전체 크기
    process_open_fds24count열린 파일 디스크립터 수
    process_max_fds1,048,576count최대 허용 fd 수
  2. 이벤트 루프(Event Loop) 상태

    메트릭값단위의미
    nodejs_eventloop_lag_seconds0.0064seconds현재 이벤트 루프 지연
    nodejs_eventloop_lag_mean_seconds0.0118seconds평균 지연
    nodejs_eventloop_lag_p99_seconds0.0154seconds99% 지연
    nodejs_eventloop_lag_max_seconds0.0517seconds최대 지연
  3. 활성 리소스/핸들

    메트릭값의미
    nodejs_active_resources_total7현재 이벤트루프를 유지하는 리소스
    nodejs_active_handles_total5활성 libuv 핸들
    nodejs_active_requests_total1활성 요청 수
  4. 힙 메모리 상태

    메트릭값단위
    nodejs_heap_size_total_bytes50,823,168bytes
    nodejs_heap_size_used_bytes46,498,680bytes
    nodejs_external_memory_bytes2,668,963bytes
  5. GC (Garbage Collection)

    종류실행 횟수총 소요 시간
    minor3회0.019s
    major3회0.079s
    incremental3회0.084s

Prometheus - NestJS 연동

prometheus.yml 수정

scrape_configs:
  - job_name: prometheus
	  metrics_path: /metrics
    static_configs:
      - targets: ['prometheus:9090']

  - job_name: app
    metrics_path: /metrics
    static_configs:
      - targets: ['app:3000']

PromQL 테스트

  1. 수집 정상 여부 확인

    up

    결과:

    up{job="app", instance="app:3000"}  1
    up{job="prometheus", instance="prometheus:9090"}  1
  2. NestJS 메트릭 수집 확인 (프로세스 메모리)

    process_resident_memory_bytes{job="app"}

    image.png

  3. NestJS CPU 사용량 추이(초당 증가량)

    rate(process_cpu_seconds_total{job="app"}[1m])

    image.png

  4. 이벤트 루프 지연 확인 (ms 단위로 보기)

    nodejs_eventloop_lag_p99_seconds{job="app"} * 1000

    image.png



Grafana 환경 세팅

도커 컴포즈 설정

docker-compose.yml

grafana:
  image: grafana/grafana
  ports:
    - "3002:3000"
  volumes:
    - grafana_data:/var/lib/grafana
  depends_on:
    - prometheus

volumes:
  prometheus_data:
  grafana_data:

실행:

docker compose up grafana -d

Grafana 접속

image.png

Grafana - Prometheus 연동

Prometheus Data Source 추가

  1. Grafana 접속 → 왼쪽 메뉴 Connections(또는 톱니바퀴 Settings) → Data sources

  2. Add data source → Prometheus 선택

  3. URL 입력

    http://prometheus:9090
  4. Save & test

    • docker-compose 네트워크 안에서 Grafana가 Prometheus를 접근할 때는 localhost가 아니라 서비스명(prometheus) 를 써야 함.

    • Successfully queried the Prometheus API. 안내 메시지가 뜨는지 확인

      image.png

image.png

Grafana 대시보드 확인

Explore에서 쿼리 테스트

  • 왼쪽 메뉴 Explore에서 Prometheus 선택 후 아래 쿼리 실행
up

image.png

공개 대시보드 찾기

image.png

Node.js/NestJS 대시보드 불러오기

Grafana는 Import로 공개 대시보드를 쉽게 가져올 수 있음

  1. 왼쪽 메뉴 Dashboards → New → Import

  2. Dashboard ID로 Import

    • 예시: 11159
  3. DB_PROMETHEUS는 prometheus 선택

    image.png

대시보드 확인

제대로 설정이 됐다면 아래와 같이 대시보드 화면이 잘 나오는 것을 볼 수 있음

image.png

참고 자료