Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions docs/test-results/evidence/issue-457/grafana-applied.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
# fix457-grafana-01 — 실제 대시보드 적용·과거 화면 확인

- 기록 시각: 2026-10-10 02:12 KST. 실행 당시 정확한 API 호출 시각은 별도로 수집하지 못했다.
- 목적·위치: 인증된 GCP 관측 VM의 Grafana. 비밀은 기존 컨테이너 내부 파일에서만 읽고 출력·파일·Git에 기록하지 않았다.
- 방법: 현재 패널 ID·제목·PromQL을 머지된 기준 JSON과 비교, Dashboard API로 갱신, Annotation API로 기존 실행의 검증된 시작·복구 시각 2건 등록, GET API와 브라우저 화면으로 재조회.
- 성공 기준: 기존 패널 보존, 새 누적 그래프·결과 불명 카드 표시, 정확한 표식 2건, 기존 실행 5xx 1건.
- 결과: 기준 대시보드 **v8/18패널**과 저장소 기준 패널 ID·제목·PromQL 일치. 적용 후 **v9/20패널**, annotation **2건** 저장. `ha1009163528`의 절대 시간 범위에서 카드 **2xx 3,599·3xx 0·4xx 0·5xx 1·결과 불명 0건**, HTTP 500 누적 **0→1 계단**, OpenProxy A 포트 불가 구간과 시작·복구 세로선 확인.
- 표식 원본: 2026-10-10 **01:38:39.554 KST**(종료 명령 반환·포트 불응 확인), **01:39:16.246 KST**(프로세스 1·포트 준비 확인). API 재조회에서 동일한 두 시각과 실행 ID 태그 확인.
- 한계: UI 화면은 요청 ID의 DB 최종 상태를 증명하지 않는다. Annotation 레코드는 Grafana DB에 있고 Dashboard JSON에는 포함되지 않는다.
8 changes: 8 additions & 0 deletions docs/test-results/evidence/issue-457/live-query.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
# fix457-live-query-01 — 기존 실행의 Prometheus 쿼리 재측정

- 기록 시각: 2026-10-10 02:12 KST. 실행 당시 정확한 조회 시작 시각은 수집하지 못했다.
- 목적·위치: GCP 관측 VM 내부 Docker 네트워크의 Prometheus에서 기존 `ha1009163528` 시계열을 읽기 전용 조회. 새 k6·장애 실행은 하지 않았다.
- 방법: Prometheus `/api/v1/query_range`에서 원시 `k6_ha_outcome_500_total`과 새 `sum(last_over_time(...[10m])) or VU*0` 쿼리를 절대 시간 범위로 조회. 주소·인증값은 기록하지 않았다.
- 성공 기준: 500 누적값이 첫 오류 전 0, 첫 Counter 수신 이후 1이고 이후 유지.
- 결과: 원시 500 Counter는 **11개 표본**이 저장됐고 모두 값 1. 첫 표본은 **2026-10-10 01:38:40 KST**. 새 쿼리는 5초 간격 조회에서 **01:38:20~35의 0 → 01:38:40~55의 1**을 반환했다.
- 해석: 이전 그래프가 희미했던 이유를 “원시 표본이 한 개뿐”으로 단정할 수 없다. 첫 표본이 이미 1이므로 `rate()`는 그 이전 증가를 계산하지 못한다. 조회 해상도와 Remote Write 주기로 오류 완료 시각과 최대 수초 차이 날 수 있다.
8 changes: 8 additions & 0 deletions docs/test-results/evidence/issue-457/promql-attempt-01.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
# fix457-promql-attempt-01 — 합성 Fixture 첫 시도

- 기록 시각: 2026-10-10 02:12 KST. 실행 당시 ID와 정확한 시각을 사전 기록하지 못해 이 ID는 사후 부여했다.
- 목적·위치: 로컬 Docker의 기존 `prom/prometheus:v3.5.5` 이미지에서 `promtool test rules`로 단발 오류 쿼리를 검증.
- 명령: `promtool test rules monitoring/grafana/tests/ha_dashboard_http_classes.yml` (읽기 전용 마운트 컨테이너).
- 기대: 합성 Counter 한 표본을 새 쿼리가 1로 유지.
- 결과: **실패 2건**. `rSparse` 500·결과 불명 기대 1에 대해 실제 0. 나머지 기존 테스트는 실패로 보고되지 않았다.
- 다음 조치: 표본 평가 시각이 맞는지 별도 재시험. 이 단계에서는 제품 쿼리 오류인지 Fixture 문제인지 확정하지 않았다.
8 changes: 8 additions & 0 deletions docs/test-results/evidence/issue-457/promql-attempt-02.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
# fix457-promql-attempt-02 — 합성 평가 시각 조정

- 기록 시각: 2026-10-10 02:12 KST. 실행 당시 ID와 정확한 시각을 사전 기록하지 못해 이 ID는 사후 부여했다.
- 목적·위치: 로컬 Docker Prometheus v3.5.5에서 합성 표본의 평가 시각을 500=10초·결과 불명=20초로 맞춤.
- 명령: `promtool test rules monitoring/grafana/tests/ha_dashboard_http_classes.yml` (읽기 전용 마운트 컨테이너).
- 기대: 시각을 맞추면 두 Counter가 1로 평가.
- 결과: **실패 2건**. 두 기대값 모두 여전히 실제 0.
- 다음 조치: 누적 계산 이전의 원시 시계열 존재 여부를 직접 테스트.
8 changes: 8 additions & 0 deletions docs/test-results/evidence/issue-457/promql-attempt-03.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
# fix457-promql-attempt-03 — 원시 시계열 확인

- 기록 시각: 2026-10-10 02:12 KST. 실행 당시 ID와 정확한 시각을 사전 기록하지 못해 이 ID는 사후 부여했다.
- 목적·위치: 로컬 Docker Prometheus v3.5.5에서 `rSparse` 원시 500 Counter 자체를 조회.
- 명령: `promtool test rules monitoring/grafana/tests/ha_dashboard_http_classes.yml` (원시 Counter 기대값을 추가한 Fixture).
- 기대: 원시 Counter 1, 누적 500 1, 누적 결과 불명 1.
- 결과: **실패 3건**. 원시 Counter 결과가 `nil`이고 두 누적 쿼리가 0. 맨 앞을 누락 표본(`_`)으로 둔 이 Fixture는 이 실행에서 원시 시계열을 만들지 못했다.
- 다음 조치: 한 표본을 Fixture 시작 시각에 두고, 이후에는 표본을 생략해 `rate()`와 `last_over_time()` 차이를 확인.
9 changes: 9 additions & 0 deletions docs/test-results/evidence/issue-457/promql-final.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
# fix457-promql-final — 희소 Counter 최종 합성 검증

- 기록 시각: 2026-10-10 02:12 KST. 실행 전 이 ID와 성공 기준을 선언했다.
- 목적·위치: 로컬 Docker의 기존 `prom/prometheus:v3.5.5` 이미지, 실행 후 컨테이너 자동 제거.
- 명령: `promtool test rules monitoring/grafana/tests/ha_dashboard_http_classes.yml` (저장소 파일을 읽기 전용 마운트).
- 입력: `rSparse`에 VU 연속 표본, HTTP 500 Counter 1표본, 결과 불명 Counter 1표본. 다른 시험 그룹은 403 전용·201 전용·미존재 실행.
- 성공 기준: 500·결과 불명 누적값 1, 500의 `rate(...[15s])` 결과 없음, 기존 0 대체 기대값 유지.
- 결과: **SUCCESS**. PromQL 기대값 총 12개 통과, 컨테이너 회수.
- 한계: 시작 시각에 한 표본을 둔 합성 입력이다. 실제 장애 실행의 0→1 계단은 별도 GCP 과거 데이터 조회로 검증했다.
8 changes: 8 additions & 0 deletions docs/test-results/evidence/issue-457/static-final.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
# fix457-static-final — 로컬 대시보드 정적 검증

- 기록 시각: 2026-10-10 02:12 KST. 실행 직전 식별자를 선언했으며 명령별 초 단위 시각은 별도로 수집하지 않았다.
- 목적·위치: 분리된 로컬 `fix/457` 작업 공간에서 JSON, 패널 겹침, 쿼리·데이터소스 경계를 확인.
- 명령: `python3 -m unittest monitoring.grafana.tests.test_ha_dashboard -v`; `python3 -m json.tool monitoring/grafana/dashboards/docgrid-ha-demo.json`; `git diff --check`.
- 성공 기준: Python 12/12, JSON 파싱, diff 공백 검사 모두 통과.
- 결과: Python **12/12 통과**(0.002초), JSON 유효, `git diff --check` 오류 0건.
- 한계: 정적 검사는 실제 Grafana 화면·Prometheus 과거 시계열을 증명하지 않는다. 별도 실행에서 확인했다.
31 changes: 31 additions & 0 deletions docs/test-results/opensql-ha-dashboard-sparse-failure-20261010.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
# OpenSQL HA 대시보드 단발 오류·장애 시각 표시 검증

- 기록 시각: 2026-10-10 02:12 KST. 일부 진단 재시도의 정확한 시작 시각은 수집하지 못해 아래 실행별 로그에 그 한계를 적었다.
- 변경 범위: Grafana 시연 Dashboard JSON·설명·정적/PromQL 회귀 시험. 백엔드 코드, DB, OpenProxy, k6 부하 스크립트는 변경하지 않았다.
- 기존 원본 실행: `ha1009163528` (30 req/s × 120초, HTTP 201 3,599건·500 1건·결과 불명 0건). 이 문서 작업 중 새 장애나 부하를 실행하지 않았다. 원래 요청 ID 원장과 DB 대조 원본은 비공개 보관하며 이 PR에 복사하지 않는다.

## 변경 전후와 판정

| 항목 | 이전 | 변경 후 실제 확인 | 해석·한계 |
|---|---|---|---|
| 500 표시 | `rate(...[30s])` 결과별 응답/초에 포함 | `last_over_time(...[10m])` 누적 계단에서 기존 실행의 **0→1건** | 실제 첫 Counter 표본은 이미 1이었다. 장애 명령 반환 시각과 그래프 시각은 Remote Write 전송 주기 때문에 다를 수 있다. |
| 결과 불명 | 누적 카드 없음 | 별도 카드 **0건** | `HTTP 2xx~5xx` 카드와 분리. DB 반영 여부를 뜻하지 않는다. |
| 성공 처리율 | 30초 이동 창 | 15초 이동 창 | 더 짧은 관측 창이며 정확한 장애 RTO가 아니다. |
| 앱 5xx | 초당 비율·30초 창 | 15초 증가량 패널 | Prometheus 보간값이라 정확한 1건과 숫자가 같지 않을 수 있다. LB 자체 오류는 빠질 수 있다. |
| 장애 시각 | built-in annotation 조회만 설정 | 원본 기록의 시작·복구 시각 **2건**을 Grafana DB에 기록, 과거 화면에서 세로선 확인 | JSON만 다른 Grafana에 가져오면 이 두 레코드는 함께 복사되지 않는다. |

### 별도 실행 기록

| 실행 ID | 목적·위치 | 결과 | 기록 |
|---|---|---|---|
| `fix457-static-final` | 로컬 JSON/배치/정적 단위 시험 | 12/12 통과, JSON 유효, diff 오류 없음 | [정적 검증](evidence/issue-457/static-final.md) |
| `fix457-promql-attempt-01` | 로컬 Docker 희소 표본 첫 합성 시험 | 2개 기대값 실패 | [1차 진단](evidence/issue-457/promql-attempt-01.md) |
| `fix457-promql-attempt-02` | 평가 시각 조정 재시험 | 2개 기대값 실패 | [2차 진단](evidence/issue-457/promql-attempt-02.md) |
| `fix457-promql-attempt-03` | 원시 입력 시계열 추가 확인 | 3개 기대값 실패 | [3차 진단](evidence/issue-457/promql-attempt-03.md) |
| `fix457-promql-final` | 합성 Counter 한 표본·0 대체·`rate()` 한계 | 최종 12개 PromQL 기대값 통과 | [최종 PromQL](evidence/issue-457/promql-final.md) |
| `fix457-live-query-01` | GCP 관측 VM 내부 Prometheus 과거 실행 읽기 | 원시 500 표본 11개; 새 쿼리 0→1 | [실측 쿼리](evidence/issue-457/live-query.md) |
| `fix457-grafana-01` | 인증된 Grafana 적용·과거 화면 조회 | Dashboard v8→v9, 20패널, annotation 2건, 카드 3,599/0/0/1/0 | [화면 확인](evidence/issue-457/grafana-applied.md) |

초기 PromQL 실패 3회는 제품 장애가 아니다. 합성 Fixture의 맨 앞 누락 표본(`_`)만으로는 이 `promtool` 실행에서 늦게 시작하는 원시 시계열을 만들지 못했다. 세 번째 실행에서 원시 시계열 자체가 없음을 확인하고, 한 표본을 시작 시각에 두는 Fixture로 바꿨다. 이 입력에서는 `rate()`가 값을 내지 못하지만 새 누적 쿼리는 1을 유지한다. 실제 GCP 과거 시계열에서도 새 쿼리의 0→1 변화는 별도로 확인했다.

장애 표식의 원본 시간은 2026-10-10 **01:38:39.554 KST**(종료 명령 반환·포트 불응 확인)와 **01:39:16.246 KST**(프로세스 1·포트 준비 확인)이다. 이 둘의 차이를 앱 쓰기 공백이나 RTO로 부르지 않는다. Grafana annotation 레코드는 서버 DB에 있으며 Dashboard JSON에는 조회 설정만 들어간다. DB 요청 ID 대조는 이번 수정에서 재실행하지 않았으므로 Grafana 그래프만으로 RPO를 주장하지 않는다.
17 changes: 13 additions & 4 deletions monitoring/grafana/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -40,19 +40,28 @@ Git에서 다음 파일을 수정한다.
`dashboards/docgrid-ha-demo.json`은 별도 GCP 관측 VM에서 사용하는 수동 가져오기용 Dashboard다.
번들 Data Source가 아니라 인증된 관측 VM의 Prometheus UID `ha-prometheus`를 요구한다. 앱 A/B,
Patroni 3노드의 수집·역할 상태와 관측 VM에서 본 OpenProxy A/B TCP 포트 연결을 타임라인으로 표시하고,
현재 primary·timeline·연결 가능한 프록시 포트 수, 실행 ID별 HTTP 2xx·3xx·4xx·5xx 누적 응답 건수, 앱별 5xx,
Hikari 대기·연결 timeout, standby WAL 수신·재생 차이, k6 결과별 응답/초와 활성 VU를 보여준다.
현재 primary·timeline·연결 가능한 프록시 포트 수, 실행 ID별 HTTP 2xx·3xx·4xx·5xx와 결과 불명 누적 건수,
앱별 최근 15초 5xx 증가량, Hikari 대기·연결 timeout, standby WAL 수신·재생 차이,
k6 HTTP 201 응답/초·실패 누적 계단과 활성 VU를 보여준다.
`run_id` 변수는 k6 VU 지표에서 읽어 201 응답이 0건인 실행도 선택할 수 있게 한다. 각 코드 대역 카드에
해당 응답이 없더라도 선택한 실행의 VU 지표가 수집됐다면 0건으로 표시한다. `All`이면 최근 10분 이내
여러 실행의 건수가 합산될 수 있으므로 영상에서는 특정 실행 ID를 선택한다. 새 실행 ID가 자동 새로고침만으로
목록에 나타나는지는 검증되지 않았으므로 촬영 전 목록을 다시 열어 확인한다. 코드 대역 카드에는 응답이 오지 않은
결과 불명 요청이 포함되지 않으며, 이 건수는 아래 결과별 응답/초 그래프와 안전 원장에서 별도로 확인한다.
결과 불명 요청이 포함되지 않으므로 별도 결과 불명 카드와 안전 원장에서 확인한다.

HTTP 201 응답/초는 15초 이동 평균이다. 500·503·기타 예상 외 응답·결과 불명은
`last_over_time(...[10m])`으로 마지막 Counter 표본을 유지하는 누적 계단으로 따로 그린다.
첫 오류 표본이 이미 1이면 `rate()`는 그 이전 0→1 사건을 계산하지 못할 수 있다.
계단의 시각은 k6 Remote Write 전송 주기만큼 실제 응답 완료보다 늦을 수 있고,
10분 뒤에는 값이 화면에서 사라질 수 있다. 오래된 실행은 실행 ID와 절대 시간 범위를 함께 선택한다.
앱별 5xx `increase(...[15s])`는 Prometheus의 보간값이므로 정확한 총 건수처럼 읽지 않는다.

이 화면의 `up=1`은 지표 수집 성공일 뿐 HTTP 쓰기 성공이 아니며, `up=0`만으로 VM 중단을
확정하지 않는다. 앱별 5xx는 LB가 직접 반환한 오류를 포함하지 않을 수 있다. OpenProxy 포트 연결은
관측 VM에서 Blackbox Exporter의 TCP probe로 확인하며 SQL 성공을 보장하지 않는다. 앱→프록시 연결 경로는
현재 Prometheus에 직접 수집하지 않으므로 운영자 장애 로그와 HTTP 원장을
함께 본다. 장애 주입·복구 annotation은 설정만 있으며 실제 이벤트를 기록해야 화면에 나타난다. 그래프만으로
함께 본다. 장애 주입·복구 annotation은 Grafana DB에 해당 실행의 검증된 시각을 기록해야 화면에 나타난다.
Dashboard JSON만 다른 Grafana로 가져와도 과거 annotation 레코드는 복사되지 않는다. 그래프만으로
성공 응답 데이터의 보존이나 RPO를 주장하지 않으며 요청 ID별 DB 대조 결과를 별도로 확인한다.
Remote Write의 누적 Trend p95/p99는 복구 시점 지연으로 오해하기 쉬워 패널에서 제외했다.
실행·장애 계측 결과는 [GCP HA 대시보드 검증 기록](../../docs/test-results/opensql-ha-live-dashboard-fault-rehearsal-20261009.md)에 둔다.
Expand Down
Loading
Loading