Wire GenAI telemetry: settings surface, service name, and agent names (N3 WP4) #93

Merged
weichen merged 1 commits from feature/n3-otel-wp4 into main 2026-10-07 15:42:22 +00:00
8 changed files with 33 additions and 3 deletions
+4 -1
View File
@@ -84,7 +84,6 @@ func Run(opt Options) error {
if opt.InsecureListen && !config.IsLoopbackListen(opt.Addr) && !resolved.AuthEnabled() {
log.Printf("warning: listening on %s without authentication because insecureListen is set", opt.Addr)
}
traceFn := telemetry.StartFunc(logger)
var st *store.Store
var err error
if opt.StorageDSN != "" {
@@ -124,6 +123,10 @@ func Run(opt Options) error {
return fmt.Errorf("code orchestration tool: %w", err)
}
setSvc := settings.NewService(st)
effBoot := setSvc.Effective(store.OwnerDefault, "")
traceFn := telemetry.StartFunc(logger,
telemetry.WithServiceName(effBoot.GetString("telemetry.serviceName", "agent-system-backend")),
telemetry.WithEndpoint(effBoot.GetString("telemetry.otlpEndpoint", "")))
setSvc.SetSystemOverride(map[string]any{"storage": map[string]any{"dataDir": opt.DataDir}})
// 点路径键展开必须在读 tools.tavily.apiKeys 之前,否则启动仍注册旧池。
norm, err := setSvc.NormalizeStored()
+15
View File
@@ -27,3 +27,18 @@ func TestIntentSlowLaneFlagsDefaultOff(t *testing.T) {
}
}
}
// 遥测开关默认安全(N3 WP4):otlpEndpoint 默认空(不导出,保持现状),
// serviceName 有非空默认。两处都注册进 Schema。
func TestTelemetryFlagsDefaults(t *testing.T) {
seen := map[string]core.SettingDesc{}
for _, d := range settings.Schema() {
seen[d.Key] = d
}
if d, ok := seen["telemetry.otlpEndpoint"]; !ok || d.Default != "" {
t.Fatalf("otlpEndpoint 必须注册且默认空:%+v", d)
}
if d, ok := seen["telemetry.serviceName"]; !ok || d.Default != "agent-system-backend" {
t.Fatalf("serviceName 必须注册且默认 agent-system-backend:%+v", d)
}
}
+8
View File
@@ -399,6 +399,14 @@ func outputTokenCap(budget core.RunBudget, eff core.EffectiveSettings, key strin
return 0
}
// agentNameOf 是 OTel gen_ai.agent.name 的取值(画像 ID,空回退 agent-system)。
func agentNameOf(prof core.AgentProfile) string {
if strings.TrimSpace(prof.ID) != "" {
return prof.ID
}
return "agent-system"
}
// openLLMClient 不设 HTTP 客户端超时。单次生成可能很长,停止按钮通过 run 的 context 取消。
func openLLMClient(base, key string) *agentllm.Client {
return &agentllm.Client{BaseURL: base, APIKey: key, HTTPClient: &http.Client{}}
+1
View File
@@ -204,6 +204,7 @@ func (l *LLMRunner) runDirect(rc RunCtx, stream agentllm.StreamFunc, model strin
Reminders: st.reminders,
PermissionAsk: PermissionAskOf(rc),
Trace: l.Trace,
AgentName: agentNameOf(rc.Profile()),
UnknownTool: func(call agentllm.ToolCall) agenttools.Result {
return st.runTool(call.Name, call.Arguments)
},
+1
View File
@@ -110,6 +110,7 @@ func (l *SubLLMRunner) Execute(rc RunCtx) error {
OnEvent: st.onEvent,
PermissionAsk: PermissionAskOf(rc),
Trace: l.Trace,
AgentName: agentNameOf(rc.Profile()),
}, user)
if len(st.parts) == 0 {
st.parts = append(st.parts, core.Part{Type: core.PartText, Text: "(子代理未返回内容)"})
+2
View File
@@ -96,6 +96,8 @@ func Schema() []core.SettingDesc {
{Key: "runtime.composeFinal", Group: "runtime", Label: "终轮整理回复", Type: core.SettingBool, Default: true, Effect: core.EffectNewRun, Description: "用过工具的回合结束后,再用主模型写一段直接回答用户的最终回复"},
{Key: "runtime.intentSemantic", Group: "runtime", Label: "意图语义裁决(慢通道)", Type: core.SettingBool, Default: false, Effect: core.EffectRestart, Description: "规则歧义时用 embedding 语义相似度裁决。需已配置 embedding 端点。默认关闭(行为与 I1 一致)"},
{Key: "runtime.intentGenerator", Group: "runtime", Label: "意图命令生成(慢通道)", Type: core.SettingBool, Default: false, Effect: core.EffectRestart, Description: "规则与语义都未命中时用轻量模型生成意图命令(幻觉 fail-closed 回退)。默认关闭(行为与 I1 一致)"},
{Key: "telemetry.otlpEndpoint", Group: "telemetry", Label: "OTLP 端点", Type: core.SettingString, Default: "", Effect: core.EffectRestart, Description: "OTel HTTP JSON 上报端点(如 http://localhost:4318)。空 = 不导出(默认);环境变量 OTEL_EXPORTER_OTLP_ENDPOINT 作为后备"},
{Key: "telemetry.serviceName", Group: "telemetry", Label: "遥测 service.name", Type: core.SettingString, Default: "agent-system-backend", Effect: core.EffectRestart, Description: "OTLP resource 的 service.name"},
{Key: "context.maxHistoryMessages", Group: "context", Label: "历史窗口条数", Type: core.SettingNumber, Default: 40, Effect: core.EffectNewRun},
{Key: "context.maxToolResultChars", Group: "context", Label: "工具结果上限(字符)", Type: core.SettingNumber, Default: 20000, Effect: core.EffectNewRun},
{Key: "context.userInstructions", Group: "context", Label: "个人指令", Type: core.SettingString, Default: "", Effect: core.EffectNewRun, Description: "每次对话附在上下文末尾,不改系统前缀"},