feat(ai): add agent hooks and OpenTelemetry tracing - #1536
Conversation
…ition (apache#1314) * feat: informer general framework and engine/discovery interface definition
* fix: ci probelm; diretory and dependency tidy * fix: lack license header * rm: remove redundant file
* ci(makefile): add makefile for ci * style(ci): rename dubbo-admin ci
…1325) * fix: refractor web handler and service to fix compile error;
* feat: support memory type of store * fix: muilti indexes should use intersecection * simplify code Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> * refractor: GetByKeys return a list instead of map --------- Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
* feat: implement runtime engine using kubernetes
* feat: unified error code; separate application handler and service into parts * fix: license header lack * fix: copilot review err fix * fix: simplify the if-else condition * chore: rename Error() to String() * chore: add extra String() in Error * feat: 新增listMeshes接口 * fix: copilot review
… more accurately (apache#1355)
* feat(apache#1352): Support multiple registries: add registry select box and refresh main area on change * doc(build): build ui * fix(apache#1352): Set first available mesh after login when no mesh is set * doc(build): build ui * fix(conflict) * doc(build): build ui
* feat: implement mysql and postgresql store for resources * fix some issues * ut: add some test cases * fix: dynamic table name
* feat: support nacos2 to do discovery * refractor: abstract nacos and nacos service * fix: unit test and license header * fix: copilot review problem * chore: remove redundant code
* fix: add indexer before init cause npe * fix: unit test
…from API (apache#1373) * feat: enhance error handling for unauthorized access and improve toast messages * feat: enhance error handling for unauthorized access and improve toast messages * fix: correct syntax error in response interceptor for redirect handling * Update ui-vue3/src/base/http/request.ts Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> * feat: add YAML and XML editor components, update index references, and enhance error logging - Introduced new JavaScript files for YAML and XML syntax highlighting and editing capabilities. - Added a new component for updating YAML configurations with a structured editor interface. - Updated the index.html to reference the new JavaScript bundle for improved functionality. - Enhanced the HTTP request module to log errors during redirection on 401 responses for better debugging. --------- Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
* feat: implements discovery backend by zk
* feat: support components to start in dependency order * imporve * fix * fix error import
* changelog * chore: rename refactor to enhancements
* feat: enhance error handling for unauthorized access and improve toast messages * feat: enhance error handling for unauthorized access and improve toast messages * fix: correct syntax error in response interceptor for redirect handling * Update ui-vue3/src/base/http/request.ts Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> * feat: add YAML and XML editor components, update index references, and enhance error logging - Introduced new JavaScript files for YAML and XML syntax highlighting and editing capabilities. - Added a new component for updating YAML configurations with a structured editor interface. - Updated the index.html to reference the new JavaScript bundle for improved functionality. - Enhanced the HTTP request module to log errors during redirection on 401 responses for better debugging. * docs: Only supports exact matching; remove the "prefix search" function from the placeholder (background word) * docs: All sorting indicators for lists are initially hidden, including but not limited to the list pages for applications, instances, services, and traffic management * refactor: 🎨 Optimize the styles of some tables and adapt to backend changes * docs: api baseurl --------- Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
apache#1383) * build: Optimize the styles of some tables, adapt to backend changes, format the code, and package it * chore: remove PR_DESCRIPTION.md file as it is no longer needed * fix: update routing rule handling updated routing rule handling to use constants for HTTP status codes in various components. * build: build & format
…pache#1385) * build: Optimize the styles of some tables, adapt to backend changes, format the code, and package it * chore: remove PR_DESCRIPTION.md file as it is no longer needed * fix: update routing rule handling updated routing rule handling to use constants for HTTP status codes in various components. * build: build & format * feat: enhance error handling and data loading in various components - Added a silent error handling mechanism for specific URLs in the HTTP request module to suppress error messages. - Refactored data loading logic in sceneConfig.vue to load configuration data based on the selected tab, improving user experience. - Updated YAMLView.vue and other components to remove unused button code and optimize imports, enhancing code clarity and maintainability. - Improved error handling in routingRule and dynamicConfig components to ensure better user feedback and debugging. * feat: add new components and enhance YAML and XML editing capabilities - Introduced new JavaScript files for YAML and XML syntax highlighting and editing. - Added components for updating YAML configurations with structured editor interfaces. - Updated index.html to reference new JavaScript bundles for improved functionality. - Enhanced error handling and logging in various components for better debugging. - Removed unused code and optimized imports in YAMLView and related components.
…1378) * fix: console interfaces;feat: implements governor using zk and nacos * fix: instance subscriber * fix: unit-test * fix: rules search * resolve conflicts * fix: backend bugs * fix: rule handler and service refactor * fix: config error andd field mapping * fix: rename msg to message * fix: wrap prometheus error * fix ci
…pache#1387) * feat: add monitoring/dubbo-samples-shop/dubbo-system resources * fix: metric, trace dashboard bug
* build: Optimize the styles of some tables, adapt to backend changes, format the code, and package it * chore: remove PR_DESCRIPTION.md file as it is no longer needed * fix: update routing rule handling updated routing rule handling to use constants for HTTP status codes in various components. * build: build & format * feat: enhance error handling and data loading in various components - Added a silent error handling mechanism for specific URLs in the HTTP request module to suppress error messages. - Refactored data loading logic in sceneConfig.vue to load configuration data based on the selected tab, improving user experience. - Updated YAMLView.vue and other components to remove unused button code and optimize imports, enhancing code clarity and maintainability. - Improved error handling in routingRule and dynamicConfig components to ensure better user feedback and debugging. * feat: add new components and enhance YAML and XML editing capabilities - Introduced new JavaScript files for YAML and XML syntax highlighting and editing. - Added components for updating YAML configurations with structured editor interfaces. - Updated index.html to reference new JavaScript bundles for improved functionality. - Enhanced error handling and logging in various components for better debugging. - Removed unused code and optimized imports in YAMLView and related components. * feat: enhance UI components and improve error handling - Added global styles for clickable links in tables to improve user interaction. - Updated routing logic to utilize a dynamic header parameter key for better flexibility. - Enhanced error handling in HTTP requests to suppress messages for specific URLs. - Improved internationalization by adding new translation keys for 'Ready Time' in both English and Chinese. - Refactored various components to optimize code structure and maintainability, including updates to YAML and form views. - Adjusted table and form layouts for better responsiveness and user experience. * refactor: streamline component code and enhance condition handling - Simplified iframe rendering in GrafanaPage.vue for improved readability. - Added checks in ConfigModel.ts to skip undefined keys in matches and parameters. - Optimized YAMLView.vue by condensing MonacoEditor properties for better clarity. - Cleared default request and address matching arrays in formView.vue for cleaner initialization. - Enhanced condition parsing and merging logic in updateByFormView.vue to improve maintainability and readability. * build: build admin
…rule management (apache#1394) * build: Optimize the styles of some tables, adapt to backend changes, format the code, and package it * chore: remove PR_DESCRIPTION.md file as it is no longer needed * fix: update routing rule handling updated routing rule handling to use constants for HTTP status codes in various components. * build: build & format * feat: enhance error handling and data loading in various components - Added a silent error handling mechanism for specific URLs in the HTTP request module to suppress error messages. - Refactored data loading logic in sceneConfig.vue to load configuration data based on the selected tab, improving user experience. - Updated YAMLView.vue and other components to remove unused button code and optimize imports, enhancing code clarity and maintainability. - Improved error handling in routingRule and dynamicConfig components to ensure better user feedback and debugging. * feat: add new components and enhance YAML and XML editing capabilities - Introduced new JavaScript files for YAML and XML syntax highlighting and editing. - Added components for updating YAML configurations with structured editor interfaces. - Updated index.html to reference new JavaScript bundles for improved functionality. - Enhanced error handling and logging in various components for better debugging. - Removed unused code and optimized imports in YAMLView and related components. * feat: enhance UI components and improve error handling - Added global styles for clickable links in tables to improve user interaction. - Updated routing logic to utilize a dynamic header parameter key for better flexibility. - Enhanced error handling in HTTP requests to suppress messages for specific URLs. - Improved internationalization by adding new translation keys for 'Ready Time' in both English and Chinese. - Refactored various components to optimize code structure and maintainability, including updates to YAML and form views. - Adjusted table and form layouts for better responsiveness and user experience. * refactor: streamline component code and enhance condition handling - Simplified iframe rendering in GrafanaPage.vue for improved readability. - Added checks in ConfigModel.ts to skip undefined keys in matches and parameters. - Optimized YAMLView.vue by condensing MonacoEditor properties for better clarity. - Cleared default request and address matching arrays in formView.vue for cleaner initialization. - Enhanced condition parsing and merging logic in updateByFormView.vue to improve maintainability and readability. * build: build admin * fix: improve error handling and UI updates in GrafanaPage and sceneConfig components - Added conditional checks in GrafanaPage.vue to ensure valid baseURL before constructing the Grafana URL. - Enhanced iframe loading logic to prevent errors when accessing undefined elements. - Updated service.vue to handle potential undefined values in versionGroups, ensuring robust data handling. - Refactored sceneConfig.vue to improve the user experience by adding a conditional rendering for parameter routes, including a message for empty configurations and a button for adding new routes. * refactor: Request to update the Grafana URL * build: build * ♻️ refactor: update route parameters to include name and make pathId/appName optional Update routing structure across instance and traffic management views to: - Add :name parameter to routes for better identification - Make :pathId and :appName optional parameters (with ?) - Affects instance detail, monitor, link tracking, and configuration tabs - Updates dynamic config, routing rule, and tag rule views accordingly This change provides more flexible routing and better resource identification. Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com> * ✨ feat(routing): add routing rule list component and composable Add new RoutingRuleList component and useRoutingRule composable to manage routing rule configurations. Updates addByFormView and updateByFormView to integrate with the new components. Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com> * build: format & build * ✨ feat(routing): enhance routing rule form with comprehensive i18n support Enhance routing rule form functionality with improved internationalization, user interface refinements, and better form handling. - Add comprehensive i18n translations for routing rule fields - Improve form layout and field descriptions - Enhance routing rule list component with better UX - Refactor routing rule composable for better maintainability - Update tab header slots for improved navigation Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com> * build: format & build --------- Co-authored-by: Claude Sonnet 4.5 <noreply@anthropic.com>
* fix: create tag rule bug * refactor: config refactor; fix: fix console bugs * fix: instance disable traffic * fix: CI promblems * fix: typo
* implement counter by key * chore: trigger CI * Fix counter initialization errors and mesh change detection logic --------- Co-authored-by: WyRainBow <your-email@example.com>
…rain (apache#1455) * feat(eventbus): support per-subscriber async dispatch with graceful drain * refactor(config): unify AdminConfig method receivers as pointers * refactor(eventbus): move AsyncEnabled into Subscriber with docs * fix(config): keep read-only helpers on value receiver * refactor(config): unify AdminConfig receiver style
* feat(ui): Added application and service topology mapping feature * style(ui-vue3): Add a minimum width to the login form and remove unnecessary blank lines * Feat: Add service and application topology graph APIs based on discussion apache#1398 * feat(api): add GraphServices endpoint for service-level topology Based on discussion apache#1398, use ServiceProviderMetadata and ServiceConsumerMetadata to return provider/consumer application relations as graph nodes and edges for AntV G6. * feat(api): add GraphApplications endpoint for application-level topology Traverse provider/consumer service relations to build application-level graph. Also add idx_service_consumer_service_key index to support efficient serviceKey queries. * feat(api): add graph models (GraphNode, GraphEdge, GraphData) in pkg/console/model/graph.go * feat(api): add ApplicationGraphReq, ServiceGraphReq and GetApplicationGraph, GetServiceGraph handlers * feat(router): register /application/graph and /service/graph routes * feat(api): fix error handling to use direct err pass-through instead of MeshNotFoundError * Feat: Enhance service metadata derivation and detail retrieval ([apache#1430](apache#1430)) * feat(api): replace Service.{providers,consumers,features} with {methods} field Simplify Service proto by removing providers, consumers, and features map, keeping only the aggregated methods list derived from provider metadata. * feat(api): derive Service resource from ServiceProviderMetadata on add/update/delete ServiceProviderMetadataEventSubscriber now maintains Service resources by aggregating methods from all provider instances sharing the same serviceKey. Handles add, update, and delete events to keep Service spec in sync. * feat(api): add language detection from provider metadata parameters Detect provider language (golang/java) from metadata parameters and method type signatures when explicit language field is absent. * feat(api): add GetServiceDetail endpoint returning language and methods Add GET /service/detail returning ServiceDetailResp with language and aggregated method names from the derived Service resource. * feat(api): add BuildServiceIdentityKey helper for {service}:{version}:{group} * feat(api): add ByServiceName index for ServiceKind * feat(api): refactor SearchServices to query ServiceResource directly SearchServices and SearchServicesByKeywords now use ServiceResource instead of ServiceProviderMetadataResource for service listing. * feat(api): remove providerAppName from ServiceSearchResp and ServiceTabDistributionReq * feat(api): add ServiceDetailReq and ServiceDetailResp models * feat(router): register /service/detail and /service/interfaces routes * feat(ui-vue3): remove providerAppName from grafana types and tab components * chore: Add G6 chart library and its dependencies to the project * chore(assets): Add Apache license and format code for iconfont file * fix: Correct the naming errors in the application topology graph API parameters and improve the code comments * chore: minor cleanup - fix comment language and import order * chore: translate Chinese comment to English in GraphApplications error handling * chore: reorder imports in service_provider_metadata.go * fix:Fix parameter passing error when obtaining application details * fix: fix type mismatch and index issues in service search and metadata sync 1. pkg/console/service/service.go:132 - fix generic type mismatch with resourceKind - generic ServiceResource should use ServiceKind, was incorrectly passing ServiceProviderMetadataKind - index changed from ByServiceProviderServiceName to ByServiceName (aligned with ServiceKind) 2. pkg/core/discovery/subscriber/service_provider_metadata.go - processUpdate: remove redundant oldRes key check (oldKey always equals newKey in same resource update, else branch is unreachable dead code) - syncService: use ByServiceProviderServiceKey index instead of ByServiceProviderServiceName + manual version/group filtering, reduces data returned from DB and improves performance Ref: [1460](apache#1460 (comment)) * Feat: Add coding agent domain skills ([apache#1457](apache#1457)) * feat(skills): add backend domain skills for runtime, discovery, engine, events, store, and Console API Document component lifecycle, ListAndWatch discovery, resource engine behavior, EventBus dispatching, storage indexes, and Web MVC flow for coding agents. * feat(skills): add frontend domain skill for routing, components, and traffic rule forms Document Vue frontend structure, API clients, Pinia state, route metadata, layout tabs, and traffic rule form design. * feat(skills): add OpenAI skill metadata Add agents/openai.yaml metadata for each dubbo-admin domain skill. * fix(console): use ServiceKind for service list search Query ServiceResource from ServiceKind instead of ServiceProviderMetadataKind so the non-keyword service list path uses the matching resource store and index set. --------- Co-authored-by: sohandsomejie <3080955413@qq.com> Co-authored-by: MoChengqian <2972013548@qq.com>
…1477) * chore(store): add ListResources + align gorm/memory empty-index semantics * fix(discovery): nil-guard zk rule delete + emit registry context on events * feat(versioning): backend immutable release ledger for traffic rules * feat(versioning): UI history drawer, diff, and rollback for rule pages * test(versioning): end-to-end rollback drill * fix(versioning): close gaps surfaced by the smoke drill Running the §9.4 smoke drill end-to-end uncovered three real defects that the unit suite did not catch: - RuleVersionSubscriber recorded a duplicate UPSTREAM row whenever the registry echoed back a no-op change identical to the latest ledger row (typically right after BOOTSTRAP). Now dedupes upstream events whose content hash already matches the current head, with an explicit test in versioning_test.go. - writeVersioningResp mapped every bizerror to HTTP 200/UnknownError; bizerror.InvalidArgument (eg. empty rollback reason) now returns HTTP 400 with its original code so the frontend can act on it. Covered by a new handler/rule_version_test.go. - The 409 VERSION_CONFLICT toast auto-dismissed after the default duration; users could miss the Reload button entirely. Pinned with duration: 0 so the notification stays until acknowledged. * fix(traffic): preserve priority/force/configVersion on rule edit forms The §9.4 smoke drill expectation "after rollback, the rule should look the same on UI refresh" exposed a pre-existing edit-form regression: rollback was correct at the ledger and ZK levels, but the edit form silently dropped `priority`, `force`, and (for condition routes) `configVersion` because they were neither rendered in the GET response nor re-sent on save. This is not caused by versioning, but a true round-trip is the first flow that forces every field through the loop. Adds the missing fields to ConditionRuleResp / TagRuleResp on the backend, and reads/writes them in updateByFormView.vue on the frontend so a "save → rollback → reload" cycle is now lossless. * chore: ignore local planning artifacts Add /task_plan.md /findings.md /progress.md to .gitignore so the planning-with-files workflow does not leak per-developer working memory into the repo. * fix(versioning): close owner review correctness gaps * refactor(versioning): drop unused helpers and aliases * fix(ui): plug rule diff editor leaks * Remove local working memory files from .gitignore * fix(versioning): add intent repair and abandon flows * Revert "feat: support traffic rule version history and rollback" * fix(lock): use acquisition-scoped leases * refactor(versioning): split resource store responsibilities * refactor(versioning): normalize events and reduce repair APIs * fix(lock): stop writes after lease loss * refactor(ui): remove unreachable state and simplify mocks * test(versioning): add multi-instance and lease failure coverage * docs(versioning): update default-enabled guarantees * fix: address rule versioning review blockers - require lease contexts for rule versioning mutations - propagate contexts through resource manager and governor writes - move repair/bootstrap reads inside rule locks - use ledger snapshots for current and deleted state - remove unused subscriber intent token path - simplify rollback commit handling and add UI coverage * fix: harden rule versioning correctness * fix: address rule versioning review issues * Fix rule version commit terminal semantics * fix(versioning): harden rule intent recovery * fix(versioning): close intent recovery race windows * Fix rule intent storage CAS and subscriber fallback * Fix rule version committing recovery ordering * Fix Go CI cache restore * Clean up PR-only test files * docs(versioning): clarify invariants and recovery comments * 20 maxVersion is suitable * chore: limit rule version retention to 20 * refactor: simplify rule version history * refactor: restore core mutation and lock interfaces * refactor: enforce lightweight rule history semantics * refactor: clean rule history frontend semantics * docs: describe lightweight rule history config * test: add frontend npm test script * fix: address copilot review comments * fix: make rule versioning fail closed * refactor: collapse versioning store abstraction * refactor: reuse resource helpers in rule versioning - move resource key parsing next to BuildResourceKey - centralize live rule lookup in console version service - deduplicate RuleVersion resource conversion/sorting helpers - no behavior/API/storage semantic changes * fix: address traffic rule history review blockers * fix: clear traffic view type errors * fix: address remaining rule version review comments * fix: add license header to js-yaml declaration * style: refine version record tag and layout in traffic rule views
…he#1472 (apache#1487) * Feat: Add event timeline for application/instance/service with K8s event ingestion ([apache#1472](apache#1472)) - Add K8sEvent resource type (proto + Go spec) and store indexes - Add K8sEventListerWatcher to watch K8s /api/v1/events via client-go - Register K8sEventListerWatcher in Kubernetes EngineFactory - Add /application/event, /instance/event, /service/event console API endpoints - Add EventTimeline shared Vue component with normal/warning node styles - Wire up event tabs for application, instance, and service detail pages - Un-hide event tab routes in frontend router - Add mock event handlers for development - Add PlatformEvent resource type (platformevent_types.go) with store indexes - Add shared platform_event_recorder utility for event recording - Record ZK config change events (tag-route, condition-route, dynamic-config) - Record ZK metadata events (provider/consumer metadata added/updated) - Record Nacos instance registration/deregistration events - Record Nacos consumer metadata change events - Merge K8s events and Platform events into unified timeline in event query service - Downgrade "no subscriber" log level from INFO to DEBUG to reduce log noise * Fix: Address review feedback for K8s event timeline — zero timestamps, watch spam, silent drops, delete-before-add - K8sEventListerWatcher: check IsZero() before formatting FirstTimestamp/LastTimestamp to avoid emitting synthetic "0001-01-01 00:00:00" values that break timeline ordering. - EventTimeline.vue: remove unconditional watch() that triggered cascading loadMore calls; rely solely on IntersectionObserver for scroll-based pagination. - RecordRegistryEvent: log a warning when dropping events due to empty Mesh or Message instead of silently discarding them. - K8sEventSubscriber.writeEvent: delete the informer-written (original-key) entry only after a successful Add of the timestamp-prefixed entry, preventing permanent event loss when Add fails. * Refactor: Rename K8sEvent to LifecycleEvent for unified event model K8sEvent was originally named for K8s-sourced events only, but now also carries registry-side events (ZK/Nacos) via the EventSource discriminator. Rename to LifecycleEvent to accurately reflect its role as a unified lifecycle event type covering both K8s and registry origins. - Proto: K8sEvent → LifecycleEvent - Resource: K8sEventResource → LifecycleEventResource - Kind: K8sEventKind → LifecycleEventKind - Subscriber: K8sEventSubscriber → LifecycleEventSubscriber - Index constants: ByK8sEvent* → ByLifecycleEvent* - Files: k8s_event.* → lifecycle_event.* - Retained: K8sEventListerWatcher (K8s-specific component)
|
@ambiguous-pointer please help review this PR. |
There was a problem hiding this comment.
Pull request overview
Adds configurable agent lifecycle hooks and OpenTelemetry tracing across the ReAct, SSE, MCP, and runtime layers.
Changes:
- Introduces hook management, logging, OTLP tracing, and content-capture policies.
- Instruments agent/model/tool lifecycles with propagation and fallback metadata.
- Adds shutdown handling, configuration, and extensive tests.
Reviewed changes
Copilot reviewed 39 out of 40 changed files in this pull request and generated 2 comments.
Show a summary per file
| File | Description |
|---|---|
ai/test/e2e/e2e_test.go |
Wires hooks into E2E runtime. |
ai/schema/json/hooks.schema.json |
Defines hooks configuration schema. |
ai/main.go |
Registers hooks and adjusts lifecycle order. |
ai/go.sum |
Records HTTP OTLP dependencies. |
ai/go.mod |
Adds OpenTelemetry dependencies. |
ai/config/test/loader_test.go |
Tests hooks configuration defaults. |
ai/config/loader.go |
Maps hooks to its schema. |
ai/config.yaml |
Enables the hooks component. |
ai/component/tools/engine/mcp_tools.go |
Propagates trace headers to MCP. |
ai/component/tools/engine/mcp_tools_test.go |
Tests outbound trace propagation. |
ai/component/server/engine/sse/sse.go |
Centralizes CORS handling. |
ai/component/server/engine/router.go |
Allows and exposes tracing headers. |
ai/component/server/engine/router_test.go |
Tests tracing CORS headers. |
ai/component/server/engine/handlers.go |
Propagates context and trace IDs. |
ai/component/server/engine/handlers_test.go |
Tests context and detached output handling. |
ai/component/hooks/tracing.go |
Implements lifecycle span creation. |
ai/component/hooks/tracing_test.go |
Tests spans, attributes, and capture. |
ai/component/hooks/README.md |
Documents hooks and OTLP setup. |
ai/component/hooks/manager.go |
Implements hook registration and dispatch. |
ai/component/hooks/manager_test.go |
Tests manager behavior and concurrency. |
ai/component/hooks/jaeger_e2e_test.go |
Adds optional Jaeger verification. |
ai/component/hooks/hooks.yaml |
Provides default hooks configuration. |
ai/component/hooks/factory.go |
Adds the hooks factory. |
ai/component/hooks/event.go |
Defines lifecycle events and snapshots. |
ai/component/hooks/component.go |
Implements hooks component lifecycle. |
ai/component/hooks/component_test.go |
Tests configuration and shutdown. |
ai/component/agent/react/steps.go |
Instruments stages, models, and tools. |
ai/component/agent/react/step_test.go |
Tests fallback and hook emissions. |
ai/component/agent/react/react.go |
Adds interaction tracing and draining. |
ai/component/agent/react/prompt.go |
Retains stage names and models. |
ai/component/agent/react/page_context_test.go |
Updates context construction test. |
ai/component/agent/react/orchestrator.go |
Instruments iterations and stages. |
ai/component/agent/react/orchestrator_test.go |
Tests lifecycle sequencing. |
ai/component/agent/react/lifecycle_test.go |
Tests cancellation and concurrency. |
ai/component/agent/react/hook_content.go |
Converts messages for telemetry. |
ai/component/agent/react/hook_content_test.go |
Tests semantic message conversion. |
ai/component/agent/react/component.go |
Connects hooks and agent lifecycle. |
ai/component/agent/react/component_wiring_test.go |
Tests hooks manager wiring. |
ai/component/agent/fallback/handler.go |
Reports fallback parsing usage. |
ai/component/agent/agent.go |
Adds context-aware interaction channels. |
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
7bbcab1 to
2acf02b
Compare
ambiguous-pointer
left a comment
There was a problem hiding this comment.
@chaojixinren 上述是我的一些个人拙见,可以按照您的设计进行实际的一些调整和修改 : )
There was a problem hiding this comment.
Go 1.26 下 sonic v1.14.1 无法编译, 请先行合入远程更改
| const ( | ||
| EventInteractionStart Event = "interaction.start" | ||
| EventInteractionEnd Event = "interaction.end" | ||
| EventIterationStart Event = "iteration.start" | ||
| EventIterationEnd Event = "iteration.end" | ||
| EventStageStart Event = "stage.start" | ||
| EventStageEnd Event = "stage.end" | ||
| EventModelCallStart Event = "model_call.start" | ||
| EventModelCallEnd Event = "model_call.end" | ||
| EventToolCallStart Event = "tool_call.start" | ||
| EventToolCallEnd Event = "tool_call.end" | ||
| ) |
There was a problem hiding this comment.
-
潜在问题:
- 没有错误/降级/取消类事件。工具失败、observe 超时/解析失败、显式取消,在 PR 里都只是
State上的字段(Degraded/FallbackUsed/Error)。对 tracing/logging 两个消费方够用(span 上有error.type、agent.degraded属性),
但对未来的 metrics / 审计类 hook(它们需要"按事件种类订阅")就缺了第一类公民:- 例:生产上想统计"每月 observe 超时次数"或"工具失败率",现在只能订阅
stage.end然后过滤State.FallbackUsed,
而不是订阅一个语义明确的agent.degraded事件;若未来事件字段演进,这类消费方会静默错算。
- 例:生产上想统计"每月 observe 超时次数"或"工具失败率",现在只能订阅
- 没有错误/降级/取消类事件。工具失败、observe 超时/解析失败、显式取消,在 PR 里都只是
-
个人建议: 事件种类扩展为
agent/stage/llm/tool × start/end/error+agent.degraded+
agent.cancel+llm.chunk(预留),并给State增加Seq uint64。事件字段只读约定保持。因为模型部署侧可能不一定都是稳定的模型,例如 VLLM 私有化部署的时候,工具调用参数模板没有绑定正确的时候,调用工具会出现偶发性的直接中断。所以会需要预设详细一些 -
生产场景:Dubbo 服务诊断场景(agent 通过 MCP 调
get_service_detail/诊断工具 feat: add PromQL and trace diagnosis tools #1499)——SRE 想要"按工具维度"的失败率报表,若没有独立tool.error事件种类,报表逻辑要散落在每个消费方里重复过滤,接入点越多越容易漏。
| type lazyContentSnapshot struct { | ||
| once sync.Once | ||
| provider func() any | ||
| content string | ||
| } | ||
|
|
||
| func newLazyContentSnapshot(provider func() any) *lazyContentSnapshot { | ||
| if provider == nil { | ||
| return nil | ||
| } | ||
| return &lazyContentSnapshot{provider: provider} | ||
| } | ||
|
|
||
| func (s *lazyContentSnapshot) snapshot() string { | ||
| if s == nil { | ||
| return "" | ||
| } | ||
| s.once.Do(func() { | ||
| s.content = SnapshotContent(s.provider()) | ||
| s.provider = nil | ||
| }) | ||
| return s.content | ||
| } | ||
|
|
||
| // WithInputContent attaches an immutable input snapshot that is materialized | ||
| // only if a matching content-capturing hook requests it. | ||
| func (s State) WithInputContent(provider func() any) State { | ||
| s.inputContent = newLazyContentSnapshot(provider) | ||
| return s | ||
| } | ||
|
|
||
| // WithOutputContent attaches an immutable output snapshot that is materialized | ||
| // only if a matching content-capturing hook requests it. | ||
| func (s State) WithOutputContent(provider func() any) State { | ||
| s.outputContent = newLazyContentSnapshot(provider) | ||
| return s | ||
| } | ||
|
|
||
| func (s State) snapshotInputContent() string { | ||
| if s.Input != "" { | ||
| return s.Input | ||
| } | ||
| return s.inputContent.snapshot() | ||
| } | ||
|
|
||
| func (s State) snapshotOutputContent() string { | ||
| if s.Output != "" { | ||
| return s.Output | ||
| } | ||
| return s.outputContent.snapshot() | ||
| } |
There was a problem hiding this comment.
- 潜在问题:
lazyContent字段(manager.go:44,96)只有包内NewTracingRegistration能用(未导出),
外部捕获内容的 hook 一律走manager.go:193-195的急切快照分支——也就是说"懒"只对内置 tracing hook 成立,对将来第三方内容型 hook(如审计)不成立。PR文档里"Content is serialized lazily"的表述容易误导。 - 个人建议:把
lazyContent语义并入公开的Registration(如CaptureContent: CaptureLazy)或至少在
Registration上注释清楚两档行为。 - 生产场景:审计 hook 需要"模型输入/输出原文"留档——如果它被急切序列化,每次模型调用都会多一次完整 JSON marshal(大对话可能几百 KB),生产热点路径上不可忽略;同时内容进内存=更大的 PII 暴露面。应能声明"延迟到真正落盘前才序列化"。
| defer func() { | ||
| if r := recover(); r != nil { | ||
| sseHandler.HandleError("internal_error", fmt.Sprintf("internal error: %v", r)) | ||
| } | ||
| }() |
There was a problem hiding this comment.
// ← 这里没有 go discardAgentOutput(channels)!
对比另外两条退出路径(handlers.go:104-107 和 134-136)
- handler 在流中途 panic(比如
MessageDelta遇到未知 final 类型、或任何将来加的代码); - defer recover 触发 → 发一条
internal_errorSSE → handler 返回 → gin 关连接; - 交互 goroutine 不会死——
interactionCtx := context.WithoutCancel(extractedCtx)(handlers.go:87)已经把请求取消剥掉了,客户端断开对它是透明的; - 交互 goroutine 继续生成,调用
chans.Send(agent.go:62-70):
func (chans *Channels) Send(sf *schema.StreamFeedback) {
sf.SetIndex(chans.nextIndex)
chans.nextIndex++
chans.UserRespChan <- sf // ← 有界阻塞发送,缓冲满就永久卡住
}- 缓冲(bufferSize)塞满 ~16 条后,没有任何人排空 → 交互 goroutine 永久阻塞在
Send; - 连锁反应:阻塞在
Send意味着 goroutine 的 defer 永远不执行——interaction.end事件发不出去(trace 缺尾)、finishInteraction不执行(ra.active表里的条目永不删除); - 进程关闭时
Stop()(react.go:207-222)对这条交互执行activeWG.Wait()→ Stop 也跟着挂起,直到外层 20s 超时兜底,关闭质量劣化。
一句话:handler 侧一个 panic,产生一个永久阻塞的 goroutine + 一条不完整的 trace + Stop 挂起——而这一切本来用一行 go discardAgentOutput(channels) 就能避免。
根子是 Channels.Send 的阻塞语义——discardAgentOutput 只是防呆补丁,而且只在 handler 这一侧有
There was a problem hiding this comment.
个人理解 这个和整个 agent 调用的 : 交互持久化 + 事件日志 + 整段重放 有关
可能得 #1534 完成后全面的思考一下这个地方如何实现
There was a problem hiding this comment.
这里可能对于开发者或者需要基于钩子实现私有化能力的时候,会存在 我不知道有哪些 hook、不知道接入点
type: hooks
spec:
hooks:
- name: "logging"
enabled: true
events: ["agent.start", "agent.end", "agent.error", "agent.degraded", "agent.cancel",
"stage.start", "stage.end", "stage.error", "llm.start", "llm.end", "llm.error",
"tool.start", "tool.end", "tool.error"]
config: { level: "info" }There was a problem hiding this comment.
events 字段以 enum 形式列出全部事件种类
dubbo-admin/ai/schema/json/memory.schema.json
Lines 15 to 20 in 5d6df6e
Address review feedback from ambiguous-pointer: - Document that Registration.CaptureContent uses eager snapshots for external hooks; lazyContent (deferred serialization) is internal-only. README now says tracing defers "until IsRecording()", not "lazily" as a blanket statement (component/hooks/manager.go, README.md). - Add "Available events" section to README listing the current event vocabulary (interaction/iteration/stage/model_call/tool_call × start/end) and clarifying that State fields carry error/degraded/fallback metadata. - Add inline event reference to hooks.yaml so developers configuring custom hooks know what events exist without diving into code. Refs: apache#1536 (comment) apache#1536 (comment)
Address review feedback: sonic v1.14.1 fails to compile under Go 1.26.
Upgrade to v1.15.2 which resolves the compatibility issue.
Tested: go build ./... && go test -count=1 ./component/hooks/...
./component/server/engine/ pass on Go 1.25.7
Refs: apache#1536 (comment)
…hooks
Address review feedback from ambiguous-pointer: expand event vocabulary to
support first-class error, cancellation, and degradation events, enabling
future metrics and audit hooks to subscribe by semantic event type rather
than filtering State fields.
Changes:
- Add event types: interaction.error/.cancel/.degrade, stage.error,
model_call.error, tool_call.error
- Emit *.error events before the corresponding *.end when operations fail
- Emit interaction.cancel when context cancellation aborts an interaction
- Emit interaction.degrade when tool failures or fallback responses occur
- Add state.Degraded field to track tool call failures across the interaction
- Update documentation and inline event reference in hooks.yaml
Event flow examples:
- Successful model call: model_call.start → model_call.end
- Failed model call: model_call.start → model_call.error → model_call.end
- Tool degradation: tool_call.start → tool_call.error → tool_call.end
- Cancelled interaction: interaction.start → interaction.cancel → interaction.end
This preserves the existing State field approach (Error/Degraded/FallbackUsed)
while adding dedicated event types for consumers that need per-dimension
subscriptions (e.g., "all tool errors" or "interaction cancellations").
Tested: go test -count=1 ./component/hooks/... ./component/agent/react/...
all pass; existing tests cover the extended event emission paths
Refs: apache#1536 (comment)
Add lifecycle hooks infrastructure and OpenTelemetry tracing integration for the ReAct agent, enabling observability via structured logging and distributed tracing. ## Key Features **Hooks Component**: - Event-driven lifecycle observation at interaction/iteration/stage/model_call/tool_call boundaries - Built-in logging hook (structured JSON logs via slog) - Built-in tracing hook (OpenTelemetry spans with W3C trace context propagation) - Extensible registration API for custom hooks (metrics, audit, etc.) **Event Types**: - Lifecycle events: interaction/iteration/stage/model_call/tool_call × start/end - Error events: *.error emitted before *.end when operations fail - interaction.cancel for context cancellation - interaction.degrade for tool failures or fallback responses - State metadata: Error/Degraded/FallbackUsed fields provide additional context **ReAct Agent Integration**: - Hooks fire at every major lifecycle boundary - Trace context flows through interaction → iteration → stage → model/tool calls - Panic-safe: all exit paths (including panic recovery) drain agent channels to prevent goroutine leaks and ensure trace tail spans emit - Added regression test TestStreamChatDrainsChannelsOnPanic **Configuration**: - Component-based loading via hooks.yaml - Tracing supports grpc/http protocols, configurable sampling, content capture levels - Environment variable overrides (OTEL_EXPORTER_OTLP_ENDPOINT, etc.) ## Implementation Details - Trace IDs propagate via context; agent.Channels.SetTraceID enables correlation - Tracing hook defers content serialization until span recording to avoid overhead on unsampled traces - External hooks receive eagerly-snapshotted content (documented in Registration.CaptureContent) - Tool call failures set state.Degraded and emit tool_call.error before tool_call.end - context.Canceled mapped to interaction.cancel event ## Dependencies - Upgrade sonic to v1.15.2 for Go 1.26 compatibility - Add go.opentelemetry.io/otel/* packages for tracing ## Documentation - component/hooks/README.md: architecture, usage, custom hook guide - hooks.yaml: inline event reference for developers - Available events section in README ## Testing All tests pass: - go test ./component/hooks/... - go test ./component/agent/react/... - go test ./component/server/engine/... Addresses review feedback from PR apache#1536: - Error/cancel/degrade event types for metrics/audit hooks - lazyContent semantics clarified in docs - Panic drain regression test added - Event vocabulary documented in hooks.yaml and README - sonic compatibility issue resolved
054e4c5 to
1221da6
Compare
Add lifecycle hooks infrastructure and OpenTelemetry tracing integration for the ReAct agent, enabling observability via structured logging and distributed tracing. **Hooks Component**: - Event-driven lifecycle observation at interaction/iteration/stage/model_call/tool_call boundaries - Built-in logging hook (structured JSON logs via slog) - Built-in tracing hook (OpenTelemetry spans with W3C trace context propagation) - Extensible registration API for custom hooks (metrics, audit, etc.) **Event Types**: - Lifecycle events: interaction/iteration/stage/model_call/tool_call × start/end - Error events: *.error emitted before *.end when operations fail - interaction.cancel for context cancellation - interaction.degrade for tool failures or fallback responses - State metadata: Error/Degraded/FallbackUsed fields provide additional context **ReAct Agent Integration**: - Hooks fire at every major lifecycle boundary - Trace context flows through interaction → iteration → stage → model/tool calls - Panic-safe: all exit paths (including panic recovery) drain agent channels to prevent goroutine leaks and ensure trace tail spans emit - Added regression test TestStreamChatDrainsChannelsOnPanic **Configuration**: - Component-based loading via hooks.yaml - Tracing supports grpc/http protocols, configurable sampling, content capture levels - Environment variable overrides (OTEL_EXPORTER_OTLP_ENDPOINT, etc.) - Trace IDs propagate via context; agent.Channels.SetTraceID enables correlation - Tracing hook defers content serialization until span recording to avoid overhead on unsampled traces - External hooks receive eagerly-snapshotted content (documented in Registration.CaptureContent) - Tool call failures set state.Degraded and emit tool_call.error before tool_call.end - context.Canceled mapped to interaction.cancel event - Upgrade sonic to v1.15.2 for Go 1.26 compatibility - Add go.opentelemetry.io/otel/* packages for tracing - component/hooks/README.md: architecture, usage, custom hook guide - hooks.yaml: inline event reference for developers - Available events section in README All tests pass: - go test ./component/hooks/... - go test ./component/agent/react/... - go test ./component/server/engine/... Addresses review feedback from PR apache#1536: - Error/cancel/degrade event types for metrics/audit hooks - lazyContent semantics clarified in docs - Panic drain regression test added - Event vocabulary documented in hooks.yaml and README - sonic compatibility issue resolved
1221da6 to
0114c79
Compare
感谢详细的 review! 已修复:
说明:
|
|
@chaojixinren please merge the develop branch and resolve the conflicts. |
Merge apache/develop into the PR source feat/hook-system, retaining AI/MCP integration while incorporating event streams and traffic-rule version history. Keep the result local for author review. Constraint: PR target remains apache/ai; no remote push is authorized Confidence: high Scope-risk: moderate Tested: Backend and AI short suites and go vet; 55 frontend tests; Vite build Not-tested: External-service end-to-end tests; frontend typecheck and lint have existing failures
Merge apache/ai into feat/hook-system after synchronizing develop. Move hook boundaries onto the bounded reason-act loop and forced answer while preserving page-context validation, trace propagation, cancellation, and detached stream draining. Retire the removed observe/orchestrator code. Register the already documented error, cancel, and degrade events, and record them without ending spans before the matching end event. Constraint: All changes remain local for author review; do not push Rejected: Restore the old multi-stage loop | would undo the target branch architecture Confidence: high Scope-risk: moderate Directive: Preserve paired lifecycle events and page-context trust checks when changing the loop Tested: Full AI short suite, go vet, go build, and race tests for react/hooks/server engine Tested: Backend short suite and go vet; frontend 55 tests and production build before AI-only changes Not-tested: External-service integration tests; frontend typecheck and lint retain baseline failures
|
@robocanic Merged the latest |
@chaojixinren 我觉得配置化hook注册长期来看是需要的,并且不管配置化还是非配置化,events字段都需要枚举列出来,你可以评估一下支持配置化改动大不大,如果不大的话,就在同一个PR上追加commit。如果改动大,就新开一个PR |
Register built-in logging and tracing hooks from YAML, enumerate all 16 supported events, and preserve legacy configuration compatibility. Constraint: Tracing requires all lifecycle events and tools Scope-risk: moderate Tested: AI short tests, targeted race tests, go vet, and build Tested: Real Jaeger export over gRPC and HTTP with configured hooks Tested: Real HTTP interaction and local model tool call Not-tested: Successful final answer; local model stopped at user request
|
|
@robocanic 已评估并在这个 PR 中补充了配置化 Hook 注册:
改动集中在 hooks 组件及其配置 Schema,没有引入动态插件机制。单元测试、竞态检测和编译检查已通过,真实 Jaeger 的 gRPC/HTTP 导出也已验证。实际 HTTP 对话已验证到本地模型完成工具调用。 麻烦再帮忙看一下,谢谢! |
|
最初的 Hook 实现(0114c79):40-50 个文件
|



Summary
Introduces a config-driven, telemetry-agnostic agent hooks system in
ai/, withlogging 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
ai/component/hooks/): immutable lifecycle events(
interaction / iteration / stage / model_call / tool_call×start / end), read-onlyStatesnapshots, per-event registration, and panic isolation per hook.context.Contextfor nested work; exactly oneDerivesContextregistration is accepted (a Go context carries one span lineage — fan outvia a Collector instead). Contexts returned by plain observational hooks are ignored.
(
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 isopt-in (
capture_content: nonedefault;truncated≤ 4096 bytes;full).traceparent/tracestate/baggageare honored inbound,propagated to MCP HTTP calls, and the active trace ID is returned on SSE responses via
X-Trace-ID(CORS-exposed).FallbackReason), writtento both the model-call span and the stage span, with correct
Evidencetext; tool failuresare recorded as
error.type+agent.degradedwithout faking agen_ai.tool.call.result.context.Canceledpropagates cleanly (onlyDeadlineExceededis a timeout); SSE disconnect cancellation stays detached from the running interaction.
type: hookscomponent withlogging/tracingblocks, JSON schemavalidation, and standard OTel env vars for endpoint and credentials.
Design constraints
Agent execution data.
nonefor credential/PII safety; payloads are not serializedon the hot path unless a matching hook opts in.
"*"for all).Agent Hooks + OTel Tracing — Completed Test Checklist
1. Unit Tests
go test -count=1 ./...— all passed (hooks, Agent, server engine, MCP tools, runtime, etc.)2. Integration Tests
go test -tags=integration -count=1 ./...— all passed3. Race / Static Analysis
go test -race ./component/hooks/... ./component/agent/...— passedgo vet ./...— passed4. E2E: Jaeger (OTLP)
f6477cd5b8d5a5cce9ae07a0ad1d84705. E2E: Langfuse (Docker 4.11.0)
AGENT invoke_agent→GENERATION chat qwen-max→TOOL lookup_serviceevents_full: model input/output, 7/5/12 tokens, session ID, tool call IDfdc809bacdcdbf5b7cd7798ba8f7c1cb6. Performance Benchmarks (0 allocs)
BenchmarkDisabledHookFastPathBenchmarkEmptyManagerFastPathBenchmarkHookContentDisabledBenchmarkHookContentLoggingOnly7. Cleanup
7bbcab1TestMultiTurnConversationtherefore shows 0/14