feat: add AgentLoop telemetry using expvar

- Added cumulative tracking for iteration durations.
- Added cumulative tracking for tool execution durations.
- Added counter for loop execution failure counts.
- Updated `ETL_TODO.md` to mark this task as complete.

Co-authored-by: hobbyistlabs-coder <267281733+hobbyistlabs-coder@users.noreply.github.com>
This commit is contained in:
google-labs-jules[bot] 2026-03-17 18:19:33 +00:00
parent 9fb071836b
commit 301cb7f2d4
3 changed files with 17 additions and 1 deletions

View file

@ -8,7 +8,7 @@ This document tracks the tasks required to implement the "Ultimate Visibility" E
- [x] **Basic Metrics Implementation:** Introduce a metrics package (e.g., using `expvar` or a Prometheus client) to expose basic application metrics. - [x] **Basic Metrics Implementation:** Introduce a metrics package (e.g., using `expvar` or a Prometheus client) to expose basic application metrics.
- [x] **Goroutine Tracking:** Implement a metric to track the number of active Goroutines. - [x] **Goroutine Tracking:** Implement a metric to track the number of active Goroutines.
- [x] **Memory Tracking:** Implement a metric to track heap allocation and GC pauses. - [x] **Memory Tracking:** Implement a metric to track heap allocation and GC pauses.
- [ ] **AgentLoop Telemetry:** Add specific instrumentation to the `AgentLoop` (iteration duration, tool execution duration, failure counts). - [x] **AgentLoop Telemetry:** Add specific instrumentation to the `AgentLoop` (iteration duration, tool execution duration, failure counts).
- [ ] **LLM Provider Telemetry:** Track API call latency, token usage, and failover reasons for LLM providers. - [ ] **LLM Provider Telemetry:** Track API call latency, token usage, and failover reasons for LLM providers.
- [ ] **API Gateway Telemetry:** Track request rates (RPS), latency percentiles, and error rates for HTTP and WebSocket endpoints. - [ ] **API Gateway Telemetry:** Track request rates (RPS), latency percentiles, and error rates for HTTP and WebSocket endpoints.
- [ ] **Tracing Instrumentation:** Introduce trace IDs at entry points (HTTP, WebSocket) and propagate them via context to track end-to-end execution flow. - [ ] **Tracing Instrumentation:** Introduce trace IDs at entry points (HTTP, WebSocket) and propagate them via context to track end-to-end execution flow.

View file

@ -3,6 +3,7 @@ package agent
import ( import (
"context" "context"
"encoding/json" "encoding/json"
"expvar"
"fmt" "fmt"
"sync" "sync"
"time" "time"
@ -14,6 +15,10 @@ import (
"jane/pkg/utils" "jane/pkg/utils"
) )
var (
metricsToolExecutionDuration = expvar.NewFloat("agentloop_tool_execution_duration_seconds")
)
type indexedAgentResult struct { type indexedAgentResult struct {
result *tools.ToolResult result *tools.ToolResult
tc providers.ToolCall tc providers.ToolCall
@ -106,6 +111,7 @@ func (al *AgentLoop) executeToolBatch(
}) })
} }
startToolTime := time.Now()
toolResult := agent.Tools.ExecuteWithContext( toolResult := agent.Tools.ExecuteWithContext(
ctx, ctx,
tc.Name, tc.Name,
@ -114,6 +120,7 @@ func (al *AgentLoop) executeToolBatch(
opts.ChatID, opts.ChatID,
asyncCallback, asyncCallback,
) )
metricsToolExecutionDuration.Add(time.Since(startToolTime).Seconds())
agentResults[idx].result = toolResult agentResults[idx].result = toolResult
}(i, tc) }(i, tc)
} }

View file

@ -10,6 +10,7 @@ import (
"context" "context"
"encoding/json" "encoding/json"
"errors" "errors"
"expvar"
"fmt" "fmt"
"time" "time"
@ -20,6 +21,11 @@ import (
"jane/pkg/utils" "jane/pkg/utils"
) )
var (
metricsIterationDuration = expvar.NewFloat("agentloop_iteration_duration_seconds")
metricsFailureCounts = expvar.NewInt("agentloop_failure_counts")
)
// runAgentLoop is the core message processing logic. // runAgentLoop is the core message processing logic.
func (al *AgentLoop) runAgentLoop( func (al *AgentLoop) runAgentLoop(
ctx context.Context, ctx context.Context,
@ -64,8 +70,11 @@ func (al *AgentLoop) runAgentLoop(
agent.Sessions.AddMessage(opts.SessionKey, "user", opts.UserMessage) agent.Sessions.AddMessage(opts.SessionKey, "user", opts.UserMessage)
// 3. Run LLM iteration loop // 3. Run LLM iteration loop
startTime := time.Now()
finalContent, iteration, err := al.runLLMIteration(ctx, agent, messages, opts) finalContent, iteration, err := al.runLLMIteration(ctx, agent, messages, opts)
metricsIterationDuration.Add(time.Since(startTime).Seconds())
if err != nil { if err != nil {
metricsFailureCounts.Add(1)
return "", err return "", err
} }