""" LangSmith 추적(tracing) 유틸리티 모듈. LangGraph 노드 실행을 LangSmith에서 추적하고 모니터링하기 위한 도구를 제공합니다. 공식 문서: https://docs.langchain.com/langsmith/trace-with-langgraph """ import os import logging import asyncio from functools import wraps from typing import Any, Callable from inspect import iscoroutinefunction from langsmith import traceable logger = logging.getLogger(__name__) def ensure_tracing_enabled() -> bool: """ LangSmith 추적이 올바르게 설정되었는지 확인합니다. Returns: bool: 추적이 활성화되어 있으면 True, 그렇지 않으면 False """ required_vars = ["LANGCHAIN_TRACING_V2", "LANGCHAIN_API_KEY"] missing_vars = [var for var in required_vars if not os.getenv(var)] if missing_vars: logger.warning( "LangSmith 추적이 비활성화되었습니다. 누락된 환경변수: %s", ", ".join(missing_vars) ) return False return True def trace_node(node_name: str) -> Callable: """ LangGraph 노드 실행을 추적하는 데코레이터. 이 데코레이터는 각 노드의 입력/출력, 실행 시간, 에러를 LangSmith 대시보드에 자동으로 기록합니다. 동기 및 비동기 함수 모두 지원합니다. Args: node_name: LangSmith에 표시될 노드 이름 Returns: Callable: 데코레이트된 함수 Example: @trace_node("check_cache") async def check_cache_node(state: AgentState) -> AgentState: # 노드 로직 return state """ def decorator(func: Callable) -> Callable: # async 함수인지 확인 if iscoroutinefunction(func): @wraps(func) @traceable(name=node_name, run_type="chain") async def async_wrapper(*args, **kwargs) -> Any: try: result = await func(*args, **kwargs) return result except Exception as e: logger.error("🔴 노드 실패: %s - %s", node_name, str(e)) raise return async_wrapper else: @wraps(func) @traceable(name=node_name, run_type="chain") def sync_wrapper(*args, **kwargs) -> Any: try: result = func(*args, **kwargs) return result except Exception as e: logger.error("🔴 노드 실패: %s - %s", node_name, str(e)) raise return sync_wrapper return decorator # 모듈 import 시 자동으로 추적 설정 확인 ensure_tracing_enabled()