From c08190458fedcfcd183426d2a625c7528e9e0eab Mon Sep 17 00:00:00 2001 From: opsx Date: Thu, 29 Oct 2026 13:09:14 +0800 Subject: [PATCH] =?UTF-8?q?fix(alerts,db):=20=E6=B8=85=E7=90=86=E5=8E=86?= =?UTF-8?q?=E5=8F=B2=E8=AF=AF=E7=A7=8D=E7=9A=84=20K8s=20=E5=9F=BA=E7=A1=80?= =?UTF-8?q?=E8=AE=BE=E6=96=BD=E5=91=8A=E8=AD=A6=E8=A7=84=E5=88=99=20+=20?= =?UTF-8?q?=E6=95=B0=E6=8D=AE=E8=BF=81=E7=A7=BB=E4=B8=8D=E7=95=99=E6=A1=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - seed 启动时一次性删除早期版本种入的「Kubernetes 节点 NotReady」「容器 OOMKilled」 (日志平台只关注应用日志,节点/容器状态告警归 Prometheus;源码早已移除该模板,但幂等只跳过不清理,旧库存量一直在) - 数据文件迁移为 lokistack.json 后直接删除旧文件,不再留 .migrated-*.bak(测试同步) --- backend/repository/db.go | 9 ++++----- backend/repository/db_migrate_test.go | 16 +++------------- backend/seed/alert_rules.go | 19 +++++++++++++++++++ 3 files changed, 26 insertions(+), 18 deletions(-) diff --git a/backend/repository/db.go b/backend/repository/db.go index 1524f62..0ef44b7 100644 --- a/backend/repository/db.go +++ b/backend/repository/db.go @@ -540,7 +540,7 @@ func (d *JsonDB) migrateSchema() bool { } // migrateLegacyDataFile 首次从历史命名(opsxloki.json / lokideploy.json)加载后, -// 立即升级到 lokistack.json:数据原子写入新文件,旧文件改名 .migrated-*.bak 留档。 +// 立即升级到 lokistack.json:数据原子写入新文件后删除旧文件。 // 不迁移的话回退链会让旧文件名(旧品牌残留)一直被沿用下去。 func (d *JsonDB) migrateLegacyDataFile() { const newName = "lokistack.json" @@ -560,12 +560,11 @@ func (d *JsonDB) migrateLegacyDataFile() { log.Printf("[ERROR] [db] 迁移数据文件到 %s 失败(%v),继续使用 %s", newPath, err, legacyPath) return } - backup := fmt.Sprintf("%s.migrated-%s.bak", legacyPath, time.Now().Format("20060102-150405")) - if err := os.Rename(legacyPath, backup); err != nil { - log.Printf("[db] 数据已写入 %s,但旧文件 %s 改名留档失败(%v)", newPath, legacyPath, err) + if err := os.Remove(legacyPath); err != nil { + log.Printf("[db] 数据已写入 %s,旧文件 %s 删除失败(%v),可手工清理", newPath, legacyPath, err) return } - log.Printf("[db] 数据文件已从 %s 升级为 %s(原文件留档 %s)", legacyPath, newPath, backup) + log.Printf("[db] 数据文件已从 %s 升级为 %s", legacyPath, newPath) } // loadFromDisk 读取并解析数据文件,重建 ID 序列;文件损坏时备份留档绝不覆盖。 diff --git a/backend/repository/db_migrate_test.go b/backend/repository/db_migrate_test.go index 091aed9..7e95d9a 100644 --- a/backend/repository/db_migrate_test.go +++ b/backend/repository/db_migrate_test.go @@ -29,19 +29,9 @@ func TestMigrateLegacyDataFile(t *testing.T) { if !strings.Contains(string(content), `"admin"`) { t.Fatalf("迁移后数据不完整: %s", content[:min(len(content), 120)]) } - // 旧文件被改名留档,原内容不丢 - entries, _ := os.ReadDir(dir) - backedUp := false - for _, e := range entries { - if strings.HasPrefix(e.Name(), "opsxloki.json.migrated-") { - kept, _ := os.ReadFile(filepath.Join(dir, e.Name())) - if string(kept) == seed { - backedUp = true - } - } - } - if !backedUp { - t.Fatalf("旧文件未留档或内容被改动: %v", entries) + // 旧文件迁移成功后直接删除(不留档) + if _, err := os.Stat(legacy); !os.IsNotExist(err) { + t.Fatalf("旧文件应被删除: %v", err) } // dataFile 已切到新路径 if filepath.Base(d.dataFile) != "lokistack.json" { diff --git a/backend/seed/alert_rules.go b/backend/seed/alert_rules.go index d428175..f8dda6b 100644 --- a/backend/seed/alert_rules.go +++ b/backend/seed/alert_rules.go @@ -6,6 +6,7 @@ package seed // 绑定数据源:部署成功自动注册的 LogSource(managed)。 // 规则默认不启用(通知通道由管理员后期在设置页配置后再开启),ChannelIDs 留空。 import ( + "slices" "time" "lokistack/models" @@ -89,9 +90,27 @@ var builtinRules = []builtinRule{ // seedBuiltinAlertRules 为每个平台管理的 LogSource(managed=true)补齐内置规则: // 首次部署 Loki 后即有一套可直接启用的告警模板;通知通道留空,管理员配置后启用。 +// legacyInfraRules 早期版本误种的 Kubernetes 基础设施类规则 —— 日志平台只关注应用日志, +// 这类节点/容器状态告警属 Prometheus + Alertmanager 职责,升级时一次性清理存量。 +var legacyInfraRules = []string{"Kubernetes 节点 NotReady", "容器 OOMKilled"} + // SeedAlertRules 补齐内置告警规则(幂等;公开给启动与部署成功两处调用) func SeedAlertRules() { + // 先清掉历史遗留的基础设施类规则(只删名字精确匹配的这两条) db := repository.GetDB() + db.Lock() + kept := db.AlertRules[:0] + for _, rule := range db.AlertRules { + if !slices.Contains(legacyInfraRules, rule.Name) { + kept = append(kept, rule) + } + } + if len(kept) != len(db.AlertRules) { + db.AlertRules = kept + db.RequestSave() + } + db.Unlock() + db.RLock() type srcRef struct { id uint