Percentiles are read from the histograms kept with the usage sums and shown per group on the usage tab and in the people page's panels. Requests refused by a limit are recorded as 429s against their owner, free of charge, so a team hitting its limits shows as such. Usage can be grouped by model. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
209 lines
14 KiB
SQL
209 lines
14 KiB
SQL
-- Ported from the SQLite migration of the same number.
|
|
-- Usage summed as it is written, per key, person, project and model: into
|
|
-- five-minute slices (usage_5m), hours (usage_1h) and days (usage_1d).
|
|
--
|
|
-- Every chart and total read the raw table, one row per request, and summed it
|
|
-- again on every page view: fine for thousands of requests a day, and a full
|
|
-- scan of tens of millions on a cluster in real use. The sums are kept in the
|
|
-- transaction that writes the rows, so they never disagree with them; the raw
|
|
-- table stays for following one request, and can be given a retention of its
|
|
-- own (auth.usage_retention).
|
|
--
|
|
-- Three widths because how well a slice compresses depends on traffic: many
|
|
-- keys each sending a little leave a five-minute slice with nearly a row per
|
|
-- request, which an hour or a day folds much further. A chart reads the
|
|
-- coarsest width its slices are made of; a total since a moment reads the
|
|
-- rows up to the next five-minute slice, those slices up to the hour, hours
|
|
-- up to the day and days from there — exact, and a month in about thirty
|
|
-- rows per key and model.
|
|
--
|
|
-- Latency and time to first token are kept as histograms, a count per fixed
|
|
-- bucket (ms: <=100, 250, 500, 1000, 2500, 5000, 10000, 30000, 60000, 120000,
|
|
-- and above), which is what a percentile per team or model is read from after
|
|
-- the rows are gone; a mean cannot do that. ttft_* counts only requests whose
|
|
-- first token was measured. limited counts requests refused with 429 — a rate,
|
|
-- token or budget limit — which are recorded with no tokens and no cost.
|
|
|
|
CREATE TABLE usage_5m (
|
|
bucket BIGINT NOT NULL,
|
|
key_id TEXT NOT NULL,
|
|
user_id TEXT NOT NULL,
|
|
project_id TEXT NOT NULL,
|
|
model TEXT NOT NULL,
|
|
served_model TEXT NOT NULL,
|
|
requests BIGINT NOT NULL DEFAULT 0,
|
|
errors BIGINT NOT NULL DEFAULT 0,
|
|
limited BIGINT NOT NULL DEFAULT 0,
|
|
prompt_tokens BIGINT NOT NULL DEFAULT 0,
|
|
completion_tokens BIGINT NOT NULL DEFAULT 0,
|
|
cost_micros BIGINT NOT NULL DEFAULT 0,
|
|
latency_ms_sum BIGINT NOT NULL DEFAULT 0,
|
|
queue_ms_sum BIGINT NOT NULL DEFAULT 0,
|
|
ttft_ms_sum BIGINT NOT NULL DEFAULT 0,
|
|
ttft_n BIGINT NOT NULL DEFAULT 0,
|
|
last_ts BIGINT NOT NULL DEFAULT 0,
|
|
lat_0 BIGINT NOT NULL DEFAULT 0,
|
|
lat_1 BIGINT NOT NULL DEFAULT 0,
|
|
lat_2 BIGINT NOT NULL DEFAULT 0,
|
|
lat_3 BIGINT NOT NULL DEFAULT 0,
|
|
lat_4 BIGINT NOT NULL DEFAULT 0,
|
|
lat_5 BIGINT NOT NULL DEFAULT 0,
|
|
lat_6 BIGINT NOT NULL DEFAULT 0,
|
|
lat_7 BIGINT NOT NULL DEFAULT 0,
|
|
lat_8 BIGINT NOT NULL DEFAULT 0,
|
|
lat_9 BIGINT NOT NULL DEFAULT 0,
|
|
lat_10 BIGINT NOT NULL DEFAULT 0,
|
|
ttft_0 BIGINT NOT NULL DEFAULT 0,
|
|
ttft_1 BIGINT NOT NULL DEFAULT 0,
|
|
ttft_2 BIGINT NOT NULL DEFAULT 0,
|
|
ttft_3 BIGINT NOT NULL DEFAULT 0,
|
|
ttft_4 BIGINT NOT NULL DEFAULT 0,
|
|
ttft_5 BIGINT NOT NULL DEFAULT 0,
|
|
ttft_6 BIGINT NOT NULL DEFAULT 0,
|
|
ttft_7 BIGINT NOT NULL DEFAULT 0,
|
|
ttft_8 BIGINT NOT NULL DEFAULT 0,
|
|
ttft_9 BIGINT NOT NULL DEFAULT 0,
|
|
ttft_10 BIGINT NOT NULL DEFAULT 0,
|
|
PRIMARY KEY (bucket, key_id, user_id, project_id, model, served_model)
|
|
);
|
|
CREATE INDEX usage_5m_by_bucket ON usage_5m(bucket);
|
|
CREATE INDEX usage_5m_by_project ON usage_5m(project_id, bucket);
|
|
CREATE INDEX usage_5m_by_user ON usage_5m(user_id, bucket);
|
|
CREATE INDEX usage_5m_by_key ON usage_5m(key_id, bucket);
|
|
|
|
INSERT INTO usage_5m (bucket, key_id, user_id, project_id, model, served_model,
|
|
requests, errors, limited, prompt_tokens, completion_tokens, cost_micros,
|
|
latency_ms_sum, queue_ms_sum, ttft_ms_sum, ttft_n, last_ts,
|
|
lat_0, lat_1, lat_2, lat_3, lat_4, lat_5, lat_6, lat_7, lat_8, lat_9, lat_10,
|
|
ttft_0, ttft_1, ttft_2, ttft_3, ttft_4, ttft_5, ttft_6, ttft_7, ttft_8, ttft_9, ttft_10)
|
|
SELECT (ts / 300000) * 300000, key_id, COALESCE(user_id, ''), project_id, model, served_model,
|
|
COUNT(*), SUM(CASE WHEN status >= 400 THEN 1 ELSE 0 END), SUM(CASE WHEN status = 429 THEN 1 ELSE 0 END),
|
|
SUM(prompt_tokens), SUM(completion_tokens), SUM(cost_micros),
|
|
SUM(latency_ms), SUM(queue_ms), SUM(ttft_ms), SUM(CASE WHEN ttft_ms > 0 THEN 1 ELSE 0 END), MAX(ts),
|
|
SUM(CASE WHEN latency_ms <= 100 THEN 1 ELSE 0 END), SUM(CASE WHEN latency_ms > 100 AND latency_ms <= 250 THEN 1 ELSE 0 END), SUM(CASE WHEN latency_ms > 250 AND latency_ms <= 500 THEN 1 ELSE 0 END), SUM(CASE WHEN latency_ms > 500 AND latency_ms <= 1000 THEN 1 ELSE 0 END), SUM(CASE WHEN latency_ms > 1000 AND latency_ms <= 2500 THEN 1 ELSE 0 END), SUM(CASE WHEN latency_ms > 2500 AND latency_ms <= 5000 THEN 1 ELSE 0 END), SUM(CASE WHEN latency_ms > 5000 AND latency_ms <= 10000 THEN 1 ELSE 0 END), SUM(CASE WHEN latency_ms > 10000 AND latency_ms <= 30000 THEN 1 ELSE 0 END), SUM(CASE WHEN latency_ms > 30000 AND latency_ms <= 60000 THEN 1 ELSE 0 END), SUM(CASE WHEN latency_ms > 60000 AND latency_ms <= 120000 THEN 1 ELSE 0 END), SUM(CASE WHEN latency_ms > 120000 THEN 1 ELSE 0 END),
|
|
SUM(CASE WHEN ttft_ms > 0 AND ttft_ms <= 100 THEN 1 ELSE 0 END), SUM(CASE WHEN ttft_ms > 0 AND ttft_ms > 100 AND ttft_ms <= 250 THEN 1 ELSE 0 END), SUM(CASE WHEN ttft_ms > 0 AND ttft_ms > 250 AND ttft_ms <= 500 THEN 1 ELSE 0 END), SUM(CASE WHEN ttft_ms > 0 AND ttft_ms > 500 AND ttft_ms <= 1000 THEN 1 ELSE 0 END), SUM(CASE WHEN ttft_ms > 0 AND ttft_ms > 1000 AND ttft_ms <= 2500 THEN 1 ELSE 0 END), SUM(CASE WHEN ttft_ms > 0 AND ttft_ms > 2500 AND ttft_ms <= 5000 THEN 1 ELSE 0 END), SUM(CASE WHEN ttft_ms > 0 AND ttft_ms > 5000 AND ttft_ms <= 10000 THEN 1 ELSE 0 END), SUM(CASE WHEN ttft_ms > 0 AND ttft_ms > 10000 AND ttft_ms <= 30000 THEN 1 ELSE 0 END), SUM(CASE WHEN ttft_ms > 0 AND ttft_ms > 30000 AND ttft_ms <= 60000 THEN 1 ELSE 0 END), SUM(CASE WHEN ttft_ms > 0 AND ttft_ms > 60000 AND ttft_ms <= 120000 THEN 1 ELSE 0 END), SUM(CASE WHEN ttft_ms > 0 AND ttft_ms > 120000 THEN 1 ELSE 0 END)
|
|
FROM usage
|
|
GROUP BY 1, 2, 3, 4, 5, 6;
|
|
|
|
CREATE TABLE usage_1h (
|
|
bucket BIGINT NOT NULL,
|
|
key_id TEXT NOT NULL,
|
|
user_id TEXT NOT NULL,
|
|
project_id TEXT NOT NULL,
|
|
model TEXT NOT NULL,
|
|
served_model TEXT NOT NULL,
|
|
requests BIGINT NOT NULL DEFAULT 0,
|
|
errors BIGINT NOT NULL DEFAULT 0,
|
|
limited BIGINT NOT NULL DEFAULT 0,
|
|
prompt_tokens BIGINT NOT NULL DEFAULT 0,
|
|
completion_tokens BIGINT NOT NULL DEFAULT 0,
|
|
cost_micros BIGINT NOT NULL DEFAULT 0,
|
|
latency_ms_sum BIGINT NOT NULL DEFAULT 0,
|
|
queue_ms_sum BIGINT NOT NULL DEFAULT 0,
|
|
ttft_ms_sum BIGINT NOT NULL DEFAULT 0,
|
|
ttft_n BIGINT NOT NULL DEFAULT 0,
|
|
last_ts BIGINT NOT NULL DEFAULT 0,
|
|
lat_0 BIGINT NOT NULL DEFAULT 0,
|
|
lat_1 BIGINT NOT NULL DEFAULT 0,
|
|
lat_2 BIGINT NOT NULL DEFAULT 0,
|
|
lat_3 BIGINT NOT NULL DEFAULT 0,
|
|
lat_4 BIGINT NOT NULL DEFAULT 0,
|
|
lat_5 BIGINT NOT NULL DEFAULT 0,
|
|
lat_6 BIGINT NOT NULL DEFAULT 0,
|
|
lat_7 BIGINT NOT NULL DEFAULT 0,
|
|
lat_8 BIGINT NOT NULL DEFAULT 0,
|
|
lat_9 BIGINT NOT NULL DEFAULT 0,
|
|
lat_10 BIGINT NOT NULL DEFAULT 0,
|
|
ttft_0 BIGINT NOT NULL DEFAULT 0,
|
|
ttft_1 BIGINT NOT NULL DEFAULT 0,
|
|
ttft_2 BIGINT NOT NULL DEFAULT 0,
|
|
ttft_3 BIGINT NOT NULL DEFAULT 0,
|
|
ttft_4 BIGINT NOT NULL DEFAULT 0,
|
|
ttft_5 BIGINT NOT NULL DEFAULT 0,
|
|
ttft_6 BIGINT NOT NULL DEFAULT 0,
|
|
ttft_7 BIGINT NOT NULL DEFAULT 0,
|
|
ttft_8 BIGINT NOT NULL DEFAULT 0,
|
|
ttft_9 BIGINT NOT NULL DEFAULT 0,
|
|
ttft_10 BIGINT NOT NULL DEFAULT 0,
|
|
PRIMARY KEY (bucket, key_id, user_id, project_id, model, served_model)
|
|
);
|
|
CREATE INDEX usage_1h_by_bucket ON usage_1h(bucket);
|
|
CREATE INDEX usage_1h_by_project ON usage_1h(project_id, bucket);
|
|
CREATE INDEX usage_1h_by_user ON usage_1h(user_id, bucket);
|
|
CREATE INDEX usage_1h_by_key ON usage_1h(key_id, bucket);
|
|
|
|
INSERT INTO usage_1h (bucket, key_id, user_id, project_id, model, served_model,
|
|
requests, errors, limited, prompt_tokens, completion_tokens, cost_micros,
|
|
latency_ms_sum, queue_ms_sum, ttft_ms_sum, ttft_n, last_ts,
|
|
lat_0, lat_1, lat_2, lat_3, lat_4, lat_5, lat_6, lat_7, lat_8, lat_9, lat_10,
|
|
ttft_0, ttft_1, ttft_2, ttft_3, ttft_4, ttft_5, ttft_6, ttft_7, ttft_8, ttft_9, ttft_10)
|
|
SELECT (ts / 3600000) * 3600000, key_id, COALESCE(user_id, ''), project_id, model, served_model,
|
|
COUNT(*), SUM(CASE WHEN status >= 400 THEN 1 ELSE 0 END), SUM(CASE WHEN status = 429 THEN 1 ELSE 0 END),
|
|
SUM(prompt_tokens), SUM(completion_tokens), SUM(cost_micros),
|
|
SUM(latency_ms), SUM(queue_ms), SUM(ttft_ms), SUM(CASE WHEN ttft_ms > 0 THEN 1 ELSE 0 END), MAX(ts),
|
|
SUM(CASE WHEN latency_ms <= 100 THEN 1 ELSE 0 END), SUM(CASE WHEN latency_ms > 100 AND latency_ms <= 250 THEN 1 ELSE 0 END), SUM(CASE WHEN latency_ms > 250 AND latency_ms <= 500 THEN 1 ELSE 0 END), SUM(CASE WHEN latency_ms > 500 AND latency_ms <= 1000 THEN 1 ELSE 0 END), SUM(CASE WHEN latency_ms > 1000 AND latency_ms <= 2500 THEN 1 ELSE 0 END), SUM(CASE WHEN latency_ms > 2500 AND latency_ms <= 5000 THEN 1 ELSE 0 END), SUM(CASE WHEN latency_ms > 5000 AND latency_ms <= 10000 THEN 1 ELSE 0 END), SUM(CASE WHEN latency_ms > 10000 AND latency_ms <= 30000 THEN 1 ELSE 0 END), SUM(CASE WHEN latency_ms > 30000 AND latency_ms <= 60000 THEN 1 ELSE 0 END), SUM(CASE WHEN latency_ms > 60000 AND latency_ms <= 120000 THEN 1 ELSE 0 END), SUM(CASE WHEN latency_ms > 120000 THEN 1 ELSE 0 END),
|
|
SUM(CASE WHEN ttft_ms > 0 AND ttft_ms <= 100 THEN 1 ELSE 0 END), SUM(CASE WHEN ttft_ms > 0 AND ttft_ms > 100 AND ttft_ms <= 250 THEN 1 ELSE 0 END), SUM(CASE WHEN ttft_ms > 0 AND ttft_ms > 250 AND ttft_ms <= 500 THEN 1 ELSE 0 END), SUM(CASE WHEN ttft_ms > 0 AND ttft_ms > 500 AND ttft_ms <= 1000 THEN 1 ELSE 0 END), SUM(CASE WHEN ttft_ms > 0 AND ttft_ms > 1000 AND ttft_ms <= 2500 THEN 1 ELSE 0 END), SUM(CASE WHEN ttft_ms > 0 AND ttft_ms > 2500 AND ttft_ms <= 5000 THEN 1 ELSE 0 END), SUM(CASE WHEN ttft_ms > 0 AND ttft_ms > 5000 AND ttft_ms <= 10000 THEN 1 ELSE 0 END), SUM(CASE WHEN ttft_ms > 0 AND ttft_ms > 10000 AND ttft_ms <= 30000 THEN 1 ELSE 0 END), SUM(CASE WHEN ttft_ms > 0 AND ttft_ms > 30000 AND ttft_ms <= 60000 THEN 1 ELSE 0 END), SUM(CASE WHEN ttft_ms > 0 AND ttft_ms > 60000 AND ttft_ms <= 120000 THEN 1 ELSE 0 END), SUM(CASE WHEN ttft_ms > 0 AND ttft_ms > 120000 THEN 1 ELSE 0 END)
|
|
FROM usage
|
|
GROUP BY 1, 2, 3, 4, 5, 6;
|
|
|
|
CREATE TABLE usage_1d (
|
|
bucket BIGINT NOT NULL,
|
|
key_id TEXT NOT NULL,
|
|
user_id TEXT NOT NULL,
|
|
project_id TEXT NOT NULL,
|
|
model TEXT NOT NULL,
|
|
served_model TEXT NOT NULL,
|
|
requests BIGINT NOT NULL DEFAULT 0,
|
|
errors BIGINT NOT NULL DEFAULT 0,
|
|
limited BIGINT NOT NULL DEFAULT 0,
|
|
prompt_tokens BIGINT NOT NULL DEFAULT 0,
|
|
completion_tokens BIGINT NOT NULL DEFAULT 0,
|
|
cost_micros BIGINT NOT NULL DEFAULT 0,
|
|
latency_ms_sum BIGINT NOT NULL DEFAULT 0,
|
|
queue_ms_sum BIGINT NOT NULL DEFAULT 0,
|
|
ttft_ms_sum BIGINT NOT NULL DEFAULT 0,
|
|
ttft_n BIGINT NOT NULL DEFAULT 0,
|
|
last_ts BIGINT NOT NULL DEFAULT 0,
|
|
lat_0 BIGINT NOT NULL DEFAULT 0,
|
|
lat_1 BIGINT NOT NULL DEFAULT 0,
|
|
lat_2 BIGINT NOT NULL DEFAULT 0,
|
|
lat_3 BIGINT NOT NULL DEFAULT 0,
|
|
lat_4 BIGINT NOT NULL DEFAULT 0,
|
|
lat_5 BIGINT NOT NULL DEFAULT 0,
|
|
lat_6 BIGINT NOT NULL DEFAULT 0,
|
|
lat_7 BIGINT NOT NULL DEFAULT 0,
|
|
lat_8 BIGINT NOT NULL DEFAULT 0,
|
|
lat_9 BIGINT NOT NULL DEFAULT 0,
|
|
lat_10 BIGINT NOT NULL DEFAULT 0,
|
|
ttft_0 BIGINT NOT NULL DEFAULT 0,
|
|
ttft_1 BIGINT NOT NULL DEFAULT 0,
|
|
ttft_2 BIGINT NOT NULL DEFAULT 0,
|
|
ttft_3 BIGINT NOT NULL DEFAULT 0,
|
|
ttft_4 BIGINT NOT NULL DEFAULT 0,
|
|
ttft_5 BIGINT NOT NULL DEFAULT 0,
|
|
ttft_6 BIGINT NOT NULL DEFAULT 0,
|
|
ttft_7 BIGINT NOT NULL DEFAULT 0,
|
|
ttft_8 BIGINT NOT NULL DEFAULT 0,
|
|
ttft_9 BIGINT NOT NULL DEFAULT 0,
|
|
ttft_10 BIGINT NOT NULL DEFAULT 0,
|
|
PRIMARY KEY (bucket, key_id, user_id, project_id, model, served_model)
|
|
);
|
|
CREATE INDEX usage_1d_by_bucket ON usage_1d(bucket);
|
|
CREATE INDEX usage_1d_by_project ON usage_1d(project_id, bucket);
|
|
CREATE INDEX usage_1d_by_user ON usage_1d(user_id, bucket);
|
|
CREATE INDEX usage_1d_by_key ON usage_1d(key_id, bucket);
|
|
|
|
INSERT INTO usage_1d (bucket, key_id, user_id, project_id, model, served_model,
|
|
requests, errors, limited, prompt_tokens, completion_tokens, cost_micros,
|
|
latency_ms_sum, queue_ms_sum, ttft_ms_sum, ttft_n, last_ts,
|
|
lat_0, lat_1, lat_2, lat_3, lat_4, lat_5, lat_6, lat_7, lat_8, lat_9, lat_10,
|
|
ttft_0, ttft_1, ttft_2, ttft_3, ttft_4, ttft_5, ttft_6, ttft_7, ttft_8, ttft_9, ttft_10)
|
|
SELECT (ts / 86400000) * 86400000, key_id, COALESCE(user_id, ''), project_id, model, served_model,
|
|
COUNT(*), SUM(CASE WHEN status >= 400 THEN 1 ELSE 0 END), SUM(CASE WHEN status = 429 THEN 1 ELSE 0 END),
|
|
SUM(prompt_tokens), SUM(completion_tokens), SUM(cost_micros),
|
|
SUM(latency_ms), SUM(queue_ms), SUM(ttft_ms), SUM(CASE WHEN ttft_ms > 0 THEN 1 ELSE 0 END), MAX(ts),
|
|
SUM(CASE WHEN latency_ms <= 100 THEN 1 ELSE 0 END), SUM(CASE WHEN latency_ms > 100 AND latency_ms <= 250 THEN 1 ELSE 0 END), SUM(CASE WHEN latency_ms > 250 AND latency_ms <= 500 THEN 1 ELSE 0 END), SUM(CASE WHEN latency_ms > 500 AND latency_ms <= 1000 THEN 1 ELSE 0 END), SUM(CASE WHEN latency_ms > 1000 AND latency_ms <= 2500 THEN 1 ELSE 0 END), SUM(CASE WHEN latency_ms > 2500 AND latency_ms <= 5000 THEN 1 ELSE 0 END), SUM(CASE WHEN latency_ms > 5000 AND latency_ms <= 10000 THEN 1 ELSE 0 END), SUM(CASE WHEN latency_ms > 10000 AND latency_ms <= 30000 THEN 1 ELSE 0 END), SUM(CASE WHEN latency_ms > 30000 AND latency_ms <= 60000 THEN 1 ELSE 0 END), SUM(CASE WHEN latency_ms > 60000 AND latency_ms <= 120000 THEN 1 ELSE 0 END), SUM(CASE WHEN latency_ms > 120000 THEN 1 ELSE 0 END),
|
|
SUM(CASE WHEN ttft_ms > 0 AND ttft_ms <= 100 THEN 1 ELSE 0 END), SUM(CASE WHEN ttft_ms > 0 AND ttft_ms > 100 AND ttft_ms <= 250 THEN 1 ELSE 0 END), SUM(CASE WHEN ttft_ms > 0 AND ttft_ms > 250 AND ttft_ms <= 500 THEN 1 ELSE 0 END), SUM(CASE WHEN ttft_ms > 0 AND ttft_ms > 500 AND ttft_ms <= 1000 THEN 1 ELSE 0 END), SUM(CASE WHEN ttft_ms > 0 AND ttft_ms > 1000 AND ttft_ms <= 2500 THEN 1 ELSE 0 END), SUM(CASE WHEN ttft_ms > 0 AND ttft_ms > 2500 AND ttft_ms <= 5000 THEN 1 ELSE 0 END), SUM(CASE WHEN ttft_ms > 0 AND ttft_ms > 5000 AND ttft_ms <= 10000 THEN 1 ELSE 0 END), SUM(CASE WHEN ttft_ms > 0 AND ttft_ms > 10000 AND ttft_ms <= 30000 THEN 1 ELSE 0 END), SUM(CASE WHEN ttft_ms > 0 AND ttft_ms > 30000 AND ttft_ms <= 60000 THEN 1 ELSE 0 END), SUM(CASE WHEN ttft_ms > 0 AND ttft_ms > 60000 AND ttft_ms <= 120000 THEN 1 ELSE 0 END), SUM(CASE WHEN ttft_ms > 0 AND ttft_ms > 120000 THEN 1 ELSE 0 END)
|
|
FROM usage
|
|
GROUP BY 1, 2, 3, 4, 5, 6;
|