현재 내가 사용하는 시스템성능 모니터링 솔루션의 수집 데이터를 Grafana 로 시각화하기 위해 Proxy API를 구축하여 중간 브릿지 역할을 하도록 구성했다.
다행히 해당 솔루션에서 API 를 제공해주었다.
[ Data Flow ]
Client (Grafana) → Proxy API (FastAPI) → onTuneV5 API
그래서 왜 Proxy API 를 통해서 Grafana 와 연동을 진행한 이유를 더 자세하게 덧붙이자면....
해당 솔루션의 API 를 Grafana 가 직접 호출하기에는 좀 제약이 있었다.
1. 토큰 인증 구조
-> 솔루션 API 는 별도의 ID 와 PW 를 통한 Token 발급 프로세스가 필요했다.
2. 토큰 만료
-> 발급된 Token 의 유효 기간이 1시간이기 때문에, 만료시마다 수동 갱신이 어려웠다.
그래서 Token 자동 갱신이 가장 필요한 과제였기 때문에,
이를 해결하기 위해서 Proxy API 내부에 다음 로직을 구현했다.
1. 서버 시작 시 또는 요청 시 Token 의 유효성 체크
2. Token 이 만료되었거나 없을 경우, 자동으로 솔루션 웹에 로그인하여 New Token 을 발급받아 메모리에 저장 (Auto-Refresh)
3. Grafana 의 요청이 들어오면 저장된 최신 Token 을 Header (Authorization) 에 실어 데이터 중계 역할
[ FastAPI 구현 로직 ]
아래는 실제 사용한 핵심 로직만 정리한 코드 예시다.
기본 구조 및 전역 변수
from fastapi import FastAPI, Request, Response
import requests
cached_token = "" # 메모리 캐시
app = FastAPI()
ONTUNE_BASE = "http://API:8080"
Token 발급 함수 (Auto-Refresh 핵심)
- Token은 메모리 캐시
- 만료 시 즉시 재발급
- 운영 중이더라도 별도 설정 변경 없음
def get_new_token():
auth_data = {
"type": 10066065, # API 토큰 발급용 고유 타입
"req": {
"id": "ID",
"password": "PW"
}
}
headers = {
"Content-Type": "application/json"
}
try:
resq = requests.post(
f"{ONTUNE_BASE}/token",
json=auth_data,
headers=headers,
timeout=10
)
resq.raise_for_status()
resp_json = resq.json()
return resp_json["res"][0]["tokenstring"]
except Exception as e:
print(f"토큰 발급 중 오류 발생: {e}")
return ""
실제 Proxy API 엔드포인트
def get_new_token():
auth_data = {
"type": 10066065, # API 토큰 발급용 고유 타입
"req": {
"id": "ID",
"password": "PW"
}
}
headers = {
"Content-Type": "application/json"
}
try:
resq = requests.post(
f"{ONTUNE_BASE}/token",
json=auth_data,
headers=headers,
timeout=10
)
resq.raise_for_status()
resp_json = resq.json()
return resp_json["res"][0]["tokenstring"]
except Exception as e:
print(f"토큰 발급 중 오류 발생: {e}")
return ""
헬스 체크 엔드포인트
@app.get("/")
def health():
return {"status": "ok"}
배포 환경 구성(Dockerization)]
Dockerfile
FROM python:3.9-slim
WORKDIR /app
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt
COPY . .
# FastAPI 서버 실행
CMD ["uvicorn", "main:app", "--host", "0.0.0.0", "--port", "8000"]
docker-compose.yml
version: '3.8'
services:
ontune-proxy:
build: .
container_name: api-proxy-api
ports:
- "8000:8000"
restart: always
environment:
- ONTUNE_URL=http://API 주소:8080
- TZ=Asia/Seoul
requirements.txt
fastapi==0.95.0
uvicorn==0.21.1
httpx==0.24.0
python-multipart==0.0.6
실행 방법 및 로그 확인 방법
docker compose down
docker compose up -d --build
docker logs -f api-grafana-proxy