팰월드 프로메테우스 익스포터 파이썬 50줄로 자작
집 서버에는 Prometheus + Grafana + Alertmanager 모니터링 스택이 돌고 있고 마크 서버는 mc-monitor라는 기성 익스포터로 보고 있다. 팰월드 서버를 새로 팠으니 얘도 같은 스택에 넣고 싶은데... mc-monitor는 마크 전용이라 팰월드를 모른다.
찾아보면 팰월드용 커뮤니티 익스포터가 있긴 할 거다. 근데 팰월드는 공식 REST API가 서버 지표를 이미 다 준다.
{"currentplayernum": 0, "serverfps": 59, "maxplayernum": 8, "uptime": 2604, ...}
이걸 프로메테우스 텍스트 포맷으로 바꿔주기만 하면 된다. 남의 이미지 검증할 시간에 그냥 만드는게 빠르겠다 싶었음
50줄이면 됨
외부 라이브러리 없이 파이썬 표준 라이브러리만 썼다. 스크레이프 요청이 올 때마다 팰월드 API를 찔러서 변환해주는 HTTP 서버가 전부다. 핵심만 보면 이렇다.
GAUGES = [
("palworld_players_online", "currentplayernum"),
("palworld_players_max", "maxplayernum"),
("palworld_server_fps", "serverfps"),
("palworld_uptime_seconds", "uptime"),
]
def render():
lines = []
try:
data = fetch_metrics() # REST API /v1/api/metrics
lines.append("palworld_up 1")
for name, key in GAUGES:
lines.append(f"{name} {data[key]}")
except Exception:
lines.append("palworld_up 0") # API가 죽었으면 그 자체가 지표
return "\n".join(lines)
API 응답이 없으면 palworld_up 0을 내보낸다. 알림 규칙은 이거 하나만 걸었다.
- alert: PalworldServerDown
expr: palworld_up == 0
for: 5m
labels: { severity: critical }
디스코드 알림 템플릿은 마크 때 한글로 만들어둔걸 그대로 타니까 추가로 할 게 없었다. "팰월드 서버 응답 없음 -> 발생함" 이렇게 온다.
네트워크 양다리
익스포터 컨테이너는 도커 네트워크 두 개에 걸쳐놨다. 모니터링 망에서는 프로메테우스한테 긁히고, 팰월드 망에서는 컨테이너 이름으로 API를 부른다. compose에서 external 네트워크 하나 더 붙이면 끝이라 팰월드 쪽 포트를 호스트에 노출할 필요가 없다. 관리용 API는 도커 내부망 밖으로 안 나가는게 맞다.
소소한 삽질
배포하고 프로메테우스 컨테이너에서 wget으로 익스포터를 찔러봣는데 이름이 안 풀렸다.
bad address
어? 같은 네트워크인데?? 하고 한참 봤는데 정작 프로메테우스 본체는 스크레이프를 잘만 하고 있었다. busybox wget 리졸버랑 Go 리졸버가 도커 내장 DNS를 대하는 방식이 다른 모양이다. 확인하려고 쓴 도구가 거짓말을 해서 멀쩡한걸 한참 의심했음(ㅠ)
마치며
기성품 찾아다니는 것보다 그냥 짜는게 빠를 때도 있다.