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
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ lerna-debug.log*
apm_query_api_spec_v2.yaml
# …but keep README.md files tracked
!README.md
!backend/OPERATIONS.md
# Keep project-specific ignores inside subdirectories (.gitignore within backend/, frontend/, etc.)
# Keep project-specific ignores inside subdirectories (.gitignore within backend/, frontend/, etc.)
reports
reports
91 changes: 91 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
# Panopticon Backend

NestJS 기반 APM 백엔드로, 수집된 로그·스팬을 Elasticsearch에 적재하고 조회/알림/롤업을 제공합니다. Kafka를 통해 들어오는 실시간 이벤트를 처리하고, 대시보드용 HTTP API와 WebSocket 알림 채널을 함께 제공합니다.

## 아키텍처 한눈에 보기
- **stream-processor**: Kafka `apm.logs`/`apm.spans` 토픽 소비 → 검증 후 ES 데이터 스트림(`logs-apm`, `traces-apm`)에 `_bulk` 색인. ERROR 로그는 별도 토픽(`apm.logs.error`)으로 포워딩.
- **query-api**: 서비스/엔드포인트 메트릭, 스팬/로그 검색, 단일 트레이스 조회용 읽기 전용 HTTP API. 롤업(1분 버킷) 데이터와 Redis 캐시를 활용해 긴 구간 조회를 가속.
- **error-stream**: `apm.logs.error`를 소비해 WebSocket으로 프런트엔드에 실시간 에러 알림 송신.
- **aggregator**: 닫힌 분(minute) 단위로 `traces-apm`을 집계해 롤업 데이터 스트림(`metrics-apm`)을 채우는 워커.
- **shared**: 공통 DTO, 저장소, Kafka/ES 설정, Redis 캐시 유틸.

## 주요 기능
- APM 로그/스팬 ingest 및 `_bulk` 색인 최적화(배치/바이트/타이머 기준 플러시, 병렬 플러시 한도).
- 서비스·엔드포인트 메트릭(QPS, p95/p90/p50, 에러율)과 트레이스/스팬/로그 검색 API 제공.
- 롤업 파이프라인(1분 버킷) 및 롤업+RAW 자동 병합 조회, Redis 기반 단기 캐시.
- Kafka → WebSocket 에러 스트림 브리지로 실시간 에러 알림.

## 디렉터리 구조
```
backend/
src/
query-api/ # 읽기 전용 HTTP API
stream-processor/ # Kafka 컨슈머(로그/스팬) + 샘플 프로듀서
error-stream/ # 에러 로그 WebSocket 브리지
aggregator/ # 롤업 워커
shared/ # 공통 DTO/서비스/설정
```

## 빠른 시작
> 모든 명령은 `backend` 디렉터리에서 실행합니다.

```bash
cd backend
npm ci

# 로컬 개발 (env는 .env/.env.local 사용)
npm run start:query-api # HTTP API (포트 3001)
npm run start:stream-processor # Kafka 컨슈머
npm run start:error-stream # WebSocket + Kafka
npm run start:aggregator # 롤업 워커
```

### 필수/주요 환경 변수
- OpenSearch/ES: `ELASTICSEARCH_NODE`, `OPENSEARCH_USERNAME`, `OPENSEARCH_PASSWORD`, `OPENSEARCH_REJECT_UNAUTHORIZED`, `USE_ISM`
- Kafka: `KAFKA_BROKERS` (`KAFKA_BROKERS_LOCAL`), `KAFKA_SSL`, `KAFKA_SASL_MECHANISM`, `KAFKA_SASL_USERNAME/PASSWORD`, `KAFKA_AWS_REGION`
- APM 토픽: `KAFKA_APM_LOG_TOPIC`, `KAFKA_APM_SPAN_TOPIC`, `KAFKA_APM_LOG_ERROR_TOPIC`
- Redis 캐시: `REDIS_HOST` (캐시 비활성화 시 생략), `METRICS_CACHE_PREFIX`, `METRICS_CACHE_TTL_SECONDS`
- 롤업: `ROLLUP_ENABLED`, `ROLLUP_THRESHOLD_MINUTES`, `ROLLUP_BUCKET_MINUTES`, `ROLLUP_CACHE_TTL_SECONDS`

## API 개요 (주요 엔드포인트)
- **트레이스**
- `GET /query/traces/:traceId` : 단일 트레이스의 스팬/로그 전체 반환(서비스/환경 필터 지원)
- **스팬 검색**
- `GET /query/spans` : 서비스/환경/이름/지연/상태/트레이스 ID 기준 검색, 페이지네이션/정렬 지원
- **로그 검색**
- `GET /query/logs` : 서비스/환경/레벨/트레이스·스팬 ID/메시지로 검색, 최신순 기본 15분
- **서비스 메트릭**
- `GET /query/services/:serviceName/metrics` : QPS, p95/p90/p50, 에러율 시계열. 긴 구간은 롤업+RAW 병합, Redis 캐시 활용
- **서비스 개요**
- `GET /query/services` : 시간 구간 내 서비스별 요청수/p95/에러율 랭킹
- **엔드포인트 메트릭/트레이스**
- `GET /query/services/:serviceName/endpoints` : 엔드포인트별 요청수/p95/에러율 상위 N개
- `GET /query/services/:serviceName/endpoints/:endpointName/traces` : 최근 에러/느린 트레이스 샘플
- **WebSocket 에러 알림**
- 경로: `ws://<host>:3010/ws/error-logs` (환경 변수로 변경 가능)
- 이벤트: `error-log` (Kafka `apm.logs.error`의 validated DTO)

## 롤업 파이프라인
- Aggregator가 닫힌 1분 구간을 계획(MinuteWindowPlanner) → 서비스/환경별 percentiles 및 에러율 집계 → `metrics-apm` 데이터 스트림에 `_bulk create` 저장.
- Query API는 조회 구간이 `ROLLUP_THRESHOLD_MINUTES` 이상이면 과거 구간을 롤업으로 채우고, 최신 구간은 RAW 집계로 결합해 응답.

## 운영 팁
- Kafka/ES/Redis는 `infra/docker-compose.yml`로 로컬 부트스트랩 가능.
- `_bulk` 설정은 `BULK_BATCH_SIZE`, `BULK_BATCH_BYTES_MB`, `BULK_MAX_PARALLEL_FLUSHES` 등으로 조정해 클러스터 부하에 맞출 수 있습니다.
- Throughput 모니터링: `STREAM_THROUGHPUT_*` 환경 변수를 설정하면 컨슈머 처리량 로그를 샘플링해 남깁니다.
- 보안: OpenSearch ISM 또는 Elasticsearch ILM/템플릿을 자동 생성하지만, 프로덕션에서는 최소 권한 계정과 TLS 설정을 사용하세요.

## 샘플 이벤트 발행
```bash
npm run test:sample:log # Kafka에 샘플 로그 전송
npm run test:sample:span # Kafka에 샘플 스팬 전송
```

## 운영 가이드 링크
- 백엔드 빌드/배포/환경 변수 세부 가이드는 [backend/OPERATIONS.md](backend/OPERATIONS.md)를 참고하세요.

## 이 아키텍처의 강점
- **책임 분리 + 스케일링**: ingest(stream-processor) / 롤업(aggregator) / 조회(query-api) / 실시간 알림(error-stream)을 각각 컨테이너로 분리해 장애 격리, 트래픽 패턴별 독립 확장이 가능.
- **운영 튜너블**: 환경 변수만으로 ILM/ISM, Kafka SSL/SASL, `_bulk` 버퍼, 롤업/캐시 전략을 즉시 조정해 인프라 부하에 맞출 수 있음.
- **성능 보호**: 1분 롤업 + Redis 캐시로 긴 구간 조회를 가볍게 하고, ThroughputTracker/배치 플러시로 컨슈머 병목을 방지.
- **데이터 신뢰성**: DTO 검증, ISM/ILM 자동 생성, idempotent 롤업 ID로 중복/충돌을 줄이고, 에러 로그는 별도 토픽으로 분리해 손실 위험을 낮춤.
65 changes: 65 additions & 0 deletions backend/OPERATIONS.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
# Backend Operations Guide

Panopticon 백엔드를 빌드/배포/운영하기 위한 실무 가이드입니다. 각 기능은 별도 이미지/프로세스로 분리되어 있어 장애 격리와 독립 스케일링이 가능합니다.

## 컴포넌트와 Docker 타깃
| 역할 | Docker target | 설명 |
| --- | --- | --- |
| Query API | `query-api` | 서비스/엔드포인트 메트릭, 스팬/로그 검색, 트레이스 조회 |
| Stream Processor | `stream-processor` | Kafka `apm.logs`/`apm.spans` 소비 → ES 데이터 스트림에 `_bulk` 색인, ERROR 로그는 별도 토픽으로 복제 |
| Error Stream | `error-stream` | `apm.logs.error` 소비 → WebSocket(`ws://host:3010/ws/error-logs`) 브로드캐스트 |
| Aggregator | `aggregator` | 닫힌 1분 구간을 롤업 집계해 `metrics-apm` 데이터 스트림에 저장 |

## 로컬 실행/빌드
모든 명령은 `backend`에서 실행합니다.

```bash
npm ci
npm run start:query-api # 포트 3001
npm run start:stream-processor # Kafka 컨슈머
npm run start:error-stream # WebSocket + Kafka
npm run start:aggregator # 롤업 워커

# 프로덕션 빌드
npm run build

# Docker 이미지 빌드 예시
docker build -f backend/Dockerfile -t panopticon-query-api --target query-api backend
docker build -f backend/Dockerfile -t panopticon-stream-processor --target stream-processor backend
docker build -f backend/Dockerfile -t panopticon-error-stream --target error-stream backend
docker build -f backend/Dockerfile -t panopticon-aggregator --target aggregator backend
```

ECR 푸시 예시:
```bash
aws ecr get-login-password --region <region> | docker login --username AWS --password-stdin <account>.dkr.ecr.<region>.amazonaws.com
docker tag panopticon-query-api:latest <account>.dkr.ecr.<region>.amazonaws.com/panopticon-query-api:latest
docker push <account>.dkr.ecr.<region>.amazonaws.com/panopticon-query-api:latest
```

## 서비스별 핵심 환경 변수
- 공통: `ELASTICSEARCH_NODE`, `OPENSEARCH_USERNAME/PASSWORD`, `OPENSEARCH_REJECT_UNAUTHORIZED`, `USE_ISM`, `KAFKA_BROKERS`(또는 `KAFKA_BROKERS_LOCAL`), `KAFKA_SSL`, `KAFKA_SASL_*`
- Query API: `PORT`, `ROLLUP_ENABLED`, `ROLLUP_THRESHOLD_MINUTES`, `ROLLUP_BUCKET_MINUTES`, `ROLLUP_CACHE_TTL_SECONDS`, `REDIS_HOST`(캐시 활성화)
- Stream Processor: `KAFKA_APM_LOG_TOPIC`, `KAFKA_APM_SPAN_TOPIC`, `_bulk` 튜닝(`BULK_BATCH_SIZE`, `BULK_BATCH_BYTES_MB`, `BULK_FLUSH_INTERVAL_MS`, `BULK_MAX_PARALLEL_FLUSHES`), 처리량 로그(`STREAM_THROUGHPUT_*`)
- Error Stream: `KAFKA_APM_LOG_ERROR_TOPIC`, `ERROR_STREAM_PORT`, `ERROR_STREAM_WS_ORIGINS`, `ERROR_STREAM_WS_PATH`
- Aggregator: `ROLLUP_AGGREGATOR_ENABLED`, `ROLLUP_BUCKET_SECONDS`, `ROLLUP_POLL_INTERVAL_MS`, `ROLLUP_INITIAL_LOOKBACK_MINUTES`, `ROLLUP_INDEX_PREFIX`, `ROLLUP_CHECKPOINT_INDEX`

## 운영/성능 튜닝 팁
- **Bulk 색인**: `_bulk` 버퍼 크기와 동시 플러시(`BULK_MAX_PARALLEL_FLUSHES`)를 클러스터 상태에 맞게 조정합니다.
- **Kafka 소비량 모니터링**: `STREAM_THROUGHPUT_*`로 샘플 처리량 로그를 남겨 병목을 조기에 파악합니다.
- **롤업 조회 전략**: 긴 구간 조회는 롤업 버킷(`metrics-apm`)을 우선 사용하고 최신 구간만 RAW를 읽습니다. 캐시 TTL을 상황에 맞게 늘리거나 줄이세요.
- **보안**: TLS/SSL·SASL(AWS MSK IAM 포함)을 환경 변수로 켜고, ISM/ILM/템플릿은 부팅 시 자동 생성되지만 프로덕션에서는 최소 권한 계정으로 접속하세요.
- **WebSocket 알림**: 허용 Origin은 `ERROR_STREAM_WS_ORIGINS`로 제한하고, 에러 토픽 소비가 실패하면 로그로 확인 후 Kafka 설정을 점검합니다.

## 배포 체크리스트
- ECR에 최신 이미지 푸시 여부 확인 (`query-api`, `stream-processor`, `error-stream`, `aggregator` 각각).
- ECS/Compose에 필수 환경 변수 입력: ES, Kafka, Redis, 롤업/캐시/버퍼 설정.
- Kafka 토픽 권한 및 SASL/SSL 설정 검증.
- 롤업/캐시 기능 플래그(`ROLLUP_ENABLED`, `ROLLUP_AGGREGATOR_ENABLED`, `ROLLUP_CACHE_TTL_SECONDS`) 원하는 상태인지 확인.
- WebSocket 경로/Origin, 헬스체크 엔드포인트(`/query/health`, `/health`)를 로드밸런서에 등록.

## 트러블슈팅 힌트
- **컨슈머 지연**: `_bulk` 설정 과도, Kafka fetch 옵션(`KAFKA_FETCH_*`) 조정 필요 여부 확인.
- **롤업 누락**: Aggregator 로그에서 체크포인트/집계/저장 단계 에러 확인, `ROLLUP_CHECKPOINT_INDEX` 접근 권한 점검.
- **캐시 미동작**: `REDIS_HOST` 설정 여부, TLS 옵션(`REDIS_USE_TLS`, `REDIS_REJECT_UNAUTHORIZED`) 확인.
- **에러 알림 미수신**: `apm.logs.error` 토픽 유입 여부와 Error Stream WebSocket 접속 로그 확인. 프런트 CORS/Origin 설정 점검.
108 changes: 0 additions & 108 deletions backend/README.md

This file was deleted.