diff --git a/cli/__init__.py b/cli/__init__.py index 65d9db5..7ab1695 100644 --- a/cli/__init__.py +++ b/cli/__init__.py @@ -2,12 +2,21 @@ Datahub GMS 서버 URL을 설정하고, 필요 시 Streamlit 인터페이스를 실행하는 CLI 프로그램입니다. """ +import logging import subprocess import click +from llm_utils.check_server import CheckServer from llm_utils.tools import set_gms_server +logging.basicConfig( + level=logging.INFO, + format="%(asctime)s [%(levelname)s] %(message)s", + datefmt="%Y-%m-%d %H:%M:%S", +) +logger = logging.getLogger(__name__) + @click.group() @click.version_option(version="0.1.4") @@ -64,11 +73,20 @@ def cli( 'set_gms_server' 함수에서 ValueError가 발생할 경우, 프로그램은 비정상 종료(exit code 1)합니다. """ - try: + logger.info( + "Initialization started: GMS server = %s, run_streamlit = %s, port = %d", + datahub_server, + run_streamlit, + port, + ) + + if CheckServer.is_gms_server_healthy(url=datahub_server): set_gms_server(datahub_server) - except ValueError as e: - click.secho(f"GMS 서버 URL 설정 실패: {str(e)}", fg="red") + logger.info("GMS server URL successfully set: %s", datahub_server) + else: + logger.error("GMS server health check failed. URL: %s", datahub_server) ctx.exit(1) + if run_streamlit: run_streamlit_command(port) @@ -89,6 +107,8 @@ def run_streamlit_command(port: int) -> None: - subprocess 호출 실패 시 예외가 발생할 수 있습니다. """ + logger.info("Starting Streamlit application on port %d...", port) + try: subprocess.run( [ @@ -100,8 +120,9 @@ def run_streamlit_command(port: int) -> None: ], check=True, ) + logger.info("Streamlit application started successfully.") except subprocess.CalledProcessError as e: - click.echo(f"Streamlit 실행 실패: {e}") + logger.error("Failed to start Streamlit application: %s", e) raise @@ -132,4 +153,5 @@ def run_streamlit_cli_command(port: int) -> None: - Streamlit 실행에 실패할 경우 subprocess 호출에서 예외가 발생할 수 있습니다. """ + logger.info("Executing 'run-streamlit' command on port %d...", port) run_streamlit_command(port) diff --git a/data_utils/__init__.py b/data_utils/__init__.py index 60d5dfc..e69de29 100644 --- a/data_utils/__init__.py +++ b/data_utils/__init__.py @@ -1 +0,0 @@ -# data_utils 패키지 초기화 파일 diff --git a/llm_utils/check_server.py b/llm_utils/check_server.py new file mode 100644 index 0000000..1cc652d --- /dev/null +++ b/llm_utils/check_server.py @@ -0,0 +1,74 @@ +""" +서버 상태 확인 및 연결 관련 기능을 제공하는 유틸리티 클래스입니다. + +이 모듈은 HTTP 기반의 서버에 대해 다음과 같은 기능을 제공합니다: +- `/health` 엔드포인트를 통한 서버 헬스 체크 +- 향후 서버 연결 또는 상태 점검과 관련된 기능 추가 예정 + +각 기능은 요청 실패, 타임아웃, 연결 오류 등의 다양한 예외 상황을 포괄적으로 처리하며, +로깅을 통해 상세한 실패 원인을 기록하고 결과를 boolean 또는 적절한 형태로 반환합니다. +""" + +import logging +from urllib.parse import urljoin + +import requests + +logging.basicConfig( + level=logging.INFO, + format="%(asctime)s [%(levelname)s] %(message)s", + datefmt="%Y-%m-%d %H:%M:%S", +) +logger = logging.getLogger(__name__) + + +class CheckServer: + """ + 서버의 상태를 확인하거나 연결을 테스트하는 유틸리티 메서드를 제공하는 클래스입니다. + + 현재는 GMS 서버의 `/health` 엔드포인트에 대한 헬스 체크 기능을 포함하고 있으며, + 향후에는 다양한 서버 연결 확인 및 상태 점검 기능이 추가될 수 있도록 확장 가능한 구조로 설계되었습니다. + 모든 기능은 네트워크 오류 및 서버 응답 상태에 따라 예외를 로깅하며, 호출자가 결과를 판단할 수 있도록 boolean 값을 반환합니다. + """ + + @staticmethod + def is_gms_server_healthy(*, url: str) -> bool: + """ + 지정된 GMS 서버의 `/health` 엔드포인트에 요청을 보내 상태를 확인합니다. + + 서버가 HTTP 200 응답을 반환하면 True를 반환하며, + 요청 실패, 타임아웃, 연결 오류 등의 예외 발생 시 False를 반환하고, + 로깅을 통해 상세한 에러 정보를 출력합니다. + + Args: + url (str): 헬스 체크를 수행할 GMS 서버의 기본 URL (예: "http://localhost:8080") + + Returns: + bool: 서버가 정상적으로 응답하면 True, 예외 발생 시 False + """ + + health_url = urljoin(url, "/health") + + try: + response = requests.get( + health_url, + timeout=3, + ) + response.raise_for_status() + logger.info("GMS server is healthy: %s", url) + return True + except ( + requests.exceptions.ConnectTimeout, + requests.exceptions.ReadTimeout, + ) as e: + logger.error( + "Timeout while connecting to GMS server: %s | %s", health_url, e + ) + except requests.exceptions.ConnectionError as e: + logger.error("Failed to connect to GMS server: %s | %s", health_url, e) + except requests.exceptions.HTTPError as e: + logger.error("GMS server returned HTTP error: %s | %s", health_url, e) + except requests.exceptions.RequestException as e: + logger.exception("Unexpected request error to GMS server: %s", health_url) + + return False