🤖

본 콘텐츠의 이미지 및 내용은 AI로 생성되었습니다.

⚠️

본 콘텐츠의 이미지 및 내용을 무단으로 복제, 배포, 수정하여 사용할 경우 저작권법에 의해 법적 제재를 받을 수 있습니다.

이미지 로딩 중...

워크플로 모니터링과 디버깅 완벽 가이드 - 슬라이드 1/6
A

AI Generated

2025. 12. 27. · 2 Views

워크플로 모니터링과 디버깅 완벽 가이드

LLM 기반 워크플로의 실행 상태를 추적하고, 문제를 진단하며, 성능을 최적화하는 방법을 다룹니다. LangSmith 통합부터 커스텀 모니터링 시스템 구축까지 실무에서 바로 적용할 수 있는 내용을 담았습니다.


목차

  1. 실행_추적_Tracing
  2. 로깅_전략
  3. 시각화_대시보드
  4. 실습_LangSmith_통합
  5. 실습_커스텀_모니터링

1. 실행 추적 Tracing

어느 날 김개발 씨는 자신이 만든 LLM 에이전트가 이상하게 동작하는 것을 발견했습니다. 분명 프롬프트는 제대로 작성한 것 같은데, 결과가 뒤죽박죽이었습니다.

"도대체 중간에 무슨 일이 일어난 거지?" 문제는 김개발 씨가 워크플로의 중간 과정을 전혀 볼 수 없다는 것이었습니다.

**실행 추적(Tracing)**은 워크플로가 실행되는 모든 과정을 기록하고 추적하는 기술입니다. 마치 비행기의 블랙박스처럼, 언제 어떤 함수가 호출되었고, 어떤 입력을 받아 어떤 출력을 냈는지 모든 것을 기록합니다.

이를 통해 문제가 발생했을 때 정확히 어디서 잘못되었는지 파악할 수 있습니다.

다음 코드를 살펴봅시다.

from functools import wraps
import time
import uuid

# 트레이스를 저장할 컨텍스트
trace_context = {"spans": [], "trace_id": None}

def trace(name):
    """함수 실행을 추적하는 데코레이터"""
    def decorator(func):
        @wraps(func)
        def wrapper(*args, **kwargs):
            span_id = str(uuid.uuid4())[:8]
            start_time = time.time()

            # 스팬 시작 기록
            span = {"name": name, "span_id": span_id, "start": start_time}
            trace_context["spans"].append(span)

            result = func(*args, **kwargs)

            # 스팬 종료 기록
            span["duration"] = time.time() - start_time
            span["output"] = str(result)[:100]
            return result
        return wrapper
    return decorator

@trace("llm_call")
def call_llm(prompt):
    # LLM 호출 시뮬레이션
    return f"Response to: {prompt}"

김개발 씨는 입사 6개월 차 주니어 개발자입니다. 요즘 회사에서 LLM을 활용한 챗봇 프로젝트를 맡게 되었는데, 생각보다 쉽지 않았습니다.

특히 여러 단계로 이루어진 워크플로가 중간에 어디서 잘못되는지 찾기가 너무 어려웠습니다. "선배, 이 에이전트가 왜 이상한 답변을 하는지 모르겠어요." 김개발 씨가 박시니어 씨에게 물었습니다.

박시니어 씨는 화면을 보더니 고개를 끄덕였습니다. "트레이싱을 안 했구나.

중간 과정을 볼 수 없으면 디버깅이 불가능해." 그렇다면 **실행 추적(Tracing)**이란 정확히 무엇일까요? 쉽게 비유하자면, 트레이싱은 마치 택배 추적 시스템과 같습니다.

우리가 택배를 주문하면 "상품 준비 중 - 배송 시작 - 허브 도착 - 배달 중 - 배달 완료"처럼 각 단계를 실시간으로 확인할 수 있습니다. 트레이싱도 마찬가지로 워크플로의 각 단계가 언제 시작되고, 얼마나 걸렸으며, 어떤 결과를 냈는지 모두 기록합니다.

트레이싱이 없던 시절에는 어땠을까요? 개발자들은 print문을 여기저기 찍어가며 디버깅해야 했습니다.

코드가 지저분해지고, 프로덕션 환경에서는 이마저도 쓸 수 없었습니다. 더 큰 문제는 LLM 워크플로가 비결정적이라는 것이었습니다.

같은 입력에도 다른 출력이 나올 수 있어서, 문제를 재현하기조차 어려웠습니다. 바로 이런 문제를 해결하기 위해 구조화된 트레이싱이 등장했습니다.

트레이싱은 **트레이스(Trace)**와 **스팬(Span)**이라는 개념을 사용합니다. 트레이스는 하나의 요청이 처리되는 전체 과정을 의미하고, 스팬은 그 안에서 일어나는 개별 작업 단위입니다.

위의 코드를 살펴보겠습니다. trace 데코레이터는 함수가 호출될 때마다 스팬을 생성합니다.

스팬에는 고유 ID, 시작 시간, 실행 시간, 출력 결과가 기록됩니다. 이렇게 하면 나중에 "이 함수가 언제 호출되었고, 얼마나 걸렸는지"를 정확히 알 수 있습니다.

실제 현업에서는 어떻게 활용할까요? 예를 들어 고객 문의 챗봇을 만든다고 가정해봅시다.

사용자 질문이 들어오면 의도 분류, 정보 검색, 답변 생성의 세 단계를 거칩니다. 각 단계에 트레이싱을 적용하면, "아, 정보 검색 단계에서 잘못된 문서를 가져왔구나"라는 것을 바로 알 수 있습니다.

하지만 주의할 점도 있습니다. 트레이싱에 너무 많은 정보를 담으면 저장 공간과 성능에 부담이 됩니다.

또한 민감한 사용자 정보가 트레이스에 기록되지 않도록 주의해야 합니다. 적절한 샘플링 전략을 세우는 것이 중요합니다.

다시 김개발 씨의 이야기로 돌아가 봅시다. 박시니어 씨의 조언을 듣고 트레이싱을 적용한 김개발 씨는 문제를 금방 찾을 수 있었습니다.

"아, 프롬프트 전처리 단계에서 특수문자가 제거되고 있었군요!" 트레이싱 덕분에 눈에 보이지 않던 문제가 선명하게 드러났습니다.

실전 팁

💡 - 모든 LLM 호출과 중요한 함수에는 반드시 트레이싱을 적용하세요

  • 트레이스 ID를 로그에 함께 남기면 나중에 연관 로그를 쉽게 찾을 수 있습니다
  • 프로덕션에서는 샘플링을 적용하여 성능 오버헤드를 줄이세요

2. 로깅 전략

김개발 씨가 트레이싱을 적용하고 나니 디버깅이 훨씬 수월해졌습니다. 그런데 새로운 고민이 생겼습니다.

"로그가 너무 많아서 정작 중요한 정보를 찾기가 어려워요." 수천 줄의 로그 속에서 바늘 찾기를 하는 기분이었습니다.

로깅 전략은 언제, 무엇을, 어떤 형식으로 기록할지 체계적으로 설계하는 것입니다. 마치 병원의 의무 기록처럼, 나중에 문제를 진단할 때 필요한 정보가 빠짐없이, 그러나 군더더기 없이 기록되어야 합니다.

잘 설계된 로깅은 장애 대응 시간을 획기적으로 줄여줍니다.

다음 코드를 살펴봅시다.

import logging
import json
from datetime import datetime

# 구조화된 로거 설정
class StructuredLogger:
    def __init__(self, name):
        self.logger = logging.getLogger(name)
        self.logger.setLevel(logging.DEBUG)
        handler = logging.StreamHandler()
        handler.setFormatter(logging.Formatter('%(message)s'))
        self.logger.addHandler(handler)

    def log(self, level, event, **context):
        """구조화된 로그 출력"""
        log_entry = {
            "timestamp": datetime.utcnow().isoformat(),
            "level": level,
            "event": event,
            **context
        }
        self.logger.log(getattr(logging, level), json.dumps(log_entry))

# 사용 예시
logger = StructuredLogger("llm_workflow")
logger.log("INFO", "llm_request_started", model="gpt-4", tokens=150)
logger.log("ERROR", "llm_request_failed", error="timeout", retry_count=3)

"로그 좀 보여줘." 장애가 발생했을 때 가장 먼저 나오는 말입니다. 그런데 막상 로그를 열어보면 어디서부터 봐야 할지 막막할 때가 많습니다.

김개발 씨도 그랬습니다. print문으로 찍은 로그는 형식도 제각각이고, 중요한 정보와 덜 중요한 정보가 뒤섞여 있었습니다.

박시니어 씨는 김개발 씨에게 로깅 레벨의 개념을 설명해주었습니다. "로그에는 등급이 있어.

DEBUG, INFO, WARNING, ERROR, CRITICAL. 상황에 맞는 레벨을 써야 해." 그렇다면 각 레벨은 언제 사용해야 할까요?

DEBUG는 개발 중에만 필요한 상세 정보입니다. 변수 값이나 중간 계산 결과 같은 것들이죠.

INFO는 시스템이 정상적으로 동작하고 있음을 알려주는 정보입니다. "LLM 호출 시작", "응답 수신 완료" 같은 것들입니다.

WARNING은 잠재적인 문제를 알려줍니다. 당장은 괜찮지만 주의가 필요한 상황입니다.

예를 들어 "토큰 사용량이 80%에 도달했습니다" 같은 경우입니다. ERROR는 실제로 문제가 발생했지만 시스템은 계속 동작할 수 있는 상황입니다.

CRITICAL은 시스템이 더 이상 동작할 수 없는 심각한 오류입니다. 하지만 레벨만으로는 부족합니다.

구조화된 로깅이 필요합니다. 위의 코드를 보면 JSON 형식으로 로그를 출력하고 있습니다.

이렇게 하면 로그 분석 도구에서 쉽게 파싱하고 검색할 수 있습니다. 구조화된 로그에는 몇 가지 필수 필드가 있습니다.

timestamp는 언제 발생했는지, level은 얼마나 심각한지, event는 무슨 일이 일어났는지를 알려줍니다. 여기에 context를 추가하면 더 풍부한 정보를 담을 수 있습니다.

LLM 워크플로에서는 어떤 정보를 로깅해야 할까요? 모델명, 토큰 수, 응답 시간, 에러 메시지는 기본입니다.

프롬프트와 응답 내용도 디버깅에 유용하지만, 민감 정보가 포함될 수 있으니 주의해야 합니다. 실제 현업에서는 로그 집계 시스템과 함께 사용합니다.

Elasticsearch, Loki, CloudWatch Logs 같은 도구에 로그를 모으면, 특정 조건으로 검색하고 알림을 설정할 수 있습니다. "ERROR 레벨 로그가 분당 10개 이상 발생하면 슬랙으로 알림"과 같은 식입니다.

김개발 씨는 구조화된 로깅을 적용한 후 장애 대응이 훨씬 빨라졌습니다. "이제 로그에서 trace_id로 검색하면 관련된 모든 기록을 한눈에 볼 수 있어요!"

실전 팁

💡 - 프로덕션에서는 DEBUG 레벨 로그를 끄고, 필요할 때만 동적으로 켜세요

  • 로그에 trace_id를 포함하면 분산 시스템에서도 요청 흐름을 추적할 수 있습니다
  • 민감 정보는 마스킹 처리하거나 별도 보안 저장소에 기록하세요

3. 시각화 대시보드

"지난주에 에러가 얼마나 발생했어요?" 팀 회의에서 팀장님이 물었습니다. 김개발 씨는 로그 파일을 뒤지며 수동으로 세어보려 했지만, 너무 오래 걸렸습니다.

이때 박시니어 씨가 노트북을 열어 대시보드 화면을 보여주었습니다. "여기 다 나와 있어요."

시각화 대시보드는 시스템의 상태를 한눈에 파악할 수 있게 해주는 화면입니다. 마치 자동차의 계기판처럼, 속도, 연료량, 엔진 상태를 운전 중에도 바로 확인할 수 있어야 합니다.

잘 설계된 대시보드는 문제를 조기에 발견하고 빠르게 대응할 수 있게 해줍니다.

다음 코드를 살펴봅시다.

from dataclasses import dataclass, field
from datetime import datetime
from collections import defaultdict

@dataclass
class MetricsCollector:
    """메트릭 수집기 - 대시보드용 데이터 수집"""
    counters: dict = field(default_factory=lambda: defaultdict(int))
    histograms: dict = field(default_factory=lambda: defaultdict(list))

    def increment(self, name, value=1, tags=None):
        """카운터 증가 (요청 수, 에러 수 등)"""
        key = f"{name}:{tags}" if tags else name
        self.counters[key] += value

    def record(self, name, value, tags=None):
        """히스토그램 기록 (응답 시간, 토큰 수 등)"""
        key = f"{name}:{tags}" if tags else name
        self.histograms[key].append({"value": value, "time": datetime.utcnow()})

    def get_summary(self, name):
        """통계 요약 반환"""
        values = [h["value"] for h in self.histograms.get(name, [])]
        if not values:
            return {}
        return {"avg": sum(values)/len(values), "max": max(values), "count": len(values)}

metrics = MetricsCollector()
metrics.increment("llm_requests", tags="model:gpt-4")
metrics.record("response_time_ms", 1250, tags="model:gpt-4")

김개발 씨는 대시보드 화면을 보고 감탄했습니다. 그래프와 숫자들이 실시간으로 업데이트되고 있었습니다.

요청 수, 에러율, 평균 응답 시간이 한눈에 들어왔습니다. "이거 어떻게 만든 거예요?" 박시니어 씨가 설명을 시작했습니다.

"대시보드를 만들려면 먼저 메트릭을 수집해야 해. 메트릭은 숫자로 표현할 수 있는 측정값이야." 메트릭에는 크게 세 가지 종류가 있습니다.

**카운터(Counter)**는 누적 값입니다. 총 요청 수, 총 에러 수처럼 계속 증가하는 값입니다.

**게이지(Gauge)**는 현재 상태를 나타내는 값입니다. 현재 메모리 사용량, 활성 연결 수 같은 것들입니다.

**히스토그램(Histogram)**은 값의 분포를 기록합니다. 응답 시간의 평균, 중앙값, 99퍼센타일 등을 계산할 수 있습니다.

LLM 워크플로에서 중요한 메트릭은 무엇일까요? 첫째, 요청량과 에러율입니다.

분당 몇 건의 요청이 들어오고, 그중 몇 퍼센트가 실패하는지 알아야 합니다. 둘째, 응답 시간입니다.

사용자가 얼마나 오래 기다리는지 모니터링해야 합니다. 셋째, 토큰 사용량입니다.

비용과 직결되는 중요한 지표입니다. 위의 코드는 간단한 메트릭 수집기입니다.

increment 메서드로 카운터를 증가시키고, record 메서드로 히스토그램에 값을 기록합니다. tags를 사용하면 모델별, 엔드포인트별로 메트릭을 구분할 수 있습니다.

실제 현업에서는 Prometheus, Grafana, Datadog 같은 도구를 사용합니다. Prometheus가 메트릭을 수집하고, Grafana가 이를 시각화합니다.

알림 규칙도 설정할 수 있습니다. 대시보드를 설계할 때는 **골든 시그널(Golden Signals)**을 기억하세요.

지연 시간(Latency), 트래픽(Traffic), 에러율(Errors), 포화도(Saturation). 이 네 가지를 모니터링하면 대부분의 문제를 감지할 수 있습니다.

하지만 너무 많은 그래프는 오히려 혼란을 줍니다. "이 대시보드를 보고 5초 안에 시스템이 정상인지 알 수 있는가?"를 기준으로 삼으세요.

핵심 지표만 상단에 배치하고, 상세 정보는 드릴다운 형태로 제공하는 것이 좋습니다. 김개발 씨는 자신의 서비스에도 대시보드를 구축했습니다.

이제 팀 회의에서 "지난주 상태가 어땠는지"를 숫자로 명확하게 보고할 수 있게 되었습니다.

실전 팁

💡 - 대시보드 상단에는 가장 중요한 지표 3-4개만 배치하세요

  • 이상 탐지 알림을 설정하여 문제를 조기에 발견하세요
  • 메트릭에 적절한 태그를 붙여 다양한 관점에서 분석할 수 있게 하세요

4. 실습 LangSmith 통합

박시니어 씨가 새로운 도구를 소개해주었습니다. "LangChain을 쓰고 있다면 LangSmith를 꼭 써봐.

트레이싱이랑 모니터링이 다 되어 있어." 김개발 씨는 귀가 솔깃했습니다. 직접 구축하려면 오래 걸릴 기능들이 이미 만들어져 있다니!

LangSmith는 LangChain에서 제공하는 LLM 애플리케이션 개발 플랫폼입니다. 마치 비행기 조종석의 블랙박스와 계기판을 한 번에 제공하는 것처럼, 트레이싱, 디버깅, 모니터링, 평가 기능을 통합적으로 제공합니다.

환경 변수 몇 개만 설정하면 자동으로 모든 LLM 호출이 추적됩니다.

다음 코드를 살펴봅시다.

import os
from langchain_openai import ChatOpenAI
from langchain_core.prompts import ChatPromptTemplate
from langsmith import traceable

# LangSmith 환경 설정
os.environ["LANGCHAIN_TRACING_V2"] = "true"
os.environ["LANGCHAIN_API_KEY"] = "your-api-key"
os.environ["LANGCHAIN_PROJECT"] = "my-llm-project"

# @traceable 데코레이터로 커스텀 함수 추적
@traceable(name="process_user_query")
def process_query(user_input: str) -> str:
    """사용자 질문을 처리하는 함수"""
    prompt = ChatPromptTemplate.from_messages([
        ("system", "You are a helpful assistant."),
        ("human", "{input}")
    ])
    llm = ChatOpenAI(model="gpt-4")
    chain = prompt | llm
    response = chain.invoke({"input": user_input})
    return response.content

# 실행하면 자동으로 LangSmith에 트레이스 기록
result = process_query("파이썬에서 리스트와 튜플의 차이점은?")

"LangSmith? 그게 뭐예요?" 김개발 씨가 물었습니다.

박시니어 씨는 브라우저를 열어 LangSmith 대시보드를 보여주었습니다. 화면에는 각 LLM 호출의 상세 정보가 타임라인 형태로 펼쳐져 있었습니다.

LangSmith는 LangChain 팀에서 만든 LLM 애플리케이션 개발 플랫폼입니다. 트레이싱, 디버깅, 모니터링, 테스팅을 한 곳에서 할 수 있습니다.

가장 좋은 점은 설정이 매우 간단하다는 것입니다. 위의 코드를 보세요.

환경 변수 세 개만 설정하면 됩니다. LANGCHAIN_TRACING_V2를 true로 설정하고, API 키와 프로젝트 이름을 지정합니다.

이것만으로 LangChain을 사용하는 모든 코드가 자동으로 추적됩니다. LangSmith가 기록하는 정보는 놀라울 정도로 상세합니다.

각 체인 단계별로 입력과 출력이 기록됩니다. LLM 호출의 경우 프롬프트 전문, 응답 전문, 토큰 수, 응답 시간, 모델명까지 모두 볼 수 있습니다.

@traceable 데코레이터를 사용하면 커스텀 함수도 추적할 수 있습니다. 위의 코드에서 process_query 함수에 이 데코레이터를 붙였습니다.

이제 이 함수가 호출될 때마다 LangSmith에 스팬이 생성됩니다. LangSmith의 또 다른 강점은 런 비교 기능입니다.

프롬프트를 수정했을 때 성능이 어떻게 변했는지 비교할 수 있습니다. "이전 버전에서는 정확도가 85%였는데, 수정 후 90%로 올랐네"와 같은 분석이 가능합니다.

데이터셋과 평가 기능도 있습니다. 테스트 케이스를 등록해두고, 프롬프트나 모델을 변경할 때마다 자동으로 평가를 실행할 수 있습니다.

이는 LLM 애플리케이션의 품질을 체계적으로 관리하는 데 매우 유용합니다. 실제 현업에서 LangSmith를 도입하면 디버깅 시간이 획기적으로 줄어듭니다.

문제가 발생했을 때 해당 트레이스를 찾아 입력값, 중간 결과, 최종 출력을 모두 확인할 수 있기 때문입니다. 김개발 씨는 자신의 프로젝트에 LangSmith를 적용했습니다.

"와, 이렇게 쉬웠어요? 환경 변수 세 개만 넣었는데 다 되네요!" 첫 번째 트레이스가 대시보드에 나타나는 것을 보며 김개발 씨는 감탄했습니다.

실전 팁

💡 - 개발 환경에서는 모든 호출을 추적하고, 프로덕션에서는 샘플링을 적용하세요

  • 프로젝트명을 환경별로 다르게 설정하여 dev, staging, prod 트레이스를 분리하세요
  • 민감한 정보는 LangSmith 설정에서 마스킹 처리할 수 있습니다

5. 실습 커스텀 모니터링

"LangSmith가 좋긴 한데, 우리 회사 보안 정책상 외부 서비스에 데이터를 보낼 수 없어요." 김개발 씨가 난감해했습니다. 박시니어 씨가 고개를 끄덕였습니다.

"그럴 때는 직접 모니터링 시스템을 만들어야 해. 생각보다 어렵지 않아."

커스텀 모니터링은 자체 인프라에 모니터링 시스템을 구축하는 것입니다. 마치 자신만의 맞춤 정장을 만드는 것처럼, 우리 서비스에 꼭 맞는 지표와 알림을 설계할 수 있습니다.

외부 서비스 의존성 없이 완전한 통제가 가능하며, 보안 요구사항도 충족할 수 있습니다.

다음 코드를 살펴봅시다.

import time
import json
import sqlite3
from contextlib import contextmanager
from datetime import datetime

class LLMMonitor:
    """커스텀 LLM 모니터링 시스템"""

    def __init__(self, db_path="llm_metrics.db"):
        self.conn = sqlite3.connect(db_path)
        self._init_db()

    def _init_db(self):
        self.conn.execute("""
            CREATE TABLE IF NOT EXISTS llm_calls (
                id INTEGER PRIMARY KEY,
                timestamp TEXT, model TEXT, prompt_tokens INT,
                completion_tokens INT, duration_ms FLOAT,
                status TEXT, error TEXT
            )
        """)

    @contextmanager
    def track_call(self, model: str):
        """LLM 호출 추적 컨텍스트 매니저"""
        start = time.time()
        record = {"model": model, "timestamp": datetime.utcnow().isoformat()}
        try:
            yield record
            record["status"] = "success"
        except Exception as e:
            record["status"] = "error"
            record["error"] = str(e)
            raise
        finally:
            record["duration_ms"] = (time.time() - start) * 1000
            self._save(record)

    def _save(self, record):
        self.conn.execute(
            "INSERT INTO llm_calls VALUES (NULL,?,?,?,?,?,?,?)",
            (record.get("timestamp"), record.get("model"),
             record.get("prompt_tokens", 0), record.get("completion_tokens", 0),
             record.get("duration_ms"), record.get("status"), record.get("error"))
        )
        self.conn.commit()

모든 회사가 외부 SaaS 도구를 사용할 수 있는 것은 아닙니다. 특히 금융권이나 공공기관처럼 데이터 보안이 중요한 곳에서는 외부로 데이터를 보내는 것 자체가 금지되어 있는 경우가 많습니다.

이럴 때는 직접 모니터링 시스템을 구축해야 합니다. 위의 코드는 간단하지만 실용적인 커스텀 모니터링 시스템입니다.

LLMMonitor 클래스는 SQLite를 사용하여 모든 LLM 호출을 기록합니다. 프로덕션에서는 PostgreSQL이나 TimescaleDB 같은 더 강력한 데이터베이스를 사용할 수 있습니다.

핵심은 track_call 컨텍스트 매니저입니다. 파이썬의 with 문을 사용하면 LLM 호출 전후로 자동으로 측정과 기록이 이루어집니다.

성공하든 실패하든 반드시 기록이 남습니다. 사용 방법은 간단합니다.

LLM을 호출하는 코드를 with monitor.track_call("gpt-4"): 블록으로 감싸면 됩니다. 블록 안에서 토큰 수를 record 딕셔너리에 기록하면 함께 저장됩니다.

커스텀 모니터링의 장점은 완전한 통제입니다. 어떤 데이터를 저장할지, 얼마나 오래 보관할지, 누가 접근할 수 있는지 모두 우리가 결정합니다.

또한 우리 서비스에 특화된 메트릭을 추가할 수 있습니다. 물론 단점도 있습니다.

인프라를 직접 운영해야 하고, 시각화 대시보드도 별도로 구축해야 합니다. Grafana와 연동하거나, Streamlit으로 간단한 대시보드를 만들 수 있습니다.

확장 아이디어도 소개합니다. 알림 시스템을 추가하면 에러율이 임계치를 넘을 때 슬랙 알림을 보낼 수 있습니다.

비용 추적을 추가하면 토큰 사용량을 기반으로 예상 비용을 계산할 수 있습니다. A/B 테스트를 위해 실험 그룹별로 메트릭을 분리할 수도 있습니다.

실제로 많은 기업들이 이런 방식으로 자체 모니터링 시스템을 운영합니다. 초기에는 간단하게 시작하고, 필요에 따라 점진적으로 기능을 추가해 나가는 것이 좋습니다.

김개발 씨는 보안팀의 승인을 받고 커스텀 모니터링 시스템을 구축했습니다. "외부 서비스 못 쓴다고 걱정했는데, 직접 만드니까 오히려 우리 서비스에 더 잘 맞는 것 같아요!"

실전 팁

💡 - 처음에는 SQLite로 시작하고, 트래픽이 늘면 전용 시계열 DB로 마이그레이션하세요

  • 메트릭 데이터는 용량이 빠르게 늘어나므로 보관 기간 정책을 미리 정하세요
  • 알림 규칙은 너무 민감하게 설정하면 알림 피로가 생기니 임계치를 신중하게 조정하세요

이상으로 학습을 마칩니다. 위 내용을 직접 코드로 작성해보면서 익혀보세요!

#Python#LangSmith#Tracing#Logging#Monitoring#LLM,모니터링,디버깅

댓글 (0)

댓글을 작성하려면 로그인이 필요합니다.

함께 보면 좋은 카드 뉴스