Skip to content

Commit 1b250f5

Browse files
committed
More usage stats scripts
1 parent 61de941 commit 1b250f5

File tree

2 files changed

+141
-4
lines changed

2 files changed

+141
-4
lines changed
Lines changed: 138 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,138 @@
1+
import { db } from '@codebuff/internal/db'
2+
import { sql } from 'drizzle-orm'
3+
4+
async function queryMinimaxCacheStats() {
5+
console.log('Querying minimax/minimax-m2.5 usage (last 19 hours)...\n')
6+
7+
// 1. Overall stats
8+
const overallResult = await db.execute(sql`
9+
SELECT
10+
COUNT(*) AS total_requests,
11+
ROUND(AVG(input_tokens)) AS avg_input_tokens,
12+
ROUND(AVG(output_tokens)) AS avg_output_tokens,
13+
ROUND(
14+
CASE
15+
WHEN SUM(input_tokens) > 0
16+
THEN SUM(cache_read_input_tokens)::numeric / SUM(input_tokens) * 100
17+
ELSE 0
18+
END, 1
19+
) AS overall_cache_rate_pct,
20+
COUNT(DISTINCT client_id) AS unique_clients
21+
FROM message
22+
WHERE finished_at >= NOW() - INTERVAL '19 hours'
23+
AND model = 'minimax/minimax-m2.5'
24+
`)
25+
26+
const overall = overallResult[0]
27+
if (!overall || Number(overall.total_requests) === 0) {
28+
console.log('No data found for minimax/minimax-m2.5 in the last 19 hours.')
29+
return
30+
}
31+
32+
console.log('Overall Stats')
33+
console.log('═══════════════════════════════════════════')
34+
console.log(`Total requests: ${overall.total_requests}`)
35+
console.log(`Unique clients: ${overall.unique_clients}`)
36+
console.log(`Avg input tokens: ${overall.avg_input_tokens}`)
37+
console.log(`Avg output tokens: ${overall.avg_output_tokens}`)
38+
console.log(`Overall cache rate: ${overall.overall_cache_rate_pct}%`)
39+
40+
// 2. Per-client stats, ordered by lowest cache rate
41+
const clientResult = await db.execute(sql`
42+
SELECT
43+
client_id,
44+
COUNT(*) AS request_count,
45+
MIN(finished_at) AS first_seen,
46+
MAX(finished_at) AS last_seen,
47+
ROUND(AVG(input_tokens)) AS avg_input,
48+
ROUND(
49+
CASE
50+
WHEN SUM(input_tokens) > 0
51+
THEN SUM(cache_read_input_tokens)::numeric / SUM(input_tokens) * 100
52+
ELSE 0
53+
END, 1
54+
) AS cache_rate_pct,
55+
SUM(cache_read_input_tokens) AS total_cache_read,
56+
SUM(input_tokens) AS total_input
57+
FROM message
58+
WHERE finished_at >= NOW() - INTERVAL '19 hours'
59+
AND model = 'minimax/minimax-m2.5'
60+
AND client_id IS NOT NULL
61+
GROUP BY client_id
62+
ORDER BY cache_rate_pct ASC, request_count DESC
63+
`)
64+
65+
console.log('\n\nPer-Client Cache Rates (lowest first)')
66+
console.log('═══════════════════════════════════════════')
67+
68+
if (clientResult.length === 0) {
69+
console.log('No client-level data found.')
70+
return
71+
}
72+
73+
for (const row of clientResult) {
74+
const clientId = String(row.client_id).slice(0, 12)
75+
const reqs = String(row.request_count).padStart(4)
76+
const cacheRate = String(row.cache_rate_pct).padStart(6)
77+
const avgInput = String(row.avg_input).padStart(8)
78+
const firstSeen = row.first_seen
79+
? new Date(String(row.first_seen)).toISOString().slice(0, 16)
80+
: 'N/A'
81+
const lastSeen = row.last_seen
82+
? new Date(String(row.last_seen)).toISOString().slice(0, 16)
83+
: 'N/A'
84+
console.log(
85+
` ${clientId}… reqs: ${reqs} cache: ${cacheRate}% avg_input: ${avgInput} range: ${firstSeen}${lastSeen}`,
86+
)
87+
}
88+
89+
// 3. Recent requests in time order
90+
const recentResult = await db.execute(sql`
91+
SELECT
92+
client_id,
93+
finished_at,
94+
input_tokens,
95+
cache_read_input_tokens,
96+
COALESCE(cache_creation_input_tokens, 0) AS cache_creation_input_tokens,
97+
output_tokens,
98+
ROUND(
99+
CASE
100+
WHEN input_tokens > 0
101+
THEN cache_read_input_tokens::numeric / input_tokens * 100
102+
ELSE 0
103+
END, 1
104+
) AS cache_rate_pct
105+
FROM message
106+
WHERE finished_at >= NOW() - INTERVAL '19 hours'
107+
AND model = 'minimax/minimax-m2.5'
108+
ORDER BY client_id, finished_at DESC
109+
LIMIT 100
110+
`)
111+
112+
console.log('\n\nRecent Requests (newest first, last 100)')
113+
console.log('═══════════════════════════════════════════')
114+
115+
for (const row of recentResult) {
116+
const clientId = row.client_id
117+
? String(row.client_id).slice(0, 12)
118+
: 'unknown '
119+
const time = row.finished_at
120+
? new Date(String(row.finished_at)).toISOString().slice(0, 19)
121+
: 'N/A'
122+
const cacheRate = String(row.cache_rate_pct).padStart(6)
123+
const input = String(row.input_tokens).padStart(7)
124+
const cached = String(row.cache_read_input_tokens).padStart(7)
125+
const creation = String(row.cache_creation_input_tokens).padStart(7)
126+
const output = String(row.output_tokens).padStart(6)
127+
console.log(
128+
` ${time} ${clientId}… cache: ${cacheRate}% input: ${input} cached: ${cached} creation: ${creation} output: ${output}`,
129+
)
130+
}
131+
}
132+
133+
queryMinimaxCacheStats()
134+
.then(() => process.exit(0))
135+
.catch((err) => {
136+
console.error(err)
137+
process.exit(1)
138+
})

scripts/query-usage-stats.ts

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -22,14 +22,13 @@ async function queryUsageStats() {
2222
2323
token_stats AS (
2424
SELECT
25-
ROUND(AVG(input_tokens + cache_read_input_tokens + cache_creation_input_tokens))
25+
ROUND(AVG(input_tokens))
2626
AS avg_total_input_tokens,
2727
ROUND(
2828
AVG(
2929
CASE
30-
WHEN (input_tokens + cache_read_input_tokens + cache_creation_input_tokens) > 0
31-
THEN cache_read_input_tokens::numeric
32-
/ (input_tokens + cache_read_input_tokens + cache_creation_input_tokens)
30+
WHEN input_tokens > 0
31+
THEN cache_read_input_tokens::numeric / input_tokens
3332
ELSE 0
3433
END
3534
) * 100, 1

0 commit comments

Comments
 (0)