From f19ddc54007cf2c996ab6bf663367f306662e7c5 Mon Sep 17 00:00:00 2001 From: furiosa Date: Fri, 9 Jan 2026 00:35:15 -0800 Subject: [PATCH] feat(costs): add verbose logging for silent failures Add --verbose/-v flag to gt costs command that outputs debug information when silent failures occur during cost tracking operations: - wisp list failures in querySessionCostWisps and deleteSessionCostWisps - bd show failures when querying wisp details - JSON unmarshal failures when parsing wisp/event data - payload unmarshal failures when parsing session payloads This makes debugging cost tracking issues much easier as these error paths previously continued silently without any indication of failure. Closes: bd-qv8f9 Co-Authored-By: Claude Opus 4.5 --- internal/cmd/costs.go | 30 +++++++++++++++++++++++++----- 1 file changed, 25 insertions(+), 5 deletions(-) diff --git a/internal/cmd/costs.go b/internal/cmd/costs.go index 59eb2a71..886a5192 100644 --- a/internal/cmd/costs.go +++ b/internal/cmd/costs.go @@ -18,11 +18,12 @@ import ( ) var ( - costsJSON bool - costsToday bool - costsWeek bool - costsByRole bool - costsByRig bool + costsJSON bool + costsToday bool + costsWeek bool + costsByRole bool + costsByRig bool + costsVerbose bool // Record subcommand flags recordSession string @@ -127,6 +128,7 @@ func init() { costsCmd.Flags().BoolVar(&costsWeek, "week", false, "Show this week's total from session events") costsCmd.Flags().BoolVar(&costsByRole, "by-role", false, "Show breakdown by role") costsCmd.Flags().BoolVar(&costsByRig, "by-rig", false, "Show breakdown by rig") + costsCmd.Flags().BoolVarP(&costsVerbose, "verbose", "v", false, "Show debug output for failures") // Add record subcommand costsCmd.AddCommand(costsRecordCmd) @@ -991,6 +993,9 @@ func querySessionCostWisps(targetDate time.Time) ([]CostEntry, error) { listOutput, err := listCmd.Output() if err != nil { // No wisps database or command failed + if costsVerbose { + fmt.Fprintf(os.Stderr, "[costs] wisp list failed: %v\n", err) + } return nil, nil } @@ -1033,6 +1038,9 @@ func querySessionCostWisps(targetDate time.Time) ([]CostEntry, error) { var payload SessionPayload if event.Payload != "" { if err := json.Unmarshal([]byte(event.Payload), &payload); err != nil { + if costsVerbose { + fmt.Fprintf(os.Stderr, "[costs] payload unmarshal failed for event %s: %v\n", event.ID, err) + } continue } } @@ -1137,6 +1145,9 @@ func deleteSessionCostWisps(targetDate time.Time) (int, error) { listCmd := exec.Command("bd", "mol", "wisp", "list", "--all", "--json") listOutput, err := listCmd.Output() if err != nil { + if costsVerbose { + fmt.Fprintf(os.Stderr, "[costs] wisp list failed in deletion: %v\n", err) + } return 0, nil } @@ -1155,11 +1166,17 @@ func deleteSessionCostWisps(targetDate time.Time) (int, error) { showCmd := exec.Command("bd", "show", wisp.ID, "--json") showOutput, err := showCmd.Output() if err != nil { + if costsVerbose { + fmt.Fprintf(os.Stderr, "[costs] bd show failed for wisp %s: %v\n", wisp.ID, err) + } continue } var events []SessionEvent if err := json.Unmarshal(showOutput, &events); err != nil { + if costsVerbose { + fmt.Fprintf(os.Stderr, "[costs] JSON unmarshal failed for wisp %s: %v\n", wisp.ID, err) + } continue } @@ -1178,6 +1195,9 @@ func deleteSessionCostWisps(targetDate time.Time) (int, error) { var payload SessionPayload if event.Payload != "" { if err := json.Unmarshal([]byte(event.Payload), &payload); err != nil { + if costsVerbose { + fmt.Fprintf(os.Stderr, "[costs] payload unmarshal failed for wisp %s: %v\n", wisp.ID, err) + } continue } }