Skip to content

트레이싱 (Tracing)

이 페이지는 AI 에이전트에 대한 포괄적인 트레이싱(tracing) 기능을 제공하는 Tracing 기능에 대한 세부 정보를 포함하고 있습니다.

기능 개요 (Feature overview)

Tracing 기능은 다음과 같은 에이전트 실행에 대한 상세 정보를 캡처하는 강력한 모니터링 및 디버깅 도구입니다:

  • 전략 실행 (Strategy execution)
  • LLM 호출
  • LLM 스트리밍 (시작, 프레임, 완료, 에러)
  • 도구 호출 (Tool calls)
  • 에이전트 그래프 내의 노드 실행

이 기능은 에이전트 파이프라인의 주요 이벤트를 가로채서 설정 가능한 메시지 프로세서로 전달하는 방식으로 작동합니다. 이러한 프로세서는 트레이스 정보를 로그 파일이나 파일 시스템의 다른 유형의 파일과 같은 다양한 목적지로 출력할 수 있어, 개발자가 에이전트의 동작을 파악하고 문제를 효과적으로 해결할 수 있도록 돕습니다.

이벤트 흐름 (Event flow)

  1. Tracing 기능이 에이전트 파이프라인의 이벤트를 가로챕니다.
  2. 설정된 메시지 필터에 따라 이벤트가 필터링됩니다.
  3. 필터링된 이벤트가 등록된 메시지 프로세서로 전달됩니다.
  4. 메시지 프로세서가 이벤트를 포맷팅하여 각각의 목적지로 출력합니다.

설정 및 초기화 (Configuration and initialization)

기본 설정

Tracing 기능을 사용하려면 다음 단계를 수행해야 합니다:

  1. 하나 이상의 메시지 프로세서를 준비합니다 (기존 프로세서를 사용하거나 직접 생성할 수 있습니다).
  2. 에이전트에 Tracing을 설치합니다.
  3. 메시지 필터를 설정합니다 (선택 사항).
  4. 기능을 수행할 메시지 프로세서를 추가합니다.
kotlin
// 트레이스 메시지의 목적지로 사용될 로거/파일 정의
val logger = KotlinLogging.logger { }
val outputPath = Path("/path/to/trace.log")

// 에이전트 생성
val agent = AIAgent(
    promptExecutor = simpleOllamaAIExecutor(),
    llmModel = OllamaModels.Meta.LLAMA_3_2,
) {
    install(Tracing) {

        // 트레이스 이벤트를 처리할 메시지 프로세서 설정
        addMessageProcessor(TraceFeatureMessageLogWriter(logger))
        addMessageProcessor(TraceFeatureMessageFileWriter(
            outputPath,
            { path: Path -> SystemFileSystem.sink(path).buffered() }
        ))
    }
}

메시지 필터링 (Message filtering)

모든 기존 이벤트를 처리하거나 특정 기준에 따라 일부만 선택하여 처리할 수 있습니다. 메시지 필터를 사용하면 어떤 이벤트를 처리할지 제어할 수 있습니다. 이는 에이전트 실행의 특정 측면에 집중할 때 유용합니다:

kotlin

val fileWriter = TraceFeatureMessageFileWriter(
    outputPath,
    { path: Path -> SystemFileSystem.sink(path).buffered() }
)

addMessageProcessor(fileWriter)

// LLM 관련 이벤트만 필터링
fileWriter.setMessageFilter { message ->
    message is LLMCallStartingEvent || message is LLMCallCompletedEvent
}

// 도구(tool) 관련 이벤트만 필터링
fileWriter.setMessageFilter { message -> 
    message is ToolCallStartingEvent ||
           message is ToolCallCompletedEvent ||
           message is ToolValidationFailedEvent ||
           message is ToolCallFailedEvent
}

// 노드 실행 이벤트만 필터링
fileWriter.setMessageFilter { message -> 
    message is NodeExecutionStartingEvent || message is NodeExecutionCompletedEvent
}

대량의 트레이스 볼륨 (Large trace volumes)

복잡한 전략이나 장시간 실행되는 에이전트의 경우, 트레이스 이벤트의 양이 상당할 수 있습니다. 이벤트 볼륨을 관리하기 위해 다음 방법들을 고려해 보세요:

  • 특정 메시지 필터를 사용하여 이벤트 수를 줄입니다.
  • 버퍼링이나 샘플링 기능이 있는 커스텀 메시지 프로세서를 구현합니다.
  • 로그 파일이 너무 커지지 않도록 파일 로테이션(file rotation)을 사용합니다.

의존성 그래프 (Dependency graph)

Tracing 기능은 다음과 같은 의존성을 가집니다:

Tracing
├── AIAgentPipeline (이벤트 가로채기용)
├── TraceFeatureConfig
│   └── FeatureConfig
├── Message Processors
│   ├── TraceFeatureMessageLogWriter
│   │   └── FeatureMessageLogWriter
│   ├── TraceFeatureMessageFileWriter
│   │   └── FeatureMessageFileWriter
│   └── TraceFeatureMessageRemoteWriter
│       └── FeatureMessageRemoteWriter
└── Event Types (ai.koog.agents.core.feature.model 에서 제공)
    ├── AgentStartingEvent
    ├── AgentCompletedEvent
    ├── AgentExecutionFailedEvent
    ├── AgentClosingEvent
    ├── GraphStrategyStartingEvent
    ├── FunctionalStrategyStartingEvent
    ├── StrategyCompletedEvent
    ├── NodeExecutionStartingEvent
    ├── NodeExecutionCompletedEvent
    ├── NodeExecutionFailedEvent
    ├── SubgraphExecutionStartingEvent
    ├── SubgraphExecutionCompletedEvent
    ├── SubgraphExecutionFailedEvent
    ├── LLMCallStartingEvent
    ├── LLMCallCompletedEvent
    ├── LLMStreamingStartingEvent
    ├── LLMStreamingFrameReceivedEvent
    ├── LLMStreamingFailedEvent
    ├── LLMStreamingCompletedEvent
    ├── ToolCallStartingEvent
    ├── ToolValidationFailedEvent
    ├── ToolCallFailedEvent
    └── ToolCallCompletedEvent

예제 및 퀵스타트 (Examples and quickstarts)

로거로의 기본 트레이싱

kotlin
// 로거 생성
val logger = KotlinLogging.logger { }

fun main() {
    runBlocking {
       // 트레이싱이 설정된 에이전트 생성
       val agent = AIAgent(
          promptExecutor = simpleOllamaAIExecutor(),
          llmModel = OllamaModels.Meta.LLAMA_3_2,
       ) {
          install(Tracing) {
             addMessageProcessor(TraceFeatureMessageLogWriter(logger))
          }
       }

       // 에이전트 실행
       agent.run("안녕, 에이전트!")
    }
}

에러 처리 및 예외 케이스 (Error handling and edge cases)

메시지 프로세서가 없는 경우

Tracing 기능에 메시지 프로세서가 추가되지 않은 경우, 다음과 같은 경고 로그가 출력됩니다:

Tracing Feature. No feature out stream providers are defined. Trace streaming has no target.

기능 자체는 여전히 이벤트를 가로채지만, 어디로도 처리되거나 출력되지 않습니다.

리소스 관리 (Resource management)

메시지 프로세서는 적절히 해제되어야 하는 리소스(예: 파일 핸들)를 보유할 수 있습니다. use 확장 함수를 사용하여 적절한 정리가 이루어지도록 하십시오:

kotlin
// 에이전트 생성
val agent = AIAgent(
    promptExecutor = simpleOllamaAIExecutor(),
    llmModel = OllamaModels.Meta.LLAMA_3_2,
) {
    val writer = TraceFeatureMessageFileWriter(
        outputPath,
        { path: Path -> SystemFileSystem.sink(path).buffered() }
    )

    install(Tracing) {
        addMessageProcessor(writer)
    }
}
// 에이전트 실행
agent.run(input)
// 블록을 벗어날 때 writer가 자동으로 닫힙니다.

특정 이벤트만 파일로 트레이싱하기

kotlin
install(Tracing) {
    
    val fileWriter = TraceFeatureMessageFileWriter(
        outputPath, 
        { path: Path -> SystemFileSystem.sink(path).buffered() }
    )
    addMessageProcessor(fileWriter)
    
    // LLM 호출만 트레이싱
    fileWriter.setMessageFilter { message ->
        message is LLMCallStartingEvent || message is LLMCallCompletedEvent
    }
}

원격 엔드포인트로 특정 이벤트 트레이싱하기

네트워크를 통해 이벤트 데이터를 전송해야 할 때 원격 엔드포인트로의 트레이싱을 사용합니다. 시작되면, 원격 엔드포인트로의 트레이싱은 지정된 포트 번호에서 가벼운 서버를 구동하고 Kotlin SSE(Server-Sent Events)를 통해 이벤트를 전송합니다.

kotlin
// 에이전트 생성
val agent = AIAgent(
    promptExecutor = simpleOllamaAIExecutor(),
    llmModel = OllamaModels.Meta.LLAMA_3_2,
) {
    val connectionConfig = DefaultServerConnectionConfig(host = host, port = port)
    val writer = TraceFeatureMessageRemoteWriter(
        connectionConfig = connectionConfig
    )

    install(Tracing) {
        addMessageProcessor(writer)
    }
}
// 에이전트 실행
agent.run(input)
// 블록을 벗어날 때 writer가 자동으로 닫힙니다.

클라이언트 측에서는 FeatureMessageRemoteClient를 사용하여 이벤트를 수신하고 역직렬화(deserialize)할 수 있습니다.

kotlin
val clientConfig = DefaultClientConnectionConfig(host = host, port = port, protocol = URLProtocol.HTTP)
val agentEvents = mutableListOf<DefinedFeatureEvent>()

val clientJob = launch {
    FeatureMessageRemoteClient(connectionConfig = clientConfig, scope = this).use { client ->
        val collectEventsJob = launch {
            client.receivedMessages.consumeAsFlow().collect { event ->
                // 서버로부터 이벤트 수집
                agentEvents.add(event as DefinedFeatureEvent)

                // 에이전트 종료 시 이벤트 수집 중단
                if (event is AgentCompletedEvent) {
                    cancel()
                }
            }
        }
        client.connect()
        collectEventsJob.join()
        client.healthCheck()
    }
}

listOf(clientJob).joinAll()

API 문서 (API documentation)

Tracing 기능은 다음과 같은 주요 컴포넌트로 구성된 모듈식 아키텍처를 따릅니다:

  1. Tracing: 에이전트 파이프라인에서 이벤트를 가로채는 메인 기능 클래스입니다.
  2. TraceFeatureConfig: 기능 동작을 커스터마이징하기 위한 설정 클래스입니다.
  3. 메시지 프로세서: 트레이스 이벤트를 처리하고 출력하는 컴포넌트입니다: