Skip to content

Commit b5e1f57

Browse files
author
SqlRush
committed
Show telemetry status summaries
1 parent 104cf2d commit b5e1f57

4 files changed

Lines changed: 90 additions & 5 deletions

File tree

docs/cc-100-roadmap.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1456,7 +1456,7 @@ M7 补充:terminal input parser 和 configurable keybinding name parser 现在
14561456
- Chrome/computer-use/voice/native integrations。
14571457
- enterprise/gated/platform-specific behavior。
14581458

1459-
当前状态:已新增 `advanced` settings gate 地基,覆盖 bridge/LSP/telemetry/Chrome/voice/computer-use/native integrations 的独立 bool 开关解析、settings merge、headless `/config show advanced` 和 `/config search` 审计;`advanced.telemetry=true` 时会在 session 目录写入安全摘要 JSONL 诊断事件,记录事件类型、session/model、tool/progress keys、token/compact/error 摘要,不写入用户/助手正文或工具结果内容,并已有安全 JSONL 读取、类型/模型过滤和汇总统计地基;`advanced.lsp=true` 时才向模型暴露只读 `LSPDiagnostics` 工具,用于读取 session-scoped diagnostics snapshot,并支持 file/severity/limit 过滤,底层已能解析 LSP `textDocument/publishDiagnostics` params/notification payload、按文件替换 snapshot,并按 LSP 空 diagnostics 语义清空旧文件诊断;`advanced.bridge=true` 时会写出 session-scoped bridge manifest,列出 bridge-safe slash/local command 元数据,并提供 command/display/alias 安全解析;未启用时仍不注册或泄露 gated 工具 schema。实际 repl bridge server、session websocket/direct connect、LSP server manager、diagnostic producer、telemetry exporter/tracing、Chrome/voice/computer-use/native runtime 仍未完成。
1459+
当前状态:已新增 `advanced` settings gate 地基,覆盖 bridge/LSP/telemetry/Chrome/voice/computer-use/native integrations 的独立 bool 开关解析、settings merge、headless `/config show advanced` 和 `/config search` 审计;`advanced.telemetry=true` 时会在 session 目录写入安全摘要 JSONL 诊断事件,记录事件类型、session/model、tool/progress keys、token/compact/error 摘要,不写入用户/助手正文或工具结果内容,并已有安全 JSONL 读取、类型/模型过滤、汇总统计和 headless `/status show telemetry` 地基;`advanced.lsp=true` 时才向模型暴露只读 `LSPDiagnostics` 工具,用于读取 session-scoped diagnostics snapshot,并支持 file/severity/limit 过滤,底层已能解析 LSP `textDocument/publishDiagnostics` params/notification payload、按文件替换 snapshot,并按 LSP 空 diagnostics 语义清空旧文件诊断;`advanced.bridge=true` 时会写出 session-scoped bridge manifest,列出 bridge-safe slash/local command 元数据,并提供 command/display/alias 安全解析;未启用时仍不注册或泄露 gated 工具 schema。实际 repl bridge server、session websocket/direct connect、LSP server manager、diagnostic producer、telemetry exporter/tracing、Chrome/voice/computer-use/native runtime 仍未完成。
14601460

14611461
## Recommended Next Steps
14621462

docs/claude-code-go-rewrite-plan.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -745,7 +745,7 @@ test/parity/ # golden tests against TS/official behavior
745745
- 每个 gated feature 独立开关测试。
746746
- 不启用 feature 时二进制行为和可见 schema 不泄露 gated 工具/命令。
747747

748-
- 本轮补充:新增 `advanced` settings gate 地基,覆盖 bridge/LSP/telemetry/Chrome/voice/computer-use/native integrations 的独立 bool 开关解析、settings merge、headless `/config show advanced` 和 `/config search` 审计;`advanced.telemetry=true` 时会在 session 目录写入安全摘要 JSONL 诊断事件,记录事件类型、session/model、tool/progress keys、token/compact/error 摘要,不写入用户/助手正文或工具结果内容,并已有安全 JSONL 读取、类型/模型过滤和汇总统计地基;`advanced.lsp=true` 时才向模型暴露只读 `LSPDiagnostics` 工具,用于读取 session-scoped diagnostics snapshot,并支持 file/severity/limit 过滤,底层已能解析 LSP `textDocument/publishDiagnostics` params/notification payload、按文件替换 snapshot,并按 LSP 空 diagnostics 语义清空旧文件诊断;`advanced.bridge=true` 时会写出 session-scoped bridge manifest,列出 bridge-safe slash/local command 元数据,并提供 command/display/alias 安全解析;未启用时仍不注册或泄露 gated 工具 schema。实际 repl bridge server、session websocket/direct connect、LSP server manager、diagnostic producer、telemetry exporter/tracing、Chrome/voice/computer-use/native runtime 仍未完成。
748+
- 本轮补充:新增 `advanced` settings gate 地基,覆盖 bridge/LSP/telemetry/Chrome/voice/computer-use/native integrations 的独立 bool 开关解析、settings merge、headless `/config show advanced` 和 `/config search` 审计;`advanced.telemetry=true` 时会在 session 目录写入安全摘要 JSONL 诊断事件,记录事件类型、session/model、tool/progress keys、token/compact/error 摘要,不写入用户/助手正文或工具结果内容,并已有安全 JSONL 读取、类型/模型过滤、汇总统计和 headless `/status show telemetry` 地基;`advanced.lsp=true` 时才向模型暴露只读 `LSPDiagnostics` 工具,用于读取 session-scoped diagnostics snapshot,并支持 file/severity/limit 过滤,底层已能解析 LSP `textDocument/publishDiagnostics` params/notification payload、按文件替换 snapshot,并按 LSP 空 diagnostics 语义清空旧文件诊断;`advanced.bridge=true` 时会写出 session-scoped bridge manifest,列出 bridge-safe slash/local command 元数据,并提供 command/display/alias 安全解析;未启用时仍不注册或泄露 gated 工具 schema。实际 repl bridge server、session websocket/direct connect、LSP server manager、diagnostic producer、telemetry exporter/tracing、Chrome/voice/computer-use/native runtime 仍未完成。
749749

750750
### M12: Parity hardening
751751

internal/conversation/run.go

Lines changed: 58 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ import (
2525
pluginpkg "ccgo/internal/plugins"
2626
"ccgo/internal/session"
2727
"ccgo/internal/skills"
28+
telemetrypkg "ccgo/internal/telemetry"
2829
"ccgo/internal/tool"
2930
)
3031

@@ -578,10 +579,10 @@ func (r Runner) formatStatusSummary(raw string) string {
578579
switch args[0] {
579580
case "show", "info":
580581
if len(args) < 2 || strings.TrimSpace(args[1]) == "" {
581-
return "Usage: /status " + args[0] + " <session|model|auth|tools|mcp|plugins>"
582+
return "Usage: /status " + args[0] + " <session|model|auth|tools|mcp|plugins|telemetry>"
582583
}
583584
return r.formatStatusShow(args[1])
584-
case "session", "model", "auth", "tools", "mcp", "plugins":
585+
case "session", "model", "auth", "tools", "mcp", "plugins", "telemetry":
585586
return r.formatStatusShow(args[0])
586587
default:
587588
return "Status section is not implemented in the Go runtime yet: " + strings.Join(args, " ")
@@ -720,8 +721,10 @@ func (r Runner) formatStatusShow(raw string) string {
720721
}
721722
}
722723
return strings.Join(lines, "\n")
724+
case "telemetry":
725+
return r.formatStatusTelemetry()
723726
default:
724-
return "Unknown status section " + strings.TrimSpace(raw) + ". Available sections: session, model, auth, tools, mcp, plugins"
727+
return "Unknown status section " + strings.TrimSpace(raw) + ". Available sections: session, model, auth, tools, mcp, plugins, telemetry"
725728
}
726729
}
727730

@@ -742,11 +745,51 @@ func normalizeStatusSection(raw string) string {
742745
return "mcp"
743746
case "plugin", "plugins":
744747
return "plugins"
748+
case "telemetry", "telemetry-events", "diagnostics", "trace", "tracing":
749+
return "telemetry"
745750
default:
746751
return compact
747752
}
748753
}
749754

755+
func (r Runner) formatStatusTelemetry() string {
756+
path := telemetrypkg.SessionPath(r.SessionPath, r.SessionID)
757+
lines := []string{
758+
"Status telemetry",
759+
"Enabled: " + boolEnabledText(r.telemetryEnabled()),
760+
}
761+
if path == "" {
762+
return strings.Join(append(lines, "Telemetry path: (not configured)", "Events: 0"), "\n")
763+
}
764+
events, err := telemetrypkg.Load(path)
765+
if err != nil {
766+
return strings.Join(append(lines, "Telemetry path: "+path, "Telemetry error: "+err.Error()), "\n")
767+
}
768+
summary := telemetrypkg.Summarize(events)
769+
lines = append(lines,
770+
"Telemetry path: "+path,
771+
fmt.Sprintf("Events: %d", summary.Total),
772+
fmt.Sprintf("Tool events: %d", summary.ToolEvents),
773+
fmt.Sprintf("Tool errors: %d", summary.ToolErrors),
774+
fmt.Sprintf("Error events: %d", summary.ErrorEvents),
775+
fmt.Sprintf("Compactions: %d", summary.Compactions),
776+
fmt.Sprintf("Token warnings: %d", summary.TokenWarnings),
777+
)
778+
if len(summary.ByType) > 0 {
779+
lines = append(lines, "Event types:")
780+
for _, key := range sortedIntMapKeys(summary.ByType) {
781+
lines = append(lines, fmt.Sprintf("- %s: %d", key, summary.ByType[key]))
782+
}
783+
}
784+
if len(summary.ByModel) > 0 {
785+
lines = append(lines, "Models:")
786+
for _, key := range sortedIntMapKeys(summary.ByModel) {
787+
lines = append(lines, fmt.Sprintf("- %s: %d", key, summary.ByModel[key]))
788+
}
789+
}
790+
return strings.Join(lines, "\n")
791+
}
792+
750793
func (r *Runner) formatConfigSummary(raw string) string {
751794
args := strings.Fields(strings.TrimSpace(raw))
752795
if len(args) > 0 {
@@ -2536,6 +2579,18 @@ func sortedAnyMapKeys(values map[string]any) []string {
25362579
return keys
25372580
}
25382581

2582+
func sortedIntMapKeys(values map[string]int) []string {
2583+
keys := make([]string, 0, len(values))
2584+
for key := range values {
2585+
key = strings.TrimSpace(key)
2586+
if key != "" {
2587+
keys = append(keys, key)
2588+
}
2589+
}
2590+
sort.Strings(keys)
2591+
return keys
2592+
}
2593+
25392594
func sortedNestedAnyMapKeys(values map[string]map[string]any) []string {
25402595
keys := make([]string, 0, len(values))
25412596
for key := range values {

internal/conversation/run_test.go

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1821,6 +1821,22 @@ func TestRunnerExecutesStatusShowSectionsWithoutQuery(t *testing.T) {
18211821
t.Fatal(err)
18221822
}
18231823
transcriptPath := filepath.Join(t.TempDir(), "session.jsonl")
1824+
if err := telemetrypkg.Append(telemetrypkg.SessionPath(transcriptPath, "sess_status_show"), telemetrypkg.Event{
1825+
SessionID: "sess_status_show",
1826+
Type: string(EventAssistantMessage),
1827+
Model: "sonnet",
1828+
}); err != nil {
1829+
t.Fatal(err)
1830+
}
1831+
if err := telemetrypkg.Append(telemetrypkg.SessionPath(transcriptPath, "sess_status_show"), telemetrypkg.Event{
1832+
SessionID: "sess_status_show",
1833+
Type: string(EventToolResult),
1834+
ToolUseID: "toolu_status",
1835+
ToolResultErr: true,
1836+
Error: "tool failed",
1837+
}); err != nil {
1838+
t.Fatal(err)
1839+
}
18241840
runner := Runner{
18251841
Client: client,
18261842
Tools: tool.NewExecutor(registry),
@@ -1892,9 +1908,23 @@ func TestRunnerExecutesStatusShowSectionsWithoutQuery(t *testing.T) {
18921908
"- market/a: enabled",
18931909
"- market/b: disabled",
18941910
}, []string{"plugin-secret"})
1911+
assertStatusShow("/status show telemetry", []string{
1912+
"Status telemetry",
1913+
"Enabled: disabled",
1914+
"Events: 2",
1915+
"Tool events: 1",
1916+
"Tool errors: 1",
1917+
"Error events: 1",
1918+
"Event types:",
1919+
"- assistant_message: 1",
1920+
"- tool_result: 1",
1921+
"Models:",
1922+
"- sonnet: 1",
1923+
}, []string{"tool failed"})
18951924
assertStatusShow("/status show unknown", []string{
18961925
"Unknown status section unknown.",
18971926
"Available sections:",
1927+
"telemetry",
18981928
}, nil)
18991929
}
19001930

0 commit comments

Comments
 (0)