부록 B: 메트릭 상세 분석 (심화 학습)
대상 독자: APM 엔지니어, DevOps 엔지니어, 시스템 성능 튜닝 담당자
이 문서는 메트릭 수집의 상세 기술 내용을 다룹니다. 일반 사용자는 부록 A: 메트릭 데이터 수집를 먼저 읽으시길 권장합니다.
개요
이 문서는 FlowKat이 수집하는 모든 메트릭의 상세 정의, 데이터 원본, 계산 방법, 엔지니어 해석 가이드를 제공합니다.
1. Host Agent 메트릭 상세
1.1 CPU 메트릭
1.1.1 메트릭 정의
| 메트릭 명 | 상수 | 데이터 원본 | 계산 방법 | 실무 의미 | 주의 기준 |
|---|---|---|---|---|---|
| CPU 사용률 | HOST_CPU | /proc/stat | 100 × (1 - idle / total) | 전체 CPU 활용도, 코어별 평균 | >80%: 주의, >90%: 위험 |
| 시스템 CPU | HOST_SYSCPU | /proc/stat | 100 × system / total | 커널 모드 실행 비율 (시스템 콜, I/O) | >30%: I/O 병목 의심 |
| 사용자 CPU | HOST_USERCPU | /proc/stat | 100 × user / total | 애플리케이션 실행 비율 | 지속 >70%: 프로세스 최적화 필요 |
1.1.2 데이터 원본 분석
**/proc/stat** 파일 포맷:
cpu 2255 34 2290 22625563 6290 127 456 0 0 0 0
^user ^nice ^system ^idle ^iowait ^irq ^softirq
필드 설명:
user: 사용자 모드 실행 시간 (애플리케이션)system: 커널 모드 실행 시간 (시스템 콜)idle: 유휴 시간iowait: I/O 대기 시간
CPU 사용률 계산:
CPU 사용률 = 100 × (1 - idle / 전체 합계)
= 100 × (1 - idle / (user + nice + system + idle + iowait + irq + softirq))
1.1.3 엔지니어 해석 가이드
IOWait가 높으면 (20%+):
진단:
→ 디스크 I/O 병목
→ 네트워크 대기 시간
→ 외부 API 호출 지연
확인 방법:
1. iostat -x 1으로 I/O 대기 확인
2. pidstat -d로 프로세스별 I/O 확인
3. netstat로 네트워크 연결 상태 확인
해결 방법:
1. 디스크를 SSD로 교체
2. DB 쿼리 튜닝
3. 캐시 레이어 추가
4. 비동기 I/O로 변경
System CPU가 높으면 (30%+):
진단:
→ 시스템 콜 과다
→ 컨텍스트 스위칭 빈번
→ 스레드가 너무 많음
확인 방법:
1. pidstat -w로 컨텍스트 스위칭 확인
2. ps -eLf로 스레드 수 확인
3. strace로 시스템 콜 추적
해결 방법:
1. 스레드 풀 크기 조정
2. 락 경쟁 감소
3. 시스템 콜 최적화
1.2 메모리 메트릭
1.2.1 메트릭 정의
| 메트릭 명 | 상수 | 데이터 원본 | 계산 방법 | 실무 의미 | 주의 기준 |
|---|---|---|---|---|---|
| 메모리 사용률 | HOST_MEM | /proc/meminfo | 100 × (MemTotal - MemAvailable) / MemTotal | 실제 사용 중인 메모리 비율 (버퍼+캐시 포함) | >85%: 위험 |
| 전체 메모리 | HOST_MEM_TOTAL | /proc/meminfo | MemTotal / 1024 (KB→MB 변환) | 물리 메모리 총량 | - |
| 사용 메모리 | HOST_MEM_USED | /proc/meminfo | (MemTotal - MemAvailable) / 1024 | 실제 사용량 (anon + file + slab) | - |
| 가용 메모리 | HOST_MEM_AVAILABLE | /proc/meminfo | MemAvailable / 1024 | 즉시 할당 가능한 메모리 | <500MB: 부족 경고 |
1.2.2 데이터 원본 분석
**/proc/meminfo** 주요 필드:
MemTotal: 16384000 kB (16GB)
MemFree: 2048000 kB (2GB, 실제 free)
MemAvailable: 8192000 kB (8GB, 버퍼+캐시 제외한 가용량)
Buffers: 102400 kB
Cached: 5120000 kB
SwapTotal: 8388608 kB (8GB)
SwapFree: 8388608 kB
필드 설명:
MemTotal: 물리 메모리 총량MemFree: 완전히 비어 있는 메모리MemAvailable: 버퍼+캐시를 포함한 가용 메모리 (실제 사용 가능량)Buffers: 블록 디바이스 버퍼Cached: 페이지 캐시
1.2.3 엔지니어 해석 가이드
메모리 부족 판단 기준:
기준 1: MemAvailable < 10% MemTotal
→ OOM Kill 위험
기준 2: SwapUsed > 50% SwapTotal
→ 물리 메모리 부족
기준 3: SwapInRate > 0
→ 스와핑 활발 (성능 저하)
확인 방법:
1. free -m으로 메모리 사용량 확인
2. vmstat 1로 스와핑 활동 확인
3. sar -r 1로 메모리 추이 확인
해결 방법:
1. 물리 메모리 증설
2. 메모리 누수 원인 파악 (heap dump 분석)
3. 캐시 크기 조정 (buffer/cache 감소)
4. 애플리케이션 메모리 사용량 최적화
1.3 스왑 메트릭
1.3.1 메트릭 정의
| 메트릭 명 | 상수 | 데이터 원본 | 계산 방법 | 실무 의미 | 주의 기준 |
|---|---|---|---|---|---|
| 스왑 사용률 | HOST_SWAP | /proc/meminfo | 100 × (SwapTotal - SwapFree) / SwapTotal | 가상 메모리 사용 비율 | >10%: 물리 메모리 부족 |
| 전체 스왑 | HOST_SWAP_TOTAL | /proc/meminfo | SwapTotal / 1024 (KB→MB) | 스왑 파티션 총량 | - |
| 사용 스왑 | HOST_SWAP_USED | /proc/meminfo | (SwapTotal - SwapFree) / 1024 | 스왑 사용량 | - |
1.3.2 엔지니어 해석 가이드
스와핑이 발생하면:
영향:
→ 디스크 I/O 급증 (디스크가 RAM보다 1000배 느림)
→ 응답 시간 급격 저하 (페이지 폴트 대기)
→ 스레드가 차단(BLOCKED) 상태로 대기
진단:
1. vmstat 1로 si/so (swap in/out) 확인
2. iostat -x 1로 디스크 I/O 급증 확인
3. ps aux로 대기 상태 스레드 확인
해결 방법:
1. 물리 메모리 증설 (우선)
2. 메모리 누수 원인 파악 (heap dump 분석)
3. 캐시 크기 조정 (buffer/cache 감소)
4. swappiness 설정 조정 (vm.swappiness=10)
1.4 네트워크 메트릭
1.4.1 메트릭 정의
| 메트릭 명 | 상수 | 데이터 원본 | 계산 방법 | 실무 의미 | 주의 기준 |
|---|---|---|---|---|---|
| 수신 패킷 | HOST_NET_IN | /proc/net/snmp | delta(inReceives) / delta(time) | 초당 수신 패킷 수 (pps) | - |
| 송신 패킷 | HOST_NET_OUT | /proc/net/snmp | delta(outRequests) / delta(time) | 초당 송신 패킷 수 (pps) | - |
| 수신 바이트 | HOST_NET_RX_BYTES | /proc/net/snmp | delta(inOctets) / delta(time) | 초당 수신 바이트 (Bps) | >80% 대역폭: 병목 |
| 송신 바이트 | HOST_NET_TX_BYTES | /proc/net/snmp | delta(outOctets) / delta(time) | 초당 송신 바이트 (Bps) | >80% 대역폭: 병목 |
1.4.2 데이터 원본 분석
**/proc/net/snmp** 주요 필드:
inReceives: 총 수신 패킷 수
inOctets: 총 수신 바이트 수
outRequests: 총 송신 패킷 수
outOctets: 총 송신 바이트 수
1.4.3 엔지니어 해석 가이드
대역폭 사용률 계산:
1Gbps NIC = 125 MB/s 이론 최대
실제 처리량 = RX_BYTES + TX_BYTES (bytes/sec)
사용률 = 실제 처리량 / 125 MB/s × 100
네트워크 병목 징후:
징후 1: 사용률 > 80%
→ 대역폭 증설 고려
징후 2: RX_Errors > 0
→ 케이블/포트 문제
징후 3: RX_Dropped > 0
→ 수신 버퍼 부족
징후 4: Collisions > 0 (half-duplex)
→ full-duplex로 변경
1.5 디스크 I/O 메트릭
1.5.1 메트릭 정의
| 메트릭 명 | 상수 | 데이터 원본 | 계산 방법 | 실무 의미 | 주의 기준 |
|---|---|---|---|---|---|
| 디스크 읽기 | HOST_DISK_READ_BYTES | /proc/diskstats | delta(sector_reads) × 512 / delta(time) | 초당 디스크 읽기 바이트 | >100MB/s: HDD 한계 |
| 디스크 쓰기 | HOST_DISK_WRITE_BYTES | /proc/diskstats | delta(sector_writes) × 512 / delta(time) | 초당 디스크 쓰기 바이트 | - |
1.5.2 데이터 원본 분석
**/proc/diskstats** 포맷:
8 0 sda 12345 67890 987 100 11 12 13 14 15
^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^
| | | | | | | | | | | +-- ioMs (I/O 소요 시간)
| | | | | | | | | | +----- weighted ioMs
| | | | | | | | | +-------- writes completed
| | | | | | | | +----------- sectors written
| | | | | | | +-------------- reads completed
| | | | | | +----------------- sectors read
| | | | | +------------------- writes merged
| | | | +------------------------- read merged
| | | +------------------------------ device name
| | +---------------------------------- minor number
| +-------------------------------------- major number
1.5.3 엔지니어 해석 가이드
디스크 병목 징후:
징후 1: Avg I/O Wait > 10ms
→ HDD 한계 (SSD로 교체 권장)
징후 2: IOPS > 5000 (HDD)
→ 순차 I/O 최적화 필요
징후 3: Queue Length > 1
→ I/O 대기 발생
2. Java Agent 메트릭 상세
2.1 Service 메트릭
2.1.1 메트릭 정의
| 메트릭 명 | 상수 | 데이터 원본 | 계산 방법 | 실무 의미 | 주의 기준 |
|---|---|---|---|---|---|
| TPS | WAS_TPS | MeterService | count(delta_time) / delta_time | 초당 트랜잭션 처리량 | - |
| 응답 시간 | WAS_ELAPSED_TIME | MeterService | total_elapsed / count | 평균 응답 시간 (ms) | >SLA×1.5: 주의 |
| P90 응답시간 | WAS_ELAPSED_90PCT | ResponseTimeHistogram | 90% 백분위수 | 상위 10% 제외 응답 시간 | >SLA×2: 위험 |
| 서비스 건수 | WAS_SERVICE_COUNT | MeterService | 누적 처리 건수 (단조 증가) | 총 처리 서비스 수 | - |
| 에러율 | WAS_ERROR_RATE | MeterService | error_count / total_count × 100 | 에러 응답 비율 | >1%: 주의 |
| 활성 서비스 | WAS_ACTIVE_SERVICE | TraceContextManager | activeServiceCount.get() | 현재 처리 중인 서비스 수 | >스레드풀 크기: 대기 |
2.1.2 데이터 원본 분석
MeterService 내부 구조:
private long totalCount = 0; // 단조 증가 카운터
private long totalElapsed = 0; // 단조 증가 누적 시간 (ms)
private long errorCount = 0; // 에러 건수
private final AtomicLong activeCount = new AtomicLong(0);
TPS 계산 (1초 윈도우):
tps = (count(t) - count(t-1000)) / 1000ms
응답 시간 계산:
avg_elapsed = (totalElapsed(t) - totalElapsed(t-1000)) / (count(t) - count(t-1000))
활성 서비스 추적:
startService() → activeCount.incrementAndGet()
endService() → activeCount.decrementAndGet()
2.1.3 P90 응답 시간 상세 설명
P90이란 무엇인가?
P90 = 90번째 백분위수 (90th Percentile)
→ 전체 응답 시간을 오름차순 정렬했을 때 90% 위치에 있는 값
→ "100명 중 90명은 이 시간 안에 응답받았다"를 의미
왜 평균 대신 P90을 쓰는가?
평균의 문제: 아웃라이어(특이값)에 취약
┌────────────────────────────────────────────────────────────┐
│ 데이터: [10ms, 10ms, ..., 10ms, 2000ms] (100개 요청) │
│ │
│ 평균: (10ms × 99 + 2000ms) / 100 = 1019ms │
│ → 1개 느린 요청 때문에 평균이 왜곡됨 │
│ │
│ P50 (중앙값): 10ms │
│ P90: 10ms │
│ P99: 2000ms │
│ │
│ → 대부분 사용자(90%)는 10ms에 응답받았음 │
│ → P90가 실제 사용자 경험을 더 정확히 반영 │
└────────────────────────────────────────────────────────────┘
P90 계산 방법:
ResponseTimeHistogram이 구간별 빈도를 저장:
구간 설정 (예: 0~10ms, 10~20ms, ..., 1000ms~):
┌────────┬────────┬────────┬────────┬────────┐
│ 구간 │ 0~10ms │ 10~20ms│ ... │ 1000+ │
├────────┼────────┼────────┼────────┼────────┤
│ 건수 │ 50 │ 30 │ ... │ 5 │
└────────┴────────┴────────┴────────┴────────┘
누적 빈도 계산:
0~10ms: 50건 → 누적 50건 (50%)
0~20ms: 30건 → 누적 80건 (80%)
...
1000ms+: 5건 → 누적 100건 (100%)
P90 추정:
90% 위치 → 20~30ms 구간에 있음
→ 선형 보간으로 P90 ≈ 25ms
P90 해석 가이드:
P90 < 50ms: 매우 빠름
→ 대부분 요청이 50ms 안에 완료
P90 = 200ms: 적절
→ 90% 사용자는 200ms 경험
→ 상위 10%는 더 느릴 수 있음
P90 > 1000ms: 느림
→ 상위 10% 사용자가 1초 이상 대기
→ 원인 파악 필요 (Slow Query, 외부 API 지연)
P90 vs P99 차이:
P90: 상위 10% 제외 → "대부분" 사용자 경험
P99: 상위 1% 제외 → "꼬리" 사용자 경험
P90과 P99 간격이 크면:
→ 응답 시간 분산이 큼 (불균형)
→ 일부 요청이 매우 느림
→ 캐시 미스나 DB Lock 의심
예시:
P90 = 100ms, P99 = 5000ms
→ 90%는 100ms, 1%는 5초 대기
→ "느린 1%"가 무엇인지 분석 필요
2.1.4 엔지니어 해석 가이드
병목 발생 조건:
조건 1: activeCount ≥ threadPoolSize
→ 요청 대기 (큐잉)
조건 2: avg_elapsed 증가 + activeCount 증가
→ 스레드 고갈 (Stuck)
확인 방법:
1. jstack <pid>으로 스레드 덤프 확인
2. 스레드 상태 분석 (RUNNABLE, BLOCKED, WAITING)
3. ThreadPoolExecutor 상태 확인
해결 방법:
1. 스레드 풀 크기 증설
2. 비동기 처리로 변경
3. 병목 지점 최적화
2.2 Heap 메트릭
2.2.1 메트릭 정의
| 메트릭 명 | 상수 | 데이터 원본 | 계산 방법 | 실무 의미 | 주의 기준 |
|---|---|---|---|---|---|
| Heap 사용량 | JAVA_HEAP_USED | java.lang:type=Memory | HeapMemoryUsage.used / 1024 / 1024 | 힙 영역 사용량 (MB) | - |
| Heap 전체 | JAVA_HEAP_TOTAL | java.lang:type=Memory | max / 1024 / 1024 | 힙 최대 용량 (MB) | - |
| Heap 사용률 | JAVA_HEAP_PERCENT | java.lang:type=Memory | 100 × used / max | 힙 사용 비율 | >85%: 위험 |
2.2.2 데이터 원본 분석
JMX MBean: java.lang:type=Memory:
HeapMemoryUsage:
- init: 초기 크기 (Xms)
- used: 현재 사용량
- committed: JVM이 확보한 크기
- max: 최대 크기 (Xmx)
Heap 영역 구조 (G1 GC 기준):
┌─────────────────────────────────┐
│ Young Generation │
│ ┌─────────┐ ┌─────────┐ │
│ │ Eden │ │Survivor│ │
│ └─────────┘ └─────────┘ │
├─────────────────────────────────┤
│ Old Generation │
│ ┌─────────────────────┐ │
│ │ Humongous │ │
│ └─────────────────────┘ │
└─────────────────────────────────┘
2.2.3 엔지니어 해석 가이드
메모리 누수 징후:
징후 1: Old Gen이 계속 증가
→ 객체 참조 미해제
징후 2: GC 후 사용량이 감소하지 않음
→ 메모리 누수
징후 3: OutOfMemoryError: GC overhead limit exceeded
→ GC 과다
분석 방법:
jmap -heap <pid> # Heap 사용량 확인
jmap -histo:live <pid> # 객체별 사용량 확인
jcmd <pid> GC.heap_info # Heap 영역별 사용량
해결 방법:
1. heap dump 분석 (jmap -dump:live,format=b,file=heap.bin <pid>)
2. MAT (Memory Analyzer Tool)로 누수 원인 파악
3. 객체 참조 해제 코드 수정
4. WeakReference 사용 검토
2.3 GC 메트릭
2.3.1 메트릭 정의
| 메트릭 명 | 상수 | 데이터 원본 | 계산 방법 | 실무 의미 | 주의 기준 |
|---|---|---|---|---|---|
| GC 횟수 | JAVA_GC_COUNT | java.lang:type=GarbageCollector | delta(collectionCount) / 60sec | 1분당 GC 실행 횟수 | >60: 과도 GC |
| GC 시간 | JAVA_GC_TIME | java.lang:type=GarbageCollector | delta(collectionTime) / 60sec | 1분당 GC 총 시간(ms) | >5000ms: STW 지연 |
2.3.2 데이터 원본 분석
JMX MBean: java.lang:type=GarbageCollector,name=G1 Young Generation:
- collectionCount: GC 실행 횟수
- collectionTime: 누적 GC 시간 (ms)
GC 시간/분 계산:
gc_time_per_min = (gc_time(t) - gc_time(t-60000)) / 60000ms × 100
Stop-The-World (STW) 영향:
STW 시간 = GC 시간 중 애플리케이션 스레드가 멈춘 시간
STW 비율 = gc_time_per_min / 60000ms × 100
STW 비율 기준:
< 1%: 양호
1~5%: 주의
> 5%: 위험 (사용자 응답 지연)
2.3.3 엔지니어 해석 가이드
GC 튜닝 가이드라인:
문제 1: Young GC 빈도 ↑
→ Eden 영역 확대
문제 2: Full GC 발생
→ Young/Old 비율 조정
문제 3: STW 시간 길다
→ G1 → ZGC 전환 고려
확인 방법:
jstat -gcutil <pid> 1000 # 1초 간격으로 GC 통계 확인
jcmd <pid> VM.flags # JVM 플래그 확인
jcmd <pid> GC.heap_info # Heap 영역별 사용량
튜닝 예시:
1. Eden 영역 확대: -XX:NewRatio=1 (Young:Old = 1:1)
2. G1 GC 전환: -XX:+UseG1GC
3. ZGC 전환: -XX:+UseZGC (Java 15+)
2.4 Process 메트릭
2.4.1 메트릭 정의
| 메트릭 명 | 상수 | 데이터 원본 | 계산 방법 | 실무 의미 | 주의 기준 |
|---|---|---|---|---|---|
| 프로세스 CPU | JAVA_PROCESS_CPU | java.lang:type=OperatingSystem | 100 × processCpuTime / uptime | JVM 프로세스 CPU 사용률 | >80%: CPU 병목 |
| 파일 디스크립터 | JAVA_FD_USAGE | java.lang:type=OperatingSystem | openFileDescriptorCount | 열린 FD 수 | >ulimit-100: 부족 |
2.4.2 데이터 원본 분석
JMX MBean: java.lang:type=OperatingSystem:
- processCpuTime: 프로세스 CPU 시간 (ns)
- uptime: JVM 가동 시간 (ns)
- openFileDescriptorCount: 열린 FD 수
- maxFileDescriptorCount: 최대 FD 한도
프로세스 CPU 계산:
cpu_usage = (cpu_time(t) - cpu_time(t-1000)) / 1000000000 / 1sec
2.4.3 엔지니어 해석 가이드
FD 한도 확인:
ulimit -n # 최대 FD 수 확인
lsof -p <pid> | wc -l # 현재 열린 FD 수
FD 부족 원인:
원인 1: 파일/소켓 닫지 않음 (Resource Leak)
원인 2: 너무 많은 연결 (DB Connection Pool 크기)
원인 3: 로그 파일 핸들 누적
해결 방법:
해결 1: close() 호출 확인 (try-with-resources 사용)
해결 2: Connection Pool 최대 크기 축소
해결 3: ulimit -n 65536 (한도 증설)
3. Interaction 메트릭 상세
3.1 메트릭 정의
| 메트릭 명 | 상수 | 데이터 원본 | 계산 방법 | 실무 의미 | 주의 기준 |
|---|---|---|---|---|---|
| API 송신 | INTR_API_OUTGOING | ApicallASM | count(startService() - endService()) | 외부 API 호출 건수 | - |
| API 수신 | INTR_API_INCOMING | HttpTrace | HTTP 요청 수신 건수 | - | |
| DB 호출 | INTR_DB_CALL | TraceSQL0 | PreparedStatement.execute() 호출 횟수 | DB 쿼리 실행 건수 | - |
| Redis 호출 | INTR_REDIS_CALL | JedisProtocolASM | Redis 명령어 실행 횟수 | Redis 오퍼레이션 건수 | - |
| Kafka 호출 | INTR_KAFKA_CALL | KafkaProducerASM | Kafka Producer 전송 건수 | Kafka 메시지 전송 건수 | - |
| RabbitMQ 호출 | INTR_RABBITMQ_CALL | RabbitPublisherASM | RabbitMQ publish 건수 | 메시지 발행 건수 | - |
| Elasticsearch 호출 | INTR_ELASTICSEARCH_CALL | RestClientASM | ES 요청 건수 | 인덱싱/검색 건수 | - |
| MongoDB 호출 | INTR_MONGODB_CALL | MongoCommandProtocolASM | MongoDB 명령 실행 건수 | CRUD 오퍼레이션 건수 | - |
3.2 엔지니어 해석 가이드
Interaction 추적 원리:
1. ASM Instrumentation이 외부 라이브러리 호출 감지
2. startService() → 호출 전후 타임스탬프 기록
3. endService() → elapsed = end - start 계산
서비스 메시 (Service Map) 구성:
A Service → B Service: INTR_API_OUTGOING(A) = INTR_API_INCOMING(B)
상관 분석 활용:
분석 1: OUTGOING 증가 + INCOMING 감소
→ 다운스트림 병목
분석 2: DB_CALL 증가 + ELAPSED_TIME 증가
→ Slow Query
분석 3: INTR_API_OUTGOING 높음 + INTR_API_INCOMING 낮음
→ 외부 API 지연
네트워크 계층 구조 추론:
Interaction Counter 기반으로 서비스 의존성 그래프 자동 생성
→ Service Mesh (Istio/Linkerd) 없이도 서비스 토폴로지 가능
4. 메트릭별 연관 분석 가이드
4.1 성능 문제 진단 트리
┌─────────────────────────────────────────────────────────────┐
│ 응답 시간 급증 (P99 > SLA×2) │
└─────────────────────────────────────────────────────────────┘
│
┌───────────────────┼───────────────────┐
│ │ │
┌───▼────┐ ┌───────▼────────┐ ┌────▼───────────┐
│ CPU │ │ Memory │ │ Network │
│ 병목 │ │ 부족 │ │ 지연 │
└───┬────┘ └───────┬────────┘ └────┬───────────┘
│ │ │
HOST_CPU > 90% HOST_MEM > 85% HOST_NET_* 급증
│ │ │
│ ┌─────▼────────┐ │
│ │ Swap 사용 │ │
│ │ (Paging) │ │
│ └─────┬────────┘ │
│ │ │
┌───▼────┐ ┌───────▼────────┐ ┌────▼───────────┐
│ GC │ │ Heap Leak │ │ DB/Redis │
│ 빈도 │ │ (Old Gen↑) │ │ Slow Query │
└─────────┘ └────────────────┘ └────────────────┘
4.2 메트릭 연관 매트릭스
| 원인 징후 | 1차 지표 | 2차 확인 지표 | 판단 근거 |
|---|---|---|---|
| CPU 병목 | HOST_CPU > 90% | HOST_SYSCPU ↑ | I/O 대기로 시스템 CPU 증가 |
| 메모리 부족 | HOST_MEM > 85% | HOST_SWAP_USED ↑ | 스와핑 시작 |
| 메모리 누수 | JAVA_HEAP_PERCENT ↑ | OLD_GEN 계속 증가 | GC 후 감소하지 않음 |
| GC 과도 | JAVA_GC_COUNT ↑ | JAVA_GC_TIME ↑ | STW 비율 > 5% |
| 스레드 고갈 | WAS_ACTIVE_SERVICE ↑ | WAS_ELAPSED_TIME ↑ | ThreadPoolSize 도달 |
| DB 병목 | INTR_DB_CALL ↑ | WAS_SQL_TIME ↑ | DB Connection Pool 고갈 |
| 외부 API 지연 | INTR_API_OUTGOING ↑ | WAS_APICALL_TIME ↑ | DOWNSTREAM 서버 응답 지연 |