| 文件 | 最后提交记录 | 最后更新时间 |
|---|---|---|
fix(audit): consolidate boom_request_log DDL ownership, fix cached_tokens missing column The cached_tokens column added by upstream PR !38 was never actually created in the database: boom-audit's run_request_log_migration was the intended owner of the DDL, but nothing called it — boom-dashboard's run_migrations kept running a hand-copy-pasted version of the same DDL and skipped cached_tokens with a "Not duplicated here" comment, while boom-main only invoked run_migrations. Result: list_logs query against rl.cached_tokens failed with "Column rl.cached_tokens does not exist". Consolidate all boom_request_log DDL into boom-audit as the sole owner per the architecture rules: - Change run_request_log_migration to take &mut PgConnection so it reuses the caller's lock_timeout and runs on the same connection as the rest of the migration sequence. - Move the ALTER TABLE ... ADD COLUMN statements for key_alias, deployment_id, model_name, client_ip, ttft_ms, cached_tokens and the model_name / created_apipath indexes from boom-dashboard into boom-audit. - boom-dashboard's step 1/7 now just calls run_request_log_migration, eliminating the duplicated DDL. Signed-off-by: liqiang <liqiang64@huawei.com> | 22 天前 | |
fix(dashboard): keys/quota 界面多处数据源与展示修复 4 个独立修复一并提交: 1. 新库首部署 key 访问报 "column permissions does not exist" 根因:key_auth.rs 的 SELECT 引用了 boom_verification_token 表里 不存在(也无人使用)的 permissions 列。DDL 没建这列是因为 boom-gateway 从不读写它。从 SELECT 和 VerificationToken struct 里删除该字段。老库(litellm 继承过来的旧表)少 SELECT 一列 完全无害。 2. keys 界面 SPEND 列永远 0 根因:list_keys/get_key_info 把 boom_verification_token.spend (litellm 兼容列,boom-gateway 从不写入)作为累计 cost 返回。 改成从 QuotaStore.peek_cumulative(Key, TotalCost) 读真实累计 cost(boom_rate_limit_cumulative backed)。KeyRow 同时去掉 spend 字段。前端 SPEND 列改用 fmtCost(兼容 Decimal 字符串)。 顺手在用户态 get_key_info 也做同样修复,两个界面数据口径一致。 3. quota 卡片 team 套餐规格展示不全 + "RPM" 标签误导 根因:effective_limits() 只返回 concurrency/rpm/windows, total_token_limit/total_cost_limit/tpm_limit 没透传给前端, 前端无法显示累计上限;60s counts 笼统叫 "RPM",混合窗口里 tokens/costs 维度被遮蔽;未配置字段不出现,operator 看不出 "未卡" vs "不支持"。 修法:后端 effective_limits JSON 多带 tpm_limit / total_token_limit / total_cost_limit。前端 renderTeamEffectiveLimits 重写为紧凑单行 tag:并发 / 60s槽位(合并 rpm+tpm+60s window) / 其他窗口 / 累计 token / 累计 cost,每个维度都至少出现一次, 未配置的显式标 ∞。新增 .plan-tag 样式。 4. 创建 key 时 team 下拉为空(前次已修,保留) 前端 key 创建 modal 调 GET /admin/teams 拉 team 列表填充 下拉框,但该路由只注册了 POST,.catch(() => {}) 静默吞错。 修法:team 列表从 quota_overview 缓存(window._teams)读取, 缓存冷时 fallback 到 /admin/quota/overview。 Signed-off-by: liqiang <liqiang64@huawei.com> Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com> Signed-off-by: liqiang <liqiang64@huawei.com> | 13 天前 | |
refactor(quota): 修复 team RPM commit + 重命名 total_token_limit + 删除 cost_limit - 修复 team 维度 RPM/counts-window commit 遗漏:PlanCharge 新增 team_key/team_rpm_limit/team_window_counts 字段,commit() 同时 commit team 维度计数器。修复前 peek 永远看到 0 计数,team 总和 RPM 不生效。 - 重命名 total_tpm_limit → total_token_limit(语义纠正:TPM 是 per-minute 概念,但此字段是累计总量),覆盖 Rust 字段、DB 列、 SQL、JSON、前端、i18n。migration 加 RENAME COLUMN。 - 删除 cost_limit 字段(每分钟 cost 上限无业务需求),覆盖结构体、 merge_shorthand、parse_schedule、DB 列、SQL、前端、i18n、测试。 migration 加 DROP COLUMN cost_limit_micros。 - 移除 dashboard config 配置页面(KV store 管理界面)。 - 精简 config.example.yaml 为 OpenAI 示例,补全 plan 所有字段 (含 schedule/member_plan/total_token_limit/total_cost_limit) + cost_templates 模板 + prompt_log 段,每个 plan 字段末尾加注释。 Signed-off-by: liqiang <liqiang@atomgit.com> Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com> Signed-off-by: liqiang <liqiang64@huawei.com> | 14 天前 | |
feat(dashboard): 模型禁用行变灰 + 团队页改标题/修 bug + 加编辑入口 + 版本号 26.0715.0940 模型页:禁用的 deployment 行整体加 .model-row-disabled 类,整行透明度 0.55 + 灰色文字, 保留 badge 和按钮的可读性;故障禁用警告行也抽成 .model-row-warning 类复用。 团队管理页(原配额管理): - 标题 "quota.title" 改为 "团队管理" / "Team" - 修可用模型 bug:models=[] 按 CLAUDE.md 约定是"全权限",本应渲染为 "全部模型", 之前误显示为 "未配置可用模型"。空数组与 ["all-team-models"] 统一走 chip 分支。 - 团队卡片 actions 加 "编辑" 按钮,复用 showCreateTeamModal(编辑模式), 可改团队别名、可用模型、显式套餐;id 仍只读。新增 window._editTeam 入口。 版本号:26.0710.1750 → 26.0715.0940 Signed-off-by: liqiang <liqiang@atomgit.com> Signed-off-by: liqiang <liqiang64@huawei.com> | 9 天前 | |
feat(dashboard): add token-share charts and 24h deployment summary Two related stats-page extensions: 1. Agent Statistics — input/output token share charts - Extend AgentStatsTracker ring buffer to also accumulate per-bucket input/output token totals split by anthropic vs other. Previously only request counts were tracked. - New record_tokens(api_path, input, output) hook called from the three log_request sites (LoggedStream::drop for streaming, plus chat_completions and /v1/messages non-streaming success paths). - get_agent_stats handler returns the four new token fields on both memory (1h) and DB (4h+) paths; DB SQL adds SUM(...) FILTER (...) aggregations. - Frontend renders Request Volume + Input Tokens + Output Tokens stacked-bar charts and 5 summary cards (added Anthropic Input Tokens, Anthropic Output Tokens). 2. In-Flight table — 24h per-deployment summary columns - New endpoint GET /admin/stats/deployments/summary returns 24h aggregates (total_requests with input tokens, avg_input_tokens, avg_output_tokens, avg_ttft_ms) grouped by deployment_id. AVG skips NULL automatically, so averages are over rows that have the relevant field. - Off the 3s auto-poll: fetched only on page load and via the previously-dormant #btn-refresh-inflight button (now wired up). renderInflightTable reads from a module-level cache, so the auto-refresh re-renders the table without triggering new DB queries. - Four new trailing columns on the In-Flight Requests table. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com> Signed-off-by: liqiang <liqiang64@huawei.com> | 27 天前 | |
feat(dashboard): 登录页改左右分栏 + WebP 压缩 hero 图 左列放品牌插画,右列保留原表单卡片;≤960px 自动收成单列、隐藏插画。 插画走 cwebp -q 85 压缩,1.8MB PNG → 325KB WebP(17.5%),视觉无损。 - /dashboard/assets/login.png 新路由返回 image/webp(URL 保留 .png 后缀避免破坏外部链接) - index.html 包一层 .login-shell,左 .login-hero + 右原 .login-card - style.css 新增 grid 分栏 + 窄屏 fallback;.login-card 宽度由 grid 决定 Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com> Signed-off-by: liqiang <liqiang64@huawei.com> | 2 天前 | |
fix(routing): defer plan quota commit until upstream accepts request Plan quota was charged at handler entry (check_plan_or_default_limits), before flow control queuing and before the request reached the upstream provider. When a client disconnected mid-queue or the provider call failed, the quota was already consumed and the rollback path for flow control timeouts was missing — leading to quota burn with no upstream service and no visible log (FlowControlQueueTimeout is dedup'd). Split check_and_record into peek_only (read-only) + commit_record (write). check_plan_limits now returns a PlanCharge that is committed only after provider.chat_stream/chat returns Ok. Dropping PlanCharge without commit consumes zero quota; the ConcurrencyGuard releases via its own Drop. This removes the entire rollback machinery (PlanRollback / rollback_plan_quota / rollback_plan_windows / unrecord_window) since the "charged but failed" window no longer exists. Principle 2 (client disconnect cleanup) is already handled by the existing AcquireCleanup::drop in flow control — added tests to verify the future-drop path actually removes queued requests. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com> Signed-off-by: liqiang <liqiang64@huawei.com> | 24 天前 | |
Revert "!40 feat: kvc-aware dfx observability + scoring-stage rebalance + per-deployment kvc config" This reverts commit 69f0ec576e7c282e8ba54fe95f3670a12ef6761c, reversing changes made to 919b0fbb2106d2b2b1e8abb79073c3ddc07fb2ee. | 20 天前 | |
refactor(quota): 限流配额归一化 — limiter 成为唯一存储,删 QuotaStore 老板报告的 bug:key plan 配 rpm_limit=2 实际只允许 1 个请求。根因是 effective_limits() 把 rpm 单独透传,调用方又同时把 rpm 字段和含 60s counts 的 windows 都传给 limiter,commit_record 对同一 cache_key 写两次。 归一化重构从三层防线堵死双重统计路径: 1. 数据流:effective_limits() 返回 (concurrency, windows, stale) 三元组, 不再单独透传 rpm。rpm_limit/tpm_limit 由 merge_shorthand 折叠进 windows 的 60s 项的 counts/tokens 字段。PlanCharge 同步删 rpm_limit 字段, 24 字段收敛到 17。 2. 实现:commit_counts / settle_usage 内部按 window_secs 去重 — 即使 windows 里有重复 secs,每个 cache_key 也只 bump 一次。 SlidingWindowLimiter.WindowCounter 扩展为三维度(counts/tokens/costs_micros), 一个 cache_key 同时存三维度,与 WindowLimit 结构对齐。 3. 回归测试:test_rpm_limit_2_actually_allows_2_requests_e2e 端到端 复现老板原 bug 场景,验证 rpm_limit=2 真的允许 2 个请求。 test_tpm_limit_tokens_window_no_double_settle 对 tpm 做同样验证。 test_rpm_field_form_equals_window_limits_form 锁定两种 YAML 形式 产生相同 effective_limits 输出。 副作用: - boom-quota crate 整体删除。cumulative 表 DDL 迁移到 boom-limiter::migrations, cache_key 格式(kc:{kh}:{kind} / tc:{tid}:{kind})和 boom_rate_limit_cumulative 表名不变,无需 DB 数据迁移。 - spawn_quota_sync_task 合并到 spawn_sync_task(10 分钟周期)。 - dashboard 30+ callsite 改为 limiter.* / boom_limiter::*。 - dashboard 旧的 effective_limits() 4 元组解构改为 3 元组, rpm_limit 从 60s window_limits.counts 字段提取以保持前端兼容。 - 新增 state_alter_ddl() 给现有 boom_rate_limit_state 加 tokens + costs_micros 列(幂等 ALTER)。 - 删除 boom-core 里失效的 RateLimiter trait。 测试:cargo test --workspace 126 passing,唯一失败是 pre-existing 的 hybrid_router::tests::code_request_routes_to_large(已确认 master 上同样失败)。 Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com> Signed-off-by: liqiang <liqiang64@huawei.com> | 13 天前 | |
fix(reload): 热加载加 timeout + panic 兜底,失败不影响主进程可用性 老板报告:用户改 config.yaml 出错触发热加载,会让网关"卡住"。代码读完, 真问题比表面复杂——分三层 bug: 1. DB I/O 无 timeout:sync_yaml_to_db 和 3 个 load_db_only_* 都是裸 .await, DB 卡住时整个 reload future 永远不返回。对 SIGHUP listener 而言,该 task 永远 await → 后续 SIGHUP 全部丢失;对 HTTP 而言,请求 hang 死。 2. Panic 无兜底:build 步骤若 panic(unwrap 失败、第三方库 panic 等),顺着 task 传播,SIGHUP/HTTP task 死掉,之后热加载入口永久失效。 3. 状态半提交:stores 在 reload 中段就 clear(),若后续步出错/挂死,状态 半坏(旧 inner 还在路由,但 store 已空)。本次不修——需要 shadow-build + Arc<ArcSwap<DeploymentStore>> 重构,作为 TODO。 修复方案(分层安全网,不重构): - state.rs: reload() 改为 wrapper(60s 总 timeout + catch_unwind),原逻辑 搬到 reload_inner()。任何步骤失败、挂死、panic 都保证 60s 内返回 Err。 - state.rs: 新增 with_db_timeout / with_db_timeout_void,4 处 DB I/O 各加 15s 独立 timeout,避免单步 DB 慢操作拖垮整个 reload。 - main.rs: SIGHUP listener 加 tokio::sync::Mutex try_lock 串行化,避免连按 多次 SIGHUP 时 reload 叠加;try_lock 而非 lock().await 保证 listener 本身 不阻塞。 - app.js + i18n.js: reload 失败提示改为 "本次热加载未生效:{message}。网关 仍按上一次配置运行,请修复问题后重试。" 让用户明确知道网关没坏,是配置 问题。 验证: - cargo build --workspace 通过 - YAML 语法错 → load_config 早退(已有),reload 干净返回 Err,前端弹"未生效" - DB 卡死 → 15s 内单步超时 → reload 60s 内总超时 → 返回 Err → 旧 config 仍生效 - 任何 panic → catch_unwind 转 Err → 旧 config 仍生效 - 连按 SIGHUP → 第二次起日志打"reload in progress, skipping" Signed-off-by: liqiang <liqiang@atomgit.com> Signed-off-by: liqiang <liqiang64@huawei.com> | 8 天前 | |
feat: capture raw upstream response for OpenAI provider observability Squashes feat/raw-upstream-response-capture (921fae7 + 9c6d030) into a single commit on master. - Provider trait carries raw upstream text on ChatCompletionResponse (serde-skipped, observability only). - OpenAI provider records the raw response body (non-streaming) and raw SSE chunks (streaming) so prompt-log tree viewer can show exactly what the upstream returned, before any gateway-side conversion. - Prompt-log config + entry + stream wire the captured text through to the dashboard, gated by the existing debug toggle so production traffic is not affected unless explicitly enabled. - Dashboard admin handler exposes the toggle; routes.rs passes the flag down to the provider path. - Anthropic/Gemini providers annotate the same field for consistency. - boom-core test literals updated for the new ChatCompletionResponse field so the test suite compiles. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com> Signed-off-by: liqiang <liqiang64@huawei.com> | 1 个月前 | |
Revert "!40 feat: kvc-aware dfx observability + scoring-stage rebalance + per-deployment kvc config" This reverts commit 69f0ec576e7c282e8ba54fe95f3670a12ef6761c, reversing changes made to 919b0fbb2106d2b2b1e8abb79073c3ddc07fb2ee. | 20 天前 | |
feat(quota): 计费用量三维度累计 + 套餐徽章 + 修 rpm_limit 残留 - 计费用量三维度累计:CumulativeKind 增加 cric/ccic/coc 三种 cost 维度; settle_usage 接受 3 个 Decimal cost 分量;deployment_store 新增 compute_cost_breakdown 返回 (regular_input, cached_input, output); 前端累计卡片显示三种 cost。 - 套餐徽章:plan 显式分配显示 badge-plan,default fallback 显示 badge-default。 - 修 rpm_limit 残留:keys 列表里删除 litellm legacy 字段 rpm_limit。 - Team 管理合并到配额页面:删除 list_teams handler + GET /admin/teams 路由; 扩展 quota_overview 返回 plan_explicit/models/effective_limits/ prompt_log_excluded;重写 teamCard 含 plan 下拉 + prompt-log toggle + 删除按钮;配额页加创建团队按钮;删 Teams nav-link + admin-teams section。 - Debug 页面条件编译:加 debug-tools feature(dev 默认开、release 默认关), 3 个 debug handler + 3 条 debug 路由用 #[cfg] 隔离;前端运行时检测 404 隐藏。 - 套餐表格补全字段:tpm_limit / cost_limit / total_tpm_limit / total_cost_limit / member_plan / schedule。 - 密钥页面用量列三维度:list_keys 扩展 usage_tokens / usage_cost (从 QuotaStore.peek_key_windows 聚合最小窗口);前端按 "次数/token/计费" 格式展示;列标题改为"用量(次数/token/计费)"。 - 按钮 i18n 修复:plans.add / keys.add / assignments.add / config.set_value 补 data-i18n;prompt-log ON/OFF 改 i18n;修 btn-sm 类名错误(应为 btn-small); 修 .btn-secondary width:100% 在 btn-small 组合下撑满的问题。 - 分析结论:boom_config 表是 dashboard-only KV 存储,与运行时 YAML 配置 完全解耦,配置页面写入不影响网关运行时。 Signed-off-by: liqiang <liqiang@atomgit.com> Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com> Signed-off-by: liqiang <liqiang64@huawei.com> | 15 天前 | |
feat: add per-model request rate charts to dashboard Stats page Track per-deployment request counts over the last 60 minutes using a RequestRateTracker (DashMap<String, RebalanceCounter> ring buffer). Display bar charts for ALL MODELS total and each deployment on the Stats page, ordered same as in-flight requests table. Signed-off-by: liqiang <liqiang@atomego> Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com> Signed-off-by: liqiang <liqiang64@huawei.com> | 1 个月前 |
| 文件 | 最后提交记录 | 最后更新时间 |
|---|---|---|
| 22 天前 | ||
| 13 天前 | ||
| 14 天前 | ||
| 9 天前 | ||
| 27 天前 | ||
| 2 天前 | ||
| 24 天前 | ||
| 20 天前 | ||
| 13 天前 | ||
| 8 天前 | ||
| 1 个月前 | ||
| 20 天前 | ||
| 15 天前 | ||
| 1 个月前 |