성능 모니터링/Grafana

[Grafana] FastAPI Proxy를 이용한 데이터 연동 (docker 로 구축)

최선을 다하자! 2026. 1. 31. 16:10

현재 내가 사용하는 시스템성능 모니터링 솔루션의 수집 데이터를 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