mirror of
https://gitcode.com/JianFeeeee/ModelRouter.git
synced 2026-11-12 04:07:25 +00:00
生产现网发现(issue #1 排查):billing.rules 里一条指向 https://opencode.ai/inference/v1 的规则,在该源 base_url 变成 .../inference/openai/v1 之后匹配不到任何源;严格编译因此让**整个** profile 不生效 —— 账单恒 0、unpriced_reqs 涨到 3.7 万,唯一痕迹是一行启动日志。 - 严格编译失败时降级为 lenient:应用能匹配的规则,其余按 profile default; - 日志用 ERROR 点名**具体哪条 URL** 写错(新增 billing.UnmatchedRuleURLs), 并说明未匹配流量的记账去向; - 判据 TestBillingStaleRuleURLStillAppliesOtherRules:一条过期规则 + 一条有效 规则 ⇒ 有效规则必须仍然生效。
61 lines
2.1 KiB
Go
61 lines
2.1 KiB
Go
package core
|
||
|
||
import (
|
||
"path/filepath"
|
||
"testing"
|
||
|
||
"llmsproxy/internal/config"
|
||
)
|
||
|
||
// 一个过期的规则 URL 不得让**整个**计费 profile 失效。
|
||
//
|
||
// 真实事故(GitCode issue #1 排查中发现,生产现网):config.yaml 里
|
||
// `billing.rules[0].url` 是 `https://opencode.ai/inference/v1`,而该源的
|
||
// base_url 已是 `.../inference/openai/v1`。严格编译因此返回
|
||
// "rule url ... matches no configured source base_url",applyBillingDSL 直接
|
||
// return —— 于是**所有**计费规则都不生效:账单恒为 0、unpriced_reqs 涨到 3.7 万,
|
||
// 而唯一的痕迹是一行启动日志。这正是「静默少报」最严重的一种。
|
||
//
|
||
// 修法:严格编译失败时降级为 lenient(用能匹配的规则),并打 ERROR 说明后果。
|
||
// 一个 URL 写错不该把整个价目表一起葬送;但也不能装作成功。
|
||
func TestBillingStaleRuleURLStillAppliesOtherRules(t *testing.T) {
|
||
cfg := newTestConfig(t)
|
||
dir := t.TempDir()
|
||
cfg.PluginDir = filepath.Join(dir, "plugins")
|
||
cfg.Sources = []config.Source{
|
||
{Name: "localzen", BaseURL: "https://opencode.ai/inference/openai/v1", Adapter: "openai",
|
||
Models: []config.Model{{ID: "m"}}},
|
||
}
|
||
cfg.BillingDSL = &config.BillingDSL{
|
||
Active: "p",
|
||
Profiles: []config.BillingProfile{{
|
||
ID: "p",
|
||
Rules: []config.BillingRule{
|
||
// 过期 URL:没有任何源的 base_url 与它相等
|
||
{URL: "https://opencode.ai/inference/v1", Mode: "free"},
|
||
// 有效规则:必须仍然生效
|
||
{URL: "https://opencode.ai/inference/openai/v1", Mode: "free"},
|
||
},
|
||
}},
|
||
}
|
||
c := newTestCore(t, cfg)
|
||
c.applyBillingDSL()
|
||
|
||
raw := c.plugins.Prices("billing")
|
||
if raw == nil {
|
||
t.Fatal("billing has no price table (profile never applied)")
|
||
}
|
||
prices, ok := raw.(map[string]interface{})
|
||
if !ok {
|
||
t.Fatalf("price table shape: %#v", raw)
|
||
}
|
||
sources, ok := prices["sources"].(map[string]interface{})
|
||
if !ok {
|
||
t.Fatalf("prices has no sources: %#v", prices)
|
||
}
|
||
if _, ok := sources["localzen"]; !ok {
|
||
t.Fatalf("一条过期规则 URL 把整个 profile 弄失效了:有效的 free 规则也没有生效,"+
|
||
"结果是账单恒为 0 且没有告警。prices=%#v", prices)
|
||
}
|
||
}
|