콘텐츠로 이동
Study Note관측

10. 첫 대시보드 — 공식 앱의 질문을 화면으로 남기기

결론부터
Explore에서 실제 답을 확인한 공식 example query만 대시보드 패널로 승격한다
이 장에서 처음 나오는 말2개
panel패널
대시보드 안에서 query 하나와 그 결과를 보여 주는 단위. 질문 하나만 맡긴다.
visualization시각화
query 결과를 time series · stat · logs처럼 보여 주는 모양. 데이터의 뜻에 맞춰 고른다.

9장에서는 공식 rolldice의 무작위 오류를 Explore에서 따라갔다. 이번에는 반복해서 볼 가치가 있는 질문 넷만 Rolldice Lab dashboard로 남긴다.

패널답할 질문데이터소스 · 모양
요청량traffic이 계속 들어오는가Prometheus · Time series
500 비율요청 중 얼마가 실패하는가Prometheus · Time series
p95 지연느린 요청이 얼마나 느린가Prometheus · Time series
최근 오류 로그500일 때 무슨 문장이 남았나Loki · Logs

8~9장의 kind 클러스터, 공식 Java example, traffic generator를 그대로 사용한다. port-forward를 닫았다면 docker-otel-lgtm 디렉터리에서 다시 연다.

터미널 창
kubectl get pod,service
kubectl port-forward service/lgtm \
3000:3000 3200:3200 4040:4040 4317:4317 4318:4318 9090:9090

http://127.0.0.1:3000을 열어 admin / admin으로 로그인하고 시간 범위를 Last 5 minutes로 맞춘다. request rate가 비어 있다면 공식 generate-traffic.sh도 다시 실행한다.

  1. 왼쪽 메뉴에서 Dashboards를 열고 New → New dashboard를 고른다.

  2. Add visualization을 눌러 첫 panel 편집 화면을 연다.

  3. dashboard 이름을 Rolldice Lab으로 저장한다.

아래 넷을 하나씩 추가하면서 query → 결과 → 단위 → 제목 순서로 확인한다.

Prometheus와 Time series를 선택하고 공식 example dashboard가 사용하는 metric을 넣는다.

sum(rate(http_server_request_duration_seconds_count{
service_name="rolldice"
}[1m]))

제목은 요청량, Unit은 requests/sec로 정한다. traffic이 살아 있는지 확인하는 입구다.

두 번째 Prometheus Time series에는 다음 query를 넣는다.

sum(rate(http_server_request_duration_seconds_count{
service_name="rolldice", http_response_status_code=~"5.."
}[1m]))
/
sum(rate(http_server_request_duration_seconds_count{
service_name="rolldice"
}[1m]))

제목은 500 비율, Unit은 Percent (0.0-1.0)로 정하고 threshold는 20%부터 빨강으로 둔다. 공식 코드의 오류 확률은 약 30%지만 짧은 이동창에서는 값이 계속 흔들린다.

세 번째 Prometheus Time series에는 공식 dashboard의 latency query를 짧은 이동창으로 넣는다.

histogram_quantile(0.95,
sum by (le, http_route) (
rate(http_server_request_duration_seconds_bucket{
service_name="rolldice"
}[1m])
)
)

제목은 p95 지연, Unit은 seconds로 정한다. 앱의 random sleep 때문에 선이 평평하지 않아야 한다.

네 번째 panel은 Loki와 Logs를 고르고 9장에서 확인한 query를 그대로 쓴다.

{service_name="rolldice"} |= "simulating an error"

제목은 최근 rolldice 오류로 정한다. 로그 상세에서 trace_id의 Trace 링크가 Tempo를 여는지도 다시 확인한다.

무작위 오류를 한 화면에서 읽기

섹션 제목: “무작위 오류를 한 화면에서 읽기”

dashboard를 저장하고 traffic을 계속 흘리면서 다음 순서로 본다.

  1. 요청량이 0보다 큰지 본다 — example과 traffic generator가 살아 있다는 확인이다.

  2. 500 비율이 0과 1 사이에서 흔들리고 p95도 함께 변하는지 본다.

  3. 최근 오류 로그에서 simulating an error를 연다.

  4. Trace 링크로 Tempo에 넘어가 같은 요청의 GET /rolldice error span을 확인한다.

이 화면은 traffic · 오류율 · 지연 · 최근 오류 문장까지 답한다. 오류 하나를 깊이 따라갈 때는 panel query를 늘리지 않고 Explore로 넘어간다.

UI에서 만든 dashboard는 공식 LGTM Pod의 emptyDir 안에만 있다. Grafana에서 Export → Export as code를 열어 query·layout·unit이 들어간 JSON을 확인한다.

증상확인
panel 전체가 No dataLast 5 minutes, 공식 app, traffic generator 세 가지 확인
Prometheus panel만 비어 있음9장 Explore에서 같은 PromQL이 결과를 내는지 먼저 확인
500 비율만 비어 있음label browser에서 status label 이름과 500 값 확인
Loki panel만 비어 있음{service_name="rolldice"}로 넓히고 실제 오류 문장 확인
500 비율이 너무 작게 보임Unit이 Percent (0.0-1.0)인지 확인
로그의 Trace 링크가 없음로그 상세의 trace_id와 공식 LGTM 데이터소스 설정 확인
다시 접속하니 dashboard가 없음LGTM Pod나 kind 클러스터를 다시 만들었는지 확인 — 공식 샘플은 비영속

다음 단계 — 운영 구성과 내 앱 계측

섹션 제목: “다음 단계 — 운영 구성과 내 앱 계측”

공식 sample을 키우는 일은 여기서 끝낸다. 단일 Pod YAML에 PVC·인증·복제본을 덧붙여 운영 구성으로 키우지 않는다. 온프렘에서는 제품별 공식 Helm chart를 쓰는 별도 경로로 넘어가고, 레포에는 공식 chart가 렌더한 manifest 대신 환경별 values와 검증 절차만 관리한다.

운영 도입 체크리스트는 kube-prometheus-stack → 알림 → Loki·Alloy → Grafana 연결 → Tempo 순서와 완료 조건을 정리한다. 배치와 저장소 판단은 온프렘 관측에서 이어서 본다.

그 전에 실습이 하나 남았다 — 지금까지는 계측이 끝난 공식 앱의 신호를 소비했고, 11장에서는 자체 앱에 계측을 직접 붙여 같은 스택에 연결한다.

11장은 이 kind 클러스터와 터미널 A의 port-forward를 그대로 사용한다. 다만 자체 앱이 같은 8080 포트를 쓰므로 Java example과 traffic generator(터미널 B·C)는 Ctrl+C로 끝낸다.

여기서 실습을 끝낸다면 세 터미널을 모두 정리한 뒤 전용 클러스터만 삭제한다.

터미널 창
kind delete cluster --name observability-lab

LGTM의 dashboard·metric·log·trace가 emptyDir와 함께 사라진다. checkout한 공식 저장소는 다음 실습에 쓸 수 있으므로 자동으로 삭제하지 않는다.