mirror of
https://github.com/multica-ai/multica.git
synced 2026-07-08 06:45:55 +02:00
GetWorkspaceUsageByDay and GetWorkspaceUsageSummary had the same date attribution bug as the runtime endpoint fixed in #1167: they bucketed and filtered on agent_task_queue.created_at (enqueue time), so a task that queued at 23:58 and reported usage at 00:05 was attributed to the prior day, and ?days=N became a rolling now()-N window that clipped the morning of the earliest day returned. Switch both queries to task_usage.created_at (~= task completion time) and snap the since cutoff to start-of-day via DATE_TRUNC, mirroring ListRuntimeUsage. These endpoints have no frontend caller today, but per offline discussion they will back the upcoming workspace-level usage dashboard. Fix preemptively so the dashboard inherits correct numbers. Add a regression test covering both endpoints with the same cross-midnight + earliest-day-cutoff scenarios used for runtime usage.
65 lines
2.7 KiB
SQL
65 lines
2.7 KiB
SQL
-- name: UpsertTaskUsage :exec
|
|
INSERT INTO task_usage (task_id, provider, model, input_tokens, output_tokens, cache_read_tokens, cache_write_tokens)
|
|
VALUES ($1, $2, $3, $4, $5, $6, $7)
|
|
ON CONFLICT (task_id, provider, model)
|
|
DO UPDATE SET
|
|
input_tokens = EXCLUDED.input_tokens,
|
|
output_tokens = EXCLUDED.output_tokens,
|
|
cache_read_tokens = EXCLUDED.cache_read_tokens,
|
|
cache_write_tokens = EXCLUDED.cache_write_tokens;
|
|
|
|
-- name: GetTaskUsage :many
|
|
SELECT * FROM task_usage
|
|
WHERE task_id = $1
|
|
ORDER BY model;
|
|
|
|
-- name: GetWorkspaceUsageByDay :many
|
|
-- Bucket by tu.created_at (usage report time, ~= task completion time), not
|
|
-- atq.created_at (task enqueue time), so tasks that queue one day and execute
|
|
-- the next are attributed to the day tokens were actually produced. The since
|
|
-- cutoff is truncated to start-of-day so `days=N` yields full calendar days.
|
|
SELECT
|
|
DATE(tu.created_at) AS date,
|
|
tu.model,
|
|
SUM(tu.input_tokens)::bigint AS total_input_tokens,
|
|
SUM(tu.output_tokens)::bigint AS total_output_tokens,
|
|
SUM(tu.cache_read_tokens)::bigint AS total_cache_read_tokens,
|
|
SUM(tu.cache_write_tokens)::bigint AS total_cache_write_tokens,
|
|
COUNT(DISTINCT tu.task_id)::int AS task_count
|
|
FROM task_usage tu
|
|
JOIN agent_task_queue atq ON atq.id = tu.task_id
|
|
JOIN agent a ON a.id = atq.agent_id
|
|
WHERE a.workspace_id = $1
|
|
AND tu.created_at >= DATE_TRUNC('day', @since::timestamptz)
|
|
GROUP BY DATE(tu.created_at), tu.model
|
|
ORDER BY DATE(tu.created_at) DESC, tu.model;
|
|
|
|
-- name: GetWorkspaceUsageSummary :many
|
|
-- Filter by tu.created_at (usage report time), aligned to start-of-day, so
|
|
-- `days=N` is interpreted as N full calendar days like the other usage queries.
|
|
SELECT
|
|
tu.model,
|
|
SUM(tu.input_tokens)::bigint AS total_input_tokens,
|
|
SUM(tu.output_tokens)::bigint AS total_output_tokens,
|
|
SUM(tu.cache_read_tokens)::bigint AS total_cache_read_tokens,
|
|
SUM(tu.cache_write_tokens)::bigint AS total_cache_write_tokens,
|
|
COUNT(DISTINCT tu.task_id)::int AS task_count
|
|
FROM task_usage tu
|
|
JOIN agent_task_queue atq ON atq.id = tu.task_id
|
|
JOIN agent a ON a.id = atq.agent_id
|
|
WHERE a.workspace_id = $1
|
|
AND tu.created_at >= DATE_TRUNC('day', @since::timestamptz)
|
|
GROUP BY tu.model
|
|
ORDER BY (SUM(tu.input_tokens) + SUM(tu.output_tokens)) DESC;
|
|
|
|
-- name: GetIssueUsageSummary :one
|
|
SELECT
|
|
COALESCE(SUM(tu.input_tokens), 0)::bigint AS total_input_tokens,
|
|
COALESCE(SUM(tu.output_tokens), 0)::bigint AS total_output_tokens,
|
|
COALESCE(SUM(tu.cache_read_tokens), 0)::bigint AS total_cache_read_tokens,
|
|
COALESCE(SUM(tu.cache_write_tokens), 0)::bigint AS total_cache_write_tokens,
|
|
COUNT(DISTINCT tu.task_id)::int AS task_count
|
|
FROM task_usage tu
|
|
JOIN agent_task_queue atq ON atq.id = tu.task_id
|
|
WHERE atq.issue_id = $1;
|