feat: add issue_usage tracking and metrics for AI ticket enhancement and planning

Add `issue_usage` table with columns for user_uid, tokens, cost, and latency metrics, including a unique index on user_uid. Wire `accumulate_usage` into `enhance_ticket` and `generate_plan` to capture per-request AI usage, persist totals via `add_issue_usage` in both `IssueCreateService` and `PlanningReportService`, and expose aggregated usage as metric cards through `IssueTrackerService.collect_metrics`. Update planning API docs summary to reflect the new phased implementation document format.
This commit is contained in:
2026-06-19 11:59:40 +00:00
parent 7bbaf51450
commit ff3cbbbfe2
16 changed files with 503 additions and 122 deletions
@@ -284,6 +284,45 @@ def parse_usage_headers(headers) -> Optional[dict]:
}
USAGE_FIELDS = (
"calls",
"prompt_tokens",
"completion_tokens",
"total_tokens",
"cost_usd",
"upstream_latency_ms",
"total_latency_ms",
)
def new_usage_totals() -> dict:
return {field: 0 for field in USAGE_FIELDS}
def accumulate_usage(totals: Optional[dict], response) -> None:
if totals is None:
return
parsed = parse_usage_headers(getattr(response, "headers", None))
if not parsed:
return
for field in USAGE_FIELDS:
totals[field] += parsed[field]
def usage_metric_cards(usage: dict) -> list[dict]:
return [
{"label": "AI calls", "value": usage["calls"]},
{"label": "Total tokens", "value": usage["total_tokens"]},
{"label": "Prompt tokens", "value": usage["prompt_tokens"]},
{"label": "Completion tokens", "value": usage["completion_tokens"]},
{"label": "Total cost", "value": f"${usage['cost_usd']:.4f}"},
{"label": "Avg tokens/call", "value": usage["avg_tokens"]},
{"label": "Avg cost/call", "value": f"${usage['avg_cost_usd']:.6f}"},
{"label": "Avg latency", "value": f"{usage['avg_upstream_latency_ms']:.0f}ms"},
{"label": "Avg tokens/sec", "value": usage["avg_tokens_per_second"]},
]
class GatewayUsageLedger:
def record(self, raw: dict, pricing: Pricing, context_map: dict) -> Optional[dict]:
try: