chore: merge dev into v2 (#36312)

Co-authored-by: opencode-agent[bot] <219766164+opencode-agent[bot]@users.noreply.github.com>
Co-authored-by: LukeParkerDev <10430890+Hona@users.noreply.github.com>
Co-authored-by: opencode-agent[bot] <opencode-agent[bot]@users.noreply.github.com>
Co-authored-by: Aiden Cline <63023139+rekram1-node@users.noreply.github.com>
Co-authored-by: Brendan Allan <14191578+Brendonovich@users.noreply.github.com>
Co-authored-by: Aarav Sareen <96787824+arvsrn@users.noreply.github.com>
Co-authored-by: Julian Coy <julian@ex-machina.co>
Co-authored-by: Brendan Allan <git@brendonovich.dev>
Co-authored-by: usrnk1 <7547651+usrnk1@users.noreply.github.com>
Co-authored-by: opencode <opencode@sst.dev>
Co-authored-by: Vladimir Glafirov <vglafirov@gitlab.com>
Co-authored-by: Adam <2363879+adamdotdevin@users.noreply.github.com>
Co-authored-by: Frank <frank@anoma.ly>
Co-authored-by: Jay <53023+jayair@users.noreply.github.com>
Co-authored-by: Dustin Deus <deusdustin@gmail.com>
Co-authored-by: Kit Langton <kit.langton@gmail.com>
Co-authored-by: James Long <longster@gmail.com>
Co-authored-by: Simon Klee <hello@simonklee.dk>
Co-authored-by: Jay <air@live.ca>
Co-authored-by: Jack <jack@anoma.ly>
Co-authored-by: David Hill <1879069+iamdavidhill@users.noreply.github.com>
Co-authored-by: Aiden Cline <aidenpcline@gmail.com>
Co-authored-by: James Long <jlongster@users.noreply.github.com>
Co-authored-by: 冯基魁 <56265583+fengjikui@users.noreply.github.com>
Co-authored-by: Aiden Cline <rekram1-node@users.noreply.github.com>
Co-authored-by: Victor Navarro <vn4varro@gmail.com>
This commit is contained in:
opencode-agent[bot] 2026-07-10 15:11:29 -05:00 committed by GitHub
commit 43ecf3ff1b
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
82 changed files with 4519 additions and 1231 deletions

View file

@ -94,10 +94,15 @@ export type StatsModelComparisonEntry = {
tokenShare: number
tokenChange: number
totals: StatsModelData["totals"]
usage: ModelUsagePoint[]
}
export type StatsModelComparisonInput = {
provider: string
model: string
}
export type StatsModelComparisonData = {
updatedAt: string | null
models: [StatsModelComparisonEntry | null, StatsModelComparisonEntry | null]
models: (StatsModelComparisonEntry | null)[]
}
export type StatsHomeData = {
updatedAt: string | null
@ -289,27 +294,35 @@ function dateValue(value: unknown) {
return value instanceof Date ? value : new Date(stringValue(value))
}
export const getStatsModelComparisonData: (
firstProvider: string,
firstModel: string,
secondProvider: string,
secondModel: string,
) => Effect.Effect<StatsModelComparisonData, DatabaseError, ModelStatRepo> = Effect.fn("StatsModelComparison.getData")(
function* (firstProvider, firstModel, secondProvider, secondModel) {
export const getStatsModelsComparisonData: (
models: readonly StatsModelComparisonInput[],
) => Effect.Effect<StatsModelComparisonData, DatabaseError, ModelStatRepo> = Effect.fn("StatsModelsComparison.getData")(
function* (models) {
const modelStats = yield* ModelStatRepo
const rows = yield* modelStats.listDaily()
const first = toComparisonEntry(buildStatsModelData(firstModel, rows, [], firstProvider))
const second = toComparisonEntry(buildStatsModelData(secondModel, rows, [], secondProvider))
const latest = [first?.updatedAt, second?.updatedAt]
const entries = models.map((model) => toComparisonEntry(buildStatsModelData(model.model, rows, [], model.provider)))
const latest = entries
.map((model) => model?.updatedAt)
.flatMap((value) => (value ? [dateTime(value)] : []))
.toSorted((a, b) => b - a)[0]
return {
updatedAt: latest === undefined ? null : new Date(latest).toISOString(),
models: [first, second],
models: entries,
}
},
)
export const getStatsModelComparisonData = (
firstProvider: string,
firstModel: string,
secondProvider: string,
secondModel: string,
) =>
getStatsModelsComparisonData([
{ provider: firstProvider, model: firstModel },
{ provider: secondProvider, model: secondModel },
])
function buildStatsHomeData(
modelRows: ModelStatMetric[],
providerRows: ProviderStatMetric[],
@ -501,6 +514,7 @@ function toComparisonEntry(data: StatsModelData | null): StatsModelComparisonEnt
tokenShare: data.tokenShare,
tokenChange: data.tokenChange,
totals: data.totals,
usage: data.usage,
}
}

View file

@ -14,7 +14,10 @@ import { normalizeCountry, normalizeTier, type StatBaseAggregate } from "./stat"
export type StatDimension = "model" | "provider" | "geo" | "geo_model"
export function buildStatsQuery(periodStart: Date, periodEnd: Date, dimension: StatDimension) {
// All stat dimensions and both grains are computed in one query via GROUPING SETS so
// the source table is scanned once per sync pass; separate queries per dimension (and
// the previous weekly/daily UNION ALL) each re-scanned the same events.
export function buildStatsQuery(periodStart: Date, periodEnd: Date) {
const periodStartValue = sqlString(periodStart.toISOString())
const periodEndValue = sqlString(periodEnd.toISOString())
const periodStartDateValue = sqlString(periodStart.toISOString().slice(0, 10))
@ -22,23 +25,6 @@ export function buildStatsQuery(periodStart: Date, periodEnd: Date, dimension: S
const sourceTable = [Resource.InferenceEvent.catalog, Resource.InferenceEvent.database, Resource.InferenceEvent.table]
.map(sqlIdentifier)
.join(".")
const dimensionSql = (() => {
if (dimension === "model")
return {
select: "provider, model, COALESCE(MAX(NULLIF(provider_model, '')), '') AS provider_model",
groupBy: "provider, model",
}
if (dimension === "provider") return { select: "provider", groupBy: "provider" }
if (dimension === "geo_model")
return {
select: "provider, model, country, COALESCE(MAX(NULLIF(continent, '')), '') AS continent",
groupBy: "provider, model, country",
}
return {
select: "'all' AS provider, 'all' AS model, country, COALESCE(MAX(NULLIF(continent, '')), '') AS continent",
groupBy: "country",
}
})()
const aggregateColumns = `
COUNT(DISTINCT session) AS sessions,
COUNT(*) AS requests,
@ -135,34 +121,41 @@ WITH normalized AS (
COALESCE(cost_total_microcents, cost_total * 1000000) AS cost_total_microcents
FROM normalized
WHERE lower(model) NOT IN (${[...EXCLUDED_MODELS].map(sqlString).join(", ")})
), weekly AS (
), periods AS (
SELECT
concat(CAST(year_of_week(event_time) AS varchar), '-W', lpad(CAST(week(event_time) AS varchar), 2, '0')) AS week_key,
substr(to_iso8601(date_trunc('day', event_time)), 1, 10) AS day_key,
*
FROM filtered
), daily AS (
SELECT substr(to_iso8601(date_trunc('day', event_time)), 1, 10) AS day_key, *
FROM filtered
)
SELECT
'week' AS grain,
week_key AS period_key,
CASE WHEN grouping(week_key) = 0 THEN 'week' ELSE 'day' END AS grain,
COALESCE(week_key, day_key) AS period_key,
${sqlString(Resource.StatsSyncConfig.dataset)} AS dataset,
CASE
WHEN grouping(country) = 0 AND grouping(model) = 0 THEN 'geo_model'
WHEN grouping(country) = 0 THEN 'geo'
WHEN grouping(model) = 0 THEN 'model'
ELSE 'provider'
END AS dimension,
tier,
${dimensionSql.select},
CASE WHEN grouping(provider) = 0 THEN provider ELSE 'all' END AS provider,
CASE WHEN grouping(model) = 0 THEN model WHEN grouping(country) = 0 THEN 'all' END AS model,
CASE WHEN grouping(model) = 0 AND grouping(country) = 1 THEN COALESCE(MAX(NULLIF(provider_model, '')), '') END AS provider_model,
CASE WHEN grouping(country) = 0 THEN country END AS country,
CASE WHEN grouping(country) = 0 THEN COALESCE(MAX(NULLIF(continent, '')), '') END AS continent,
${aggregateColumns}
FROM weekly
GROUP BY week_key, tier, ${dimensionSql.groupBy}
UNION ALL
SELECT
'day' AS grain,
day_key AS period_key,
${sqlString(Resource.StatsSyncConfig.dataset)} AS dataset,
tier,
${dimensionSql.select},
${aggregateColumns}
FROM daily
GROUP BY day_key, tier, ${dimensionSql.groupBy}
FROM periods
GROUP BY GROUPING SETS (
(week_key, tier, provider, model),
(week_key, tier, provider),
(week_key, tier, country),
(week_key, tier, provider, model, country),
(day_key, tier, provider, model),
(day_key, tier, provider),
(day_key, tier, country),
(day_key, tier, provider, model, country)
)
ORDER BY grain, period_key, total_tokens DESC
`
}

View file

@ -1,4 +1,4 @@
import { and, asc, eq, inArray, or } from "drizzle-orm"
import { and, asc, eq, inArray, max, or } from "drizzle-orm"
import { Effect, Layer } from "effect"
import * as Context from "effect/Context"
import { DatabaseError, DrizzleClient } from "../database"
@ -43,6 +43,7 @@ export type ModelStatMetric = {
export declare namespace ModelStatRepo {
export interface Service {
readonly listDaily: () => Effect.Effect<ModelStatMetric[], DatabaseError>
readonly lastSyncedAt: () => Effect.Effect<Date | null, DatabaseError>
readonly upsert: (rows: ModelStatRow[]) => Effect.Effect<void, DatabaseError>
readonly deleteRetiredDimensions: (rows: ModelStatRow[]) => Effect.Effect<void, DatabaseError>
}
@ -111,6 +112,14 @@ export class ModelStatRepo extends Context.Service<ModelStatRepo, ModelStatRepo.
})
})
const lastSyncedAt = Effect.fn("ModelStatRepo.lastSyncedAt")(function* () {
const result = yield* Effect.tryPromise({
try: () => db.select({ value: max(modelStat.updated_at) }).from(modelStat),
catch: (cause) => DatabaseError.make({ cause }),
})
return result[0]?.value ?? null
})
const upsert = Effect.fn("ModelStatRepo.upsert")(function* (rows: ModelStatRow[]) {
yield* Effect.forEach(
chunks(rows, UPSERT_CHUNK_SIZE),
@ -192,7 +201,7 @@ export class ModelStatRepo extends Context.Service<ModelStatRepo, ModelStatRepo.
})
})
return ModelStatRepo.of({ listDaily, upsert, deleteRetiredDimensions })
return ModelStatRepo.of({ listDaily, lastSyncedAt, upsert, deleteRetiredDimensions })
}),
)
}