Skip to content

Cloudflare 기반 커스텀 대시보드 구현 가이드

목적: D1·Analytics Engine 데이터를 활용한 SaaS 관리자용 대시보드 설계 및 구현. Grafana 없이 Control Plane Worker + 정적 페이지(Chart.js)로 §16.4 행 구성을 구현.
참조: cloudflare-based-monitoring-plan.md §2.3, api-control-plane-implementation-plan.md §16.4.


1. 데이터 소스

소스내용대시보드 활용
D1tenants_master, provision_jobs, nodes테넌트 수·상태·지역/플랜별 집계, 큐 깊이(Pending), 프로비저닝 성공률, 노드 현황.
Analytics Engineapi_request, job_created, provision_complete(Phase 2) 테넌트별 RPS·에러율·지연. 쿼리 API 연동 후 Worker에서 집계해 JSON 제공.

1단계: D1만 사용한 메트릭 API로 Row 1·2·4 구현.
2단계: Analytics Engine SQL API를 Worker에서 호출해 Row 3 Edge Performance 추가. Control Plane에 CF_ANALYTICS_READ_TOKEN(Account Analytics Read), CF_ACCOUNT_ID 설정 시 GET /internal/metrics/summary 응답에 edge: { requests_1h, avg_duration_ms_1h, errors_5xx_1h } 포함. cloudflare-analytics-engine-implementation.md §5.


2. 메트릭 API (Control Plane Worker)

엔드포인트: GET /internal/metrics/summary
인증: Authorization: Bearer <INTERNAL_API_KEY>
응답: JSON. 대시보드가 이 형태로 차트 데이터를 소비.

2.1 응답 스키마 (예시)

{
"tenants": {
"total": 42,
"active": 38,
"pending": 2,
"pending_deletion": 1,
"by_region": { "sg": 20, "us": 12, "eu": 10 },
"by_plan": { "basic": 25, "professional": 12, "enterprise": 5 }
},
"provisioning": {
"queue_depth": 3,
"success_count_24h": 5,
"failed_count_24h": 0,
"success_rate_24h": 100,
"recent_jobs": [
{ "job_id": "...", "tenant_id": "...", "status": "Completed", "created_at": "...", "updated_at": "..." }
]
},
"nodes": {
"total": 6,
"by_region": { "sg": 2, "us": 2, "eu": 2 },
"by_status": { "Active": 6 },
"server_metrics": [{"node_id":"node-01","cpu_pct":12.5,"memory_pct":45,"disk_pct":60,"tenant_count":3,"updated_at":"..."}]
},
"updated_at": "2025-02-23T12:00:00Z"
}
  • nodes.server_metrics: D1 migration 0007 적용 후, 노드에서 POST /internal/server-metrics 푸시 시 채워짐. server-metrics-collection.md.
### 2.2 D1 쿼리 (구현 참고)
- **tenants**: `SELECT status, region, plan_tier, COUNT(*) FROM tenants_master GROUP BY status`; 별도로 `GROUP BY region`, `GROUP BY plan_tier`.
- **queue_depth**: `SELECT COUNT(*) FROM provision_jobs WHERE status = 'Pending'`.
- **success_rate_24h**: `SELECT status, COUNT(*) FROM provision_jobs WHERE created_at >= datetime('now', '-1 day') GROUP BY status` → Completed/(Completed+Failed)*100.
- **recent_jobs**: `SELECT job_id, tenant_id, status, created_at, updated_at FROM provision_jobs ORDER BY created_at DESC LIMIT 20`.
- **nodes**: `SELECT region, status, COUNT(*) FROM nodes GROUP BY region, status`.
---
## 3. 대시보드 UI 구조 (§16.4 정렬)
| Row | 제목 | 데이터 | 비고 |
|-----|------|--------|------|
| **Row 1** | Business Overview | tenants.total, tenants.active, tenants.by_plan | Single Stat 또는 작은 막대 차트. |
| **Row 2** | Provisioning Pipeline | provisioning.queue_depth, success_rate_24h, recent_jobs | 큐 깊이 숫자, 성공률 %, 최근 작업 테이블. |
| **Row 3** | Edge Performance (1h) | Analytics Engine SQL API (Phase 2) | requests_1h, avg_duration_ms_1h, errors_5xx_1h. Secrets 설정 시 표시. |
| **Row 4** | Infrastructure (Nodes) | nodes.by_region, nodes.by_status | 지역별·상태별 노드 수. |
### 3.1 UI 구현 옵션
- **A. 정적 HTML + Chart.js**: 한 HTML 파일에서 `fetch(Control Plane URL + '/internal/metrics/summary', { headers: { Authorization: 'Bearer ...' } })` 후 JSON으로 Chart.js 렌더링. Cloudflare Pages 또는 별도 호스팅.
- **B. Worker에서 HTML 서빙**: 동일 Worker에 `GET /internal/dashboard` 라우트 추가, HTML 반환(인라인 스크립트로 fetch `/internal/metrics/summary` 호출). 대시보드 URL 하나로 제공.
- **C. 기존 관리자 앱 통합**: prego-saas-app 등 관리자 화면에 `/admin/metrics` 페이지 추가, 동일 메트릭 API 소비.
**구현**: **B** 적용. `GET /internal/dashboard`로 HTML 서빙. 페이지에서 Internal API Key 입력 후 `/internal/metrics/summary` 호출·Chart.js로 Row 1·2·4 렌더링.
---
## 4. 구현 체크리스트
### 백엔드 (prego-control-plane)
- [x] `GET /internal/metrics/summary` 핸들러 추가. D1 쿼리로 tenants·provisioning·nodes 집계. (`internal.handleMetricsSummary`, `index.ts` 라우트 등록)
- [ ] (선택) 캐시: 동일 요청 1분 내 반복 시 KV 또는 in-memory 캐시로 응답 속도 개선.
### 프론트엔드
- [x] 메트릭 API 호출(Authorization 헤더). `GET /internal/dashboard` HTML에서 동일 오리진 fetch.
- [x] Row 1–2–4용 차트/테이블 (Chart.js). prego-control-plane `src/dashboard-html.ts`·`GET /internal/dashboard`. Row 3는 Analytics Engine 연동 후 추가.
- [x] 갱신: "Refresh" 버튼. API Key는 sessionStorage에 저장 후 재요청 시 사용.
### 보안
- [ ] `/internal/metrics/summary` 및 `/internal/dashboard`는 INTERNAL_API_KEY 또는 Cloudflare Access로만 접근.
- [ ] API Key·대시보드 URL은 Runbook·Secrets에만 기록.
---
## 5. 관련 문서
- [cloudflare-based-monitoring-plan.md](/planning/cloudflare-based-monitoring-plan/) §2.3, §4.
- [api-control-plane-implementation-plan.md](/planning/api-control-plane-implementation-plan/) §16.4 (레이아웃), §17 (Status Page와 구분).
- [cloudflare-analytics-engine-implementation.md](/planning/cloudflare-analytics-engine-implementation/) — Analytics Engine 데이터는 Phase 2에서 쿼리 API로 대시보드에 연동.
Help