본문 바로가기
C.W.K.
Stream
Lesson 07 of 10 · published

모니터링 — 봐야 할 것

~12 min · monitoring, production

Level 0Scout
0 XP0/80 lessons0/10 achievements
0/120 XP to next level120 XP to go0% complete

뭔가 잘못됐다고 알려주는 숫자

SQLite는 조용해. 데몬도 없고 metric을 뱉는 endpoint도 없어. 관측 장치는 애플리케이션 쪽에서 직접 만들어야 해. 지켜볼 값어치가 있는 신호는 여섯이야.

  • DB 파일 크기 — 갑자기 불어나거나, 멈춰 있거나, 줄어드는 것 전부 뭔가를 뜻해.
  • WAL 파일 크기 — WAL이 크다는 건 checkpointer가 못 따라간다는 뜻이야. reader가 write를 붙들고 있을 수도 있고.
  • Query 지연 — store class를 감싸서 모든 query 시간을 재고 metric 저장소로 보내.
  • SQLITE_BUSY 횟수 — 이게 보이면 busy_timeout이 너무 짧거나 transaction이 너무 길다는 신호야.
  • integrity check 결과 — 주기적으로 돌리고 실패하면 알림을 띄워.
  • 남은 디스크 — VACUUM에도 백업에도 여유 공간이 필요해. 모자라면 곤란해져.
Self-reference: 피파의 /api/health endpoint가 SQLite 크기와 JSONL 크기, 마지막으로 쓴 시각, integrity check 상태를 보고해. WebUI에는 초록·노랑·빨강 점 하나로 뜨고. 아빠가 한눈에 데이터 레이어가 건강한지 보라고.

Code

가벼운 health-check endpoint·python
import os, time
from fastapi import APIRouter, Request

router = APIRouter()

@router.get('/api/health/db')
async def db_health(request: Request):
    conn = request.app.state.store.conn
    db_path = 'myapp.db'
    started = time.perf_counter()
    n = (await (await conn.execute('SELECT count(*) AS n FROM messages')).fetchone())['n']
    elapsed_ms = (time.perf_counter() - started) * 1000
    return {
        'rows': n,
        'count_ms': round(elapsed_ms, 2),
        'db_size_bytes': os.path.getsize(db_path),
        'wal_size_bytes': (
            os.path.getsize(db_path + '-wal') if os.path.exists(db_path + '-wal') else 0
        ),
    }

External links

Exercise

네 서비스 하나에 health endpoint를 붙여봐. DB 크기, WAL 크기, 핵심 테이블의 row 수, 그리고 그걸 재는 데 걸린 시간을 돌려주면 돼. 1분에 한 번씩 찔러서 며칠 치 값을 모아 그래프로 그려. 눈에 띄는 패턴을 적고, 그게 진짜 문제를 뜻하는지 따져봐.

Progress

Progress is local-only — sign in to sync across devices.
이 페이지에서 버그를 발견하셨거나 피드백이 있으세요?문제 신고

댓글 0

🔔 답글 알림 (로그인 필요)
로그인댓글을 남기려면 로그인해 주세요.

아직 댓글이 없어요. 첫 댓글을 남겨보세요.