본문으로 건너뛰기

Monitoring (Grafana LGTM)

multi-saas-kit의 공식 통합 모니터링 플랫폼입니다. 모든 프로젝트(Laravel)와 플랫폼 서비스(_services/)의 로그·메트릭·알림을 단일 Grafana 인터페이스에서 관리합니다.

개요

항목내용
위치workspace/_devtools/monitoring
스택Grafana + Loki + Prometheus + Promtail
포트7060 (로컬)
권장 도메인monitor.devtools.{platform-domain}
설계 문서ADR-017 (Monitoring Stack Grafana LGTM)

왜 중요한가

운영 중인 플랫폼에서 **"지금 무슨 일이 일어나고 있는지"**를 즉시 답할 수 있어야 장애를 빨리 감지하고, 고객 문의에 근거로 답하며, 비용/사용량을 추적할 수 있습니다. 모니터링은 인프라의 필수 구성요소이지 선택 사항이 아닙니다.

multi-saas-kit은 멀티테넌트 SaaS 플랫폼이라 다음이 특히 중요합니다:

  • 여러 고객 프로젝트의 로그가 한 화면에서 조회되지만 격리되어 있어야 함
  • 에러 스파이크가 자동으로 감지되어 Slack/Email 알림
  • 서비스 버전/배포 이력이 대시보드에서 추적 가능
  • AI 점검 시스템이 프로그래밍 방식으로 로그/메트릭 쿼리 가능

Grafana LGTM 스택은 이 모든 것을 OSS 기반으로 충족합니다.

스택 구성

컴포넌트

컴포넌트역할내부 포트
Grafana대시보드, Explore UI, 알림 관리, 사용자 인증3000
Loki로그 저장소. Prometheus 스타일 레이블 기반3100
Prometheus메트릭 시계열 DB. /metrics 엔드포인트 pull9090
Promtail로그 수집 agent. journald + 파일 + Docker 지원9080
(선택) Tempo분산 트레이싱 저장소3200
(선택) Alertmanager고급 알림 라우팅9093

데이터 흐름

[관측 대상] ──► [수집] ──► [저장] ──► [조회/알림]

Laravel storage/logs/*.log ─┐
systemd journal (Go 서비스) ─┼─► Promtail ─► Loki ──┐
Docker containers stdout ─┘ │
├─► Grafana
/metrics endpoints ──────────► Prometheus ──────────┘ │

(Slack / Email /
Report files)

시작하기

로컬 개발

make up NAME=_devtools/monitoring

접속:

  • 로컬: http://localhost:7060
  • 기본 계정: admin / .envGRAFANA_ADMIN_PASSWORD

운영 (기존 도메인 구조 기반)

루트 .envPLATFORM_DEVTOOLS_URL이 설정되어 있다면 자동으로 monitor.{platform-domain} 또는 monitor.devtools.{platform-domain}으로 접근 가능합니다.

Nginx Proxy Manager에 다음 Proxy Host 등록:

  • Domain: monitor.devtools.codebase.how
  • Forward: {host}:7060
  • SSL: Let's Encrypt
  • WebSocket Support: ON

설정 파일 구조

workspace/_devtools/monitoring/
├── docker-compose.yml # 4개 서비스
├── .env.example # 환경변수 템플릿
├── Makefile
├── AGENTS.md
└── configs/
├── loki/
│ └── loki-config.yaml # 30일 retention, filesystem storage
├── promtail/
│ └── promtail.yaml # journald + Laravel + Docker scrape
├── prometheus/
│ └── prometheus.yml # scrape targets
└── grafana/
├── provisioning/
│ ├── datasources/
│ │ └── datasources.yaml # Loki + Prometheus 자동 등록
│ └── dashboards/
│ └── dashboards.yaml # JSON 자동 로드
└── dashboards/
├── overview.json
├── services-health.json
├── laravel-projects.json
└── edge-relay.json

수집 대상 설정

Laravel 프로젝트

특별한 설정 변경 없이 동작합니다. Laravel 기본 로그(storage/logs/laravel-*.log)를 Promtail이 tail합니다.

권장: JSON 채널 사용 — config/logging.php:

'stack' => [
'driver' => 'stack',
'channels' => ['json'],
'ignore_exceptions' => false,
],
'json' => [
'driver' => 'daily',
'path' => storage_path('logs/laravel.log'),
'formatter' => Monolog\Formatter\JsonFormatter::class,
'days' => 14,
],

Loki 레이블 자동 부여:

  • project — 프로젝트 이름 (예: apis.how)
  • applaravel
  • envAPP_ENV

_services/ Go 서비스

slog JSON 출력이 systemd journal로 흐르므로 추가 작업 없음. Promtail이 _SYSTEMD_UNIT=edge-relay-service.service 같은 필터로 scrape.

Loki 레이블:

  • service — 서비스 이름 (예: edge-relay-service)
  • runtimego
  • envproduction

Docker 컨테이너 (LiteLLM 등)

Docker daemon 소켓 접근으로 자동 수집:

# promtail.yaml
scrape_configs:
- job_name: docker
docker_sd_configs:
- host: unix:///var/run/docker.sock

메트릭 (/metrics 엔드포인트)

각 서비스의 /metrics를 Prometheus가 주기적으로 pull:

# prometheus.yml
global:
# 저사양 호스트(P330 등)에서 Prometheus 자체 부하를 줄이기 위해 30s 권장.
# 더 짧은 간격이 필요한 잡은 잡별 scrape_interval로 개별 단축 가능.
scrape_interval: 30s
evaluation_interval: 30s

scrape_configs:
- job_name: edge-relay-service
static_configs:
- targets: ['edge-relay.codebase.how:443']
metrics_path: /metrics
scheme: https

- job_name: speech-service
static_configs:
- targets: ['speech.apis.how:443']
metrics_path: /metrics
scheme: https
scrape_interval 선택 가이드
호스트 환경권장 scrape_interval
저사양 자가 호스팅 (4~8코어, 컨테이너 50개+)30s ~ 60s
일반 운영 서버30s (기본값)
알람 정밀도 우선 (특정 잡만)잡별 scrape_interval: 10s 오버라이드

scrape_interval을 절반으로 줄이면 Prometheus가 처리하는 시계열 수가 그만큼 늘어나 CPU/메모리 사용량이 비례 증가합니다. 대시보드 새로고침 주기보다 짧을 필요는 없습니다.

기본 제공 대시보드

1. Overview

  • 전체 서비스 상태 (up/down)
  • 최근 1h 총 요청 수, 에러 수, 평균 지연
  • 활성 프로젝트 수

2. Services Health

  • _services/ 각 서비스 /healthz 결과
  • 버전, 업타임, 최근 재시작
  • 버전과 services-registry.json 일치 여부

3. Laravel Projects

  • 프로젝트별 ERROR/WARN 로그 카운트
  • 최근 에러 메시지 테이블
  • Laravel 응답 지연 분포

4. Edge Relay

  • 모듈별(speech, chorus) 요청 수/지연
  • 세션 검증 성공/실패율
  • 업스트림 지연

5. Logs Explorer

  • 사용자 정의 LogQL 쿼리
  • 레이블 조합으로 빠른 필터링

LogQL 쿼리 예시

Grafana Explore에서 바로 사용 가능:

# 1시간 내 전체 edge-relay 에러
{service="edge-relay-service",level="ERROR"} | json

# 세션 서명 검증 실패만
{service="edge-relay-service"} | json | error_code="signature_mismatch"

# apis.how Laravel 에러 중 chorus 언급
{project="apis.how",app="laravel"} |= "chorus" |= "error"

# 특정 request_id 추적 (여러 서비스 동시)
{service=~"edge-relay-service|chorus-api"} | json | request_id="abc123"

# 5분 window 에러율
sum by (service) (rate({level="ERROR"}[5m]))

알림 설정

알림 엔진은 Grafana Alerting으로 일원화되어 있습니다 (ADR-021). 별도 watcher 데몬 없이 Grafana가 평가·디스패치·UI를 모두 담당합니다.

소스 오브 트루스

규칙은 Grafana 네이티브 Provisioning 포맷으로 Ansible role 안에서 Git 관리:

_services/monitoring/ 폴더와 중간 변환 계층은 [ADR-021]에서 제거되어, 중간 단계 없이 바로 Grafana가 읽는 포맷으로 편집합니다.

동작 흐름

rules.yaml + contact-points.yaml (Git, Grafana 네이티브)
↓ Ansible playbook (scripts/ansible-account.sh self site --tags grafana_lgtm)
/etc/grafana/provisioning/alerting/ (Grafana 서버)
↓ Grafana Alerting
Slack / SMTP / Webhook(파일 리포트)

운영 UI

monitor.devtools.codebase.howAlerting 메뉴에서 현재 상태, 무음, 히스토리 확인·편집. Provisioning으로 관리되는 규칙은 UI 수정 불가(allowUiUpdates: false) — 규칙 변경은 반드시 alert-rules.yaml PR로.

심각도와 채널

severity채널예시
criticalSlack + Email + Report서비스 다운, panic
errorSlack + Report5xx 스파이크
warningSlack (daily digest)지연 증가
infoReport만통계성 이벤트

로그 보존 정책

레이어보존 기간비고
Laravel storage/logs7일 (logrotate)프로젝트별
systemd journal14일 (또는 2GB)journald.conf
Docker logs7일 (100MB per container)daemon.json
Loki (중앙)30일 (기본) / 90일 (중요)loki-config.yaml
Prometheus15일--storage.tsdb.retention.time
장기 S3/R21년+Phase 3

멀티테넌시 (프로젝트 격리)

Loki의 X-Scope-OrgID 헤더로 프로젝트별 격리 가능합니다. Grafana 데이터소스를 프로젝트별로 분리 설정하면 각 고객은 자기 프로젝트 로그만 조회.

현재: 단일 조직, 운영자만 접근. 고객 직접 접근은 Phase 3 (Laravel SSO 연동).

보안

항목정책
Grafana 외부 접근NPM + SSL 필수
Loki/PrometheusDocker 내부 네트워크만
관리자 비밀번호GRAFANA_ADMIN_PASSWORD env 필수
로그 민감 정보API 토큰, 비번, 프롬프트 본문 로그 금지
방화벽Tailscale ACL 권장

AI 모니터링 연동

.ai-core/config/services-registry.json에 등록된 서비스는 AI 정기 점검 대상:

  • AI는 Grafana HTTP API (/api/ds/query)로 로그/메트릭 쿼리
  • services-registry.jsonerror_patterns를 LogQL로 변환
  • 결과를 .ai-core/data/reports/services/_ai-summary/{date}/에 저장
  • 이상 발견 시 AskUserQuestion으로 사용자에게 대응 제안

자세한 내용은 AI 모니터링 계약 참조.

운영 가이드

일별 체크리스트

  • Overview 대시보드 확인 — 이상 징후 없음
  • Slack critical 채널 미해결 항목 확인
  • .ai-core/data/reports/services/_ai-summary/{오늘} 리뷰

주별 체크리스트

  • 저장 공간 사용률 (data/platform/monitoring/ 디스크 사용)
  • 주요 서비스 버전 업데이트 검토
  • AI 주간 보고서 검토

월별 체크리스트

  • 보존 정책 준수 확인
  • 알림 규칙 튜닝 (false positive)
  • 미사용 대시보드 정리
  • 비용/리소스 트렌드 리뷰

트러블슈팅

Grafana에 로그가 안 보여요

  1. Promtail 상태 확인: docker logs -f promtail
  2. Promtail → Loki 연결: curl http://localhost:3100/ready
  3. Loki 수집 확인: Grafana Explore에서 {job=~".+"} 쿼리
  4. 레이블 확인: 로그가 뜨는데 필터가 안 맞는 것일 수 있음

"Monitoring" 카드가 unreachable

  1. _devtools/monitoring 컨테이너 기동 확인: make status NAME=_devtools/monitoring
  2. NPM Proxy Host 등록 여부
  3. SSL 인증서 발급 여부
  4. Grafana serve_from_sub_path 설정 (경로 기반 라우팅 시)

에러 알림이 너무 많아요

  1. 알림 규칙의 threshold/for 값 상향
  2. cooldown_sec 증가
  3. severityerrorwarning으로 하향 (즉시 알림 아닌 일별 digest)

디스크 공간이 부족해요

  1. Loki retention 단축: loki-config.yamlretention_period 감소
  2. Prometheus retention 단축: --storage.tsdb.retention.time=7d
  3. 장기 보관을 S3로 이관 (Phase 3)

단계별 도입 로드맵

Phase범위상태
1기본 스택 + 로그 중앙화 + 대시보드 5개🚧 진행 중
2메트릭 확산 + Alertmanager⏳ 예정
3Grafana SSO + Loki 장기 보관
4AI 자가 점검 스킬 통합
5Tempo (트레이싱)🔶 선택

관련 문서