chaojixinren opened a new pull request, #1536:
URL: https://github.com/apache/dubbo-admin/pull/1536
## Summary
Introduces a config-driven, telemetry-agnostic **agent hooks** system in
`ai/`, with
**logging** and **OpenTelemetry (OTLP) tracing** as the first observers. It
instruments
the full ReAct lifecycle — interaction, iteration, stage, model call, and
tool call —
without coupling the strategy code to any specific backend.
## Motivation
Resolves #1525. There was previously no consistent way to observe agent
execution or trace
a request end-to-end across the Agent ↔ MCP boundary, making agent behavior
hard to debug
and spans impossible to correlate.
## What changed
- **Hook manager** (`ai/component/hooks/`): immutable lifecycle events
(`interaction / iteration / stage / model_call / tool_call` × `start /
end`), read-only
`State` snapshots, per-event registration, and panic isolation per hook.
- **Context derivation**: hooks may derive a `context.Context` for nested
work; exactly one
`DerivesContext` registration is accepted (a Go context carries one span
lineage — fan out
via a Collector instead). Contexts returned by plain observational hooks
are ignored.
- **Tracing hook**: OTLP exporter (gRPC or HTTP/protobuf) with GenAI
semantic attributes
(`gen_ai.operation.name`, `gen_ai.request.model`, `gen_ai.provider.name`,
`gen_ai.conversation.id`, `gen_ai.tool.name`, `gen_ai.tool.call.id`,
`gen_ai.input/output.messages`, `gen_ai.usage.*`, `agent.fallback.*`,
`error.type`, …).
Content is serialized lazily only when the span `IsRecording()`, and
content capture is
**opt-in** (`capture_content: none` default; `truncated` ≤ 4096 bytes;
`full`).
- **Logging hook**: structured lifecycle logging with the same opt-in
content capture.
- **Trace propagation**: W3C `traceparent` / `tracestate` / `baggage` are
honored inbound,
propagated to MCP HTTP calls, and the active trace ID is returned on SSE
responses via
`X-Trace-ID` (CORS-exposed).
- **Fallback metadata**: timeout vs parse-error are distinguished
(`FallbackReason`), written
to both the model-call span and the stage span, with correct `Evidence`
text; tool failures
are recorded as `error.type` + `agent.degraded` without faking a
`gen_ai.tool.call.result`.
- **Cancellation semantics**: `context.Canceled` propagates cleanly (only
`DeadlineExceeded`
is a timeout); SSE disconnect cancellation stays detached from the running
interaction.
- **Configuration**: `type: hooks` component with `logging` / `tracing`
blocks, JSON schema
validation, and standard OTel env vars for endpoint and credentials.
## Design constraints
- Hooks are **observational**: they read state and may derive context, but
must never mutate
Agent execution data.
- Content capture defaults to `none` for credential/PII safety; payloads are
not serialized
on the hot path unless a matching hook opts in.
- Tool-call hooks must explicitly select tool names (`"*"` for all).
## Agent Hooks + OTel Tracing — Completed Test Checklist
### 1. Unit Tests
- [x] `go test -count=1 ./...` — all passed (hooks, Agent, server engine,
MCP tools, runtime, etc.)
### 2. Integration Tests
- [x] `go test -tags=integration -count=1 ./...` — all passed
### 3. Race / Static Analysis
- [x] `go test -race ./component/hooks/... ./component/agent/...` — passed
- [x] `go vet ./...` — passed
### 4. E2E: Jaeger (OTLP)
- [x] Local Jaeger OTLP end-to-end passed
- [x] Trace ID: `f6477cd5b8d5a5cce9ae07a0ad1d8470`
### 5. E2E: Langfuse (Docker 4.11.0)
- [x] Full stack via official Compose; OTLP/HTTP ingestion succeeded
- [x] v2 Observations API: HTTP 200
- [x] Correct hierarchy: `AGENT invoke_agent` → `GENERATION chat qwen-max` →
`TOOL lookup_service`
- [x] Confirmed in ClickHouse `events_full`: model input/output, 7/5/12
tokens, session ID, tool call ID
- [x] 3 observations written in total
- [x] Trace ID: `fdc809bacdcdbf5b7cd7798ba8f7c1cb`
### 6. Performance Benchmarks (0 allocs)
| Benchmark | Result |
| --- | --- |
| `BenchmarkDisabledHookFastPath` | 2.967 ns/op · 0 allocs |
| `BenchmarkEmptyManagerFastPath` | 8.943 ns/op · 0 allocs |
| `BenchmarkHookContentDisabled` | 34.23 ns/op · 0 allocs |
| `BenchmarkHookContentLoggingOnly` | 34.68 ns/op · 0 allocs |
### 7. Cleanup
- [x] Temporary test files removed
- [x] Jaeger / Langfuse containers and dedicated Docker network removed
- [x] No code or commit changes; HEAD remains `7bbcab1`
---
### ⚠️ Environment Gaps (out of scope for this issue — not completed)
- Hosted Langfuse cloud E2E — requires credentials
- External DashScope E2E — requires credentials; `TestMultiTurnConversation`
therefore shows 0/14
- External Milvus E2E — requires credentials
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: [email protected]
For queries about this service, please contact Infrastructure at:
[email protected]
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]