Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 23 additions & 4 deletions messages/en/dashboard.json
Original file line number Diff line number Diff line change
Expand Up @@ -61,13 +61,13 @@
"filters": {
"user": "User",
"provider": "Provider",
"sessionId": "Session ID",
"sessionId": "Session / Prefix ID",
"searchUser": "Search users...",
"searchProvider": "Search providers...",
"searchSessionId": "Search session IDs...",
"searchSessionId": "Search Session or Prefix IDs...",
"noUserFound": "No matching users found",
"noProviderFound": "No matching providers found",
"noSessionFound": "No matching session IDs found",
"noSessionFound": "No matching Session or Prefix IDs found",
"model": "Model",
"actualResponseModelMismatch": "Billing/actual model mismatch",
"endpoint": "Endpoint",
Expand Down Expand Up @@ -221,6 +221,23 @@
"viewFullError": "View full error",
"viewSession": "View Session"
},
"cachePerformance": {
"title": "Cache Performance",
"actualRate": "Actual Cache Rate",
"theoreticalRate": "Theoretical Cache Rate",
"coefficient": "Request Cache Coefficient",
"rawCoefficient": "Raw single-request coefficient; provider confidence is not applied.",
"estimateNote": "The theoretical rate is estimated from the longest normalized prefix (bytes / 4).",
"availability": {
"available": "Eligible request with a measurable prefix cache estimate.",
"no_input": "No input tokens were recorded for this request.",
"no_affinity_key": "No Prefix ID was recorded, so the theoretical rate and coefficient are unavailable.",
"attempt_failed": "The request attempt failed; the coefficient is excluded.",
"not_observable": "Upstream cache usage was not observable; the coefficient is excluded.",
"stream_truncated": "The stream was truncated; the coefficient is excluded.",
"not_recorded": "Prefix cache metrics were not recorded for this request."
}
},
"specialSettings": {
"title": "Special settings"
},
Expand Down Expand Up @@ -381,6 +398,8 @@
"metadata": {
"noMetadata": "No metadata available",
"sessionInfo": "Session Info",
"sessionId": "Session ID",
"prefixId": "Prefix ID",
"clientInfo": "Client Info",
"billingInfo": "Billing Info",
"technicalTimeline": "Technical Timeline",
Expand Down Expand Up @@ -695,7 +714,7 @@
"avgCostPerMillionTokens": "Avg Cost/1M Tokens",
"unknownModel": "Unknown",
"successRateUnavailable": "N/A",
"successRateBasisDisclosure": "Success rate is unavailable here because redirected billing mode can merge multiple original models into one row."
"successRateBasisDisclosure": "No countable success/failure outcomes were recorded for this model in the selected period."
},
"expandModelStats": "Expand model details",
"collapseModelStats": "Collapse model details",
Expand Down
27 changes: 23 additions & 4 deletions messages/ja/dashboard.json
Original file line number Diff line number Diff line change
Expand Up @@ -61,13 +61,13 @@
"filters": {
"user": "ユーザー",
"provider": "プロバイダー",
"sessionId": "セッションID",
"sessionId": "Session / Prefix ID",
"searchUser": "ユーザーを検索...",
"searchProvider": "プロバイダーを検索...",
"searchSessionId": "セッションIDを検索...",
"searchSessionId": "Session または Prefix ID を検索...",
"noUserFound": "一致するユーザーが見つかりません",
"noProviderFound": "一致するプロバイダーが見つかりません",
"noSessionFound": "一致するセッションIDが見つかりません",
"noSessionFound": "一致する Session または Prefix ID が見つかりません",
"model": "モデル",
"actualResponseModelMismatch": "課金/実応答モデル不一致",
"endpoint": "エンドポイント",
Expand Down Expand Up @@ -221,6 +221,23 @@
"viewFullError": "完全なエラーを表示",
"viewSession": "セッションを表示"
},
"cachePerformance": {
"title": "キャッシュ性能",
"actualRate": "実測キャッシュ率",
"theoreticalRate": "理論キャッシュ率",
"coefficient": "リクエストキャッシュ係数",
"rawCoefficient": "単一リクエストの生係数。プロバイダーの信頼度補正は適用しません。",
"estimateNote": "理論キャッシュ率は最長の正規化プレフィックス (バイト数 / 4) から推定されます。",
"availability": {
"available": "測定可能なプレフィックスキャッシュ推定値を持つ対象リクエストです。",
"no_input": "入力トークンが記録されていません。",
"no_affinity_key": "Prefix ID が記録されていないため、理論率と係数は利用できません。",
"attempt_failed": "リクエスト試行が失敗したため、係数は除外されています。",
"not_observable": "上流のキャッシュ使用量を観測できないため、係数は除外されています。",
"stream_truncated": "ストリームが途中で切断されたため、係数は除外されています。",
"not_recorded": "このリクエストではリクエスト単位のプレフィックスキャッシュ指標が記録されていません。"
}
},
"specialSettings": {
"title": "特殊設定"
},
Expand Down Expand Up @@ -381,6 +398,8 @@
"metadata": {
"noMetadata": "メタデータがありません",
"sessionInfo": "セッション情報",
"sessionId": "Session ID",
"prefixId": "Prefix ID",
"clientInfo": "クライアント情報",
"billingInfo": "課金情報",
"technicalTimeline": "技術タイムライン",
Expand Down Expand Up @@ -695,7 +714,7 @@
"avgCostPerMillionTokens": "100万トークンあたりコスト",
"unknownModel": "不明",
"successRateUnavailable": "利用不可",
"successRateBasisDisclosure": "redirected 課金モデルでは 1 行に複数の元モデルが混在しうるため、誤解を避けるためここでは成功率を表示しません。"
"successRateBasisDisclosure": "選択した期間にこのモデルの集計可能な成功/失敗結果がないため、成功率を計算できません。"
},
"expandModelStats": "モデル詳細を展開",
"collapseModelStats": "モデル詳細を折りたたむ",
Expand Down
27 changes: 23 additions & 4 deletions messages/ru/dashboard.json
Original file line number Diff line number Diff line change
Expand Up @@ -61,13 +61,13 @@
"filters": {
"user": "Пользователь",
"provider": "Поставщик",
"sessionId": "ID сессии",
"sessionId": "Session / Prefix ID",
"searchUser": "Поиск пользователей...",
"searchProvider": "Поиск провайдеров...",
"searchSessionId": "Поиск ID сессии...",
"searchSessionId": "Поиск Session или Prefix ID...",
"noUserFound": "Пользователи не найдены",
"noProviderFound": "Провайдеры не найдены",
"noSessionFound": "ID сессии не найдены",
"noSessionFound": "Session или Prefix ID не найдены",
"model": "Модель",
"actualResponseModelMismatch": "Модель тарификации отличается от фактической",
"endpoint": "Эндпоинт",
Expand Down Expand Up @@ -221,6 +221,23 @@
"viewFullError": "Показать полную ошибку",
"viewSession": "Просмотр сеанса"
},
"cachePerformance": {
"title": "Эффективность кэша",
"actualRate": "Фактическая доля кэша",
"theoreticalRate": "Теоретическая доля кэша",
"coefficient": "Коэффициент кэша запроса",
"rawCoefficient": "Необработанный коэффициент одного запроса; поправка доверия провайдера не применяется.",
"estimateNote": "Теоретическая доля оценивается по самому длинному нормализованному префиксу (байты / 4).",
"availability": {
"available": "Запрос подходит для оценки кэша префикса.",
"no_input": "Для запроса не записаны входные токены.",
"no_affinity_key": "Prefix ID не записан, поэтому теоретическая доля и коэффициент недоступны.",
"attempt_failed": "Попытка запроса завершилась ошибкой; коэффициент исключен.",
"not_observable": "Использование кэша у провайдера не наблюдалось; коэффициент исключен.",
"stream_truncated": "Поток был усечен; коэффициент исключен.",
"not_recorded": "Для этого запроса не записаны метрики кэша префикса."
}
},
"specialSettings": {
"title": "Особые настройки"
},
Expand Down Expand Up @@ -381,6 +398,8 @@
"metadata": {
"noMetadata": "Нет метаданных",
"sessionInfo": "Информация о сеансе",
"sessionId": "Session ID",
"prefixId": "Prefix ID",
"clientInfo": "Информация о клиенте",
"billingInfo": "Информация о биллинге",
"technicalTimeline": "Техническая хронология",
Expand Down Expand Up @@ -695,7 +714,7 @@
"avgCostPerMillionTokens": "Ср. стоимость/1М токенов",
"unknownModel": "Неизвестно",
"successRateUnavailable": "Н/Д",
"successRateBasisDisclosure": "В режиме redirected billing одна строка может объединять несколько исходных моделей, поэтому здесь успешность скрыта, чтобы не вводить в заблуждение."
"successRateBasisDisclosure": "За выбранный период у этой модели нет учитываемых успешных или неуспешных исходов, поэтому успешность не рассчитывается."
},
"expandModelStats": "Развернуть модели",
"collapseModelStats": "Свернуть модели",
Expand Down
27 changes: 23 additions & 4 deletions messages/zh-CN/dashboard.json
Original file line number Diff line number Diff line change
Expand Up @@ -61,13 +61,13 @@
"filters": {
"user": "用户",
"provider": "供应商",
"sessionId": "Session ID",
"sessionId": "Session / Prefix ID",
"searchUser": "搜索用户...",
"searchProvider": "搜索供应商...",
"searchSessionId": "搜索 Session ID...",
"searchSessionId": "搜索 Session 或 Prefix ID...",
"noUserFound": "未找到匹配的用户",
"noProviderFound": "未找到匹配的供应商",
"noSessionFound": "未找到匹配的 Session ID",
"noSessionFound": "未找到匹配的 Session 或 Prefix ID",
"model": "模型",
"actualResponseModelMismatch": "计费/实际模型不一致",
"endpoint": "端点",
Expand Down Expand Up @@ -221,6 +221,23 @@
"viewFullError": "查看完整错误",
"viewSession": "查看会话"
},
"cachePerformance": {
"title": "缓存表现",
"actualRate": "实际缓存率",
"theoreticalRate": "理论缓存率",
"coefficient": "本请求缓存系数",
"rawCoefficient": "单请求原始系数,不应用供应商窗口置信度折扣。",
"estimateNote": "理论缓存率根据最长规范化前缀估算(字节数 / 4)。",
"availability": {
"available": "请求符合条件,前缀缓存估算可测量。",
"no_input": "该请求没有记录输入令牌。",
"no_affinity_key": "未记录 Prefix ID,因此理论缓存率和缓存系数不可用。",
"attempt_failed": "请求尝试失败,缓存系数已排除。",
"not_observable": "无法观测上游缓存用量,缓存系数已排除。",
"stream_truncated": "响应流被截断,缓存系数已排除。",
"not_recorded": "该请求未记录单请求前缀缓存指标。"
}
},
"specialSettings": {
"title": "特殊设置"
},
Expand Down Expand Up @@ -381,6 +398,8 @@
"metadata": {
"noMetadata": "暂无元数据",
"sessionInfo": "会话信息",
"sessionId": "Session ID",
"prefixId": "Prefix ID",
"clientInfo": "客户端信息",
"billingInfo": "计费信息",
"technicalTimeline": "技术时间线",
Expand Down Expand Up @@ -695,7 +714,7 @@
"avgCostPerMillionTokens": "平均百万 Token 成本",
"unknownModel": "未知",
"successRateUnavailable": "不适用",
"successRateBasisDisclosure": "在 redirected 计费模型模式下,一行可能合并多个原始模型,因此这里不展示成功率以避免口径误导。"
"successRateBasisDisclosure": "所选时间段内该模型没有可计数的成功或失败结果,因此无法计算成功率。"
},
"expandModelStats": "展开模型详情",
"collapseModelStats": "收起模型详情",
Expand Down
27 changes: 23 additions & 4 deletions messages/zh-TW/dashboard.json
Original file line number Diff line number Diff line change
Expand Up @@ -61,13 +61,13 @@
"filters": {
"user": "使用者",
"provider": "供應商",
"sessionId": "Session ID",
"sessionId": "Session / Prefix ID",
"searchUser": "搜尋使用者...",
"searchProvider": "搜尋供應商...",
"searchSessionId": "搜尋 Session ID...",
"searchSessionId": "搜尋 Session 或 Prefix ID...",
"noUserFound": "未找到匹配的使用者",
"noProviderFound": "未找到匹配的供應商",
"noSessionFound": "未找到符合的 Session ID",
"noSessionFound": "未找到符合的 Session 或 Prefix ID",
"model": "Model",
"actualResponseModelMismatch": "計費/實際模型不一致",
"endpoint": "端點",
Expand Down Expand Up @@ -221,6 +221,23 @@
"viewFullError": "查看完整錯誤",
"viewSession": "查看工作階段"
},
"cachePerformance": {
"title": "快取表現",
"actualRate": "實際快取率",
"theoreticalRate": "理論快取率",
"coefficient": "本次請求快取係數",
"rawCoefficient": "單次請求原始係數,不套用供應商視窗信心折扣。",
"estimateNote": "理論快取率根據最長正規化前綴估算(位元組數 / 4)。",
"availability": {
"available": "請求符合條件,可測量前綴快取估算。",
"no_input": "此請求沒有記錄輸入 token。",
"no_affinity_key": "未記錄 Prefix ID,因此理論快取率和快取係數不可用。",
"attempt_failed": "請求嘗試失敗,快取係數已排除。",
"not_observable": "無法觀測上游快取用量,快取係數已排除。",
"stream_truncated": "回應串流被截斷,快取係數已排除。",
"not_recorded": "此請求未記錄單次前綴快取指標。"
}
},
"specialSettings": {
"title": "特殊設定"
},
Expand Down Expand Up @@ -381,6 +398,8 @@
"metadata": {
"noMetadata": "暫無中繼資料",
"sessionInfo": "工作階段資訊",
"sessionId": "Session ID",
"prefixId": "Prefix ID",
"clientInfo": "用戶端資訊",
"billingInfo": "計費資訊",
"technicalTimeline": "技術時間軸",
Expand Down Expand Up @@ -695,7 +714,7 @@
"avgCostPerMillionTokens": "平均每百萬 Token 成本",
"unknownModel": "未知",
"successRateUnavailable": "不適用",
"successRateBasisDisclosure": "在 redirected 計費模型模式下,一列可能合併多個原始模型,因此這裡不顯示成功率以避免口徑誤導。"
"successRateBasisDisclosure": "所選時間範圍內該模型沒有可計數的成功或失敗結果,因此無法計算成功率。"
},
"expandModelStats": "展開模型詳情",
"collapseModelStats": "收起模型詳情",
Expand Down
17 changes: 17 additions & 0 deletions src/actions/my-usage.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import { getTranslations } from "next-intl/server";
import { db } from "@/drizzle/db";
import { messageRequest, usageLedger } from "@/drizzle/schema";
import { getSession } from "@/lib/auth";
import type { RequestCacheMetricAvailability } from "@/lib/cache-effectiveness/request-metrics";
import { lookupIp } from "@/lib/ip-geo/client";
import { logger } from "@/lib/logger";
import { resolveKeyConcurrentSessionLimit } from "@/lib/rate-limit/concurrent-session-limit";
Expand Down Expand Up @@ -251,6 +252,14 @@ export interface MyUsageLogEntry {
cacheCreation5mInputTokens: number | null;
cacheCreation1hInputTokens: number | null;
cacheTtlApplied: string | null;
theoreticalCacheTokens: number | null;
cacheScoreEligible: boolean | null;
cacheScoreExcludedReason: string | null;
cacheInputTotal: number;
actualCacheRate: number | null;
theoreticalCacheRate: number | null;
requestCacheCoefficientBp: number | null;
requestCacheMetricAvailability: RequestCacheMetricAvailability;
}

export interface MyUsageLogsBatchResult {
Expand Down Expand Up @@ -656,6 +665,14 @@ function mapMyUsageLogEntries(
cacheCreation5mInputTokens: log.cacheCreation5mInputTokens ?? null,
cacheCreation1hInputTokens: log.cacheCreation1hInputTokens ?? null,
cacheTtlApplied: log.cacheTtlApplied ?? null,
theoreticalCacheTokens: log.theoreticalCacheTokens ?? null,
cacheScoreEligible: log.cacheScoreEligible ?? null,
cacheScoreExcludedReason: log.cacheScoreExcludedReason ?? null,
cacheInputTotal: log.cacheInputTotal,
actualCacheRate: log.actualCacheRate,
theoreticalCacheRate: log.theoreticalCacheRate,
requestCacheCoefficientBp: log.requestCacheCoefficientBp,
requestCacheMetricAvailability: log.requestCacheMetricAvailability,
};
});
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,11 @@ type AnyEntry =
| ModelEntry;

function renderSuccessRateCell(
row: { successRate: number | null; basisDisclosureRequired?: boolean },
row: {
successRate: number | null;
basisDisclosureRequired?: boolean;
successRateUnavailableReason?: "no_countable_outcomes";
},
t: ReturnType<typeof useTranslations>
) {
const display = getSuccessRateCellDisplay(row, t);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
export interface SuccessRateDisplayRow {
successRate: number | null;
basisDisclosureRequired?: boolean;
successRateUnavailableReason?: "no_countable_outcomes";
}

export interface SuccessRateDisplayValue {
Expand All @@ -21,6 +22,9 @@ export function getSuccessRateCellDisplay(

return {
label: t("columns.successRateUnavailable"),
title: row.basisDisclosureRequired ? t("columns.successRateBasisDisclosure") : undefined,
title:
row.successRateUnavailableReason === "no_countable_outcomes"
? t("columns.successRateBasisDisclosure")
: undefined,
};
}
Loading
Loading