Files
OpenFlare/.agents/skills/logstore/SKILL.md
T
2026-08-16 11:32:13 +08:00

76 lines
4.2 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
---
name: "logstore"
description: "OpenFlare / Wavelet:当新增或修改日志/分析用途表(节点访问日志、用户访问日志、可观测时序)、接入 internal/repository/logstore、切换日志主库、实现 PG/SQLite 回落,或判断一张表该走业务主库还是日志库时必须使用。"
---
# 日志用途表开发
开始前阅读根目录 `AGENTS.md`。DDL 用 `database-migration`;高频写入队列用 `clickhouse-batchwriter`;切换任务用 `new-async-task`。本技能只回答:**这张表是不是日志表,以及如何接入可切换的日志主库。**
设计背景见 [日志存储解耦](../../../docs/design/logstore.md)。
## 先判定
日志表同时满足:
- 追加写入、几乎不更新单行
- 按时间查询/聚合,允许按保留天数删除
- 关闭 ClickHouse 后仍要能写、能查
- 不参与网站/节点/证书等事务一致性
**不要**做成日志表:Zone、节点、配置版本、任务执行、上传元数据。这些走主库 `repository`。
当前日志域:
| 域 | 接口 | 表 |
| :--- | :--- | :--- |
| 节点访问日志 | `AccessLogStore` | `of_node_access_logs` |
| 可观测 | `ObservabilityStore` | `of_node_metric_snapshots` / `of_node_edge_health` / `of_node_obs_frps` / `of_node_obs_frpc` |
| 用户访问审计 | `UserAccessLogStore` | `w_user_access_logs` |
## 分层
| 层级 | 路径 | 职责 |
| :--- | :--- | :--- |
| 抽象 | `internal/repository/logstore` | 接口 + `Active`/`BuildForMigration`;apps **只**面向这里或 `repository` 门面 |
| CH 实现 | `logstore/clickhouse_store.go` 委托 `analytics` | 原生批量 + 现有聚合 SQL |
| 主库实现 | `logstore/postgres_store.go` | PG(按月分区)与 SQLite(普通表)共用 GORM |
| Model | `internal/model/analytics` | 实体与批量 SQL,无 IO |
| 入队 | `chwriter` / `risk_control` + `batchwriter` | flush 调 logstore `BatchInsert*`;CH 入队经 hooks |
| 切换 | `of_log_db_switch` | 冻结 → `chwriter.Drain` → 逐表复制 → 翻转 |
| 约束 | `logstore/imports_test.go` | apps 禁止 import `repository/analytics` |
`log_database` 只能是「随主库」或 `clickhouse`。`log_database` / `log_db_migration` 受保护。
## 新增一张日志表
1. **Model**(`internal/model/analytics`):`TableName` + `InsertColumns` / `BatchInsertSQL`。
2. **三套 DDL**:CH `MergeTree` + `toYYYYMM`;PG `PARTITION BY RANGE(时间列)`(主键含分区键);SQLite 普通表。不要在主库建 CH 物化视图,聚合实时算。
3. **挂到已有域或新接口**:能进 `AccessLogStore` / `ObservabilityStore` / `UserAccessLogStore` 就不要再拆包。新域才新增接口并放进 `Store`。
4. **方法最少集**:`BatchInsert`(含 `ensureWritable`)、业务查询、`ListForMigration`、`MigrationRange`、`DeleteAll`、`DeleteBefore`、`EnsurePartitions`(仅 PG 预建)。
5. **双实现**:CH 委托 `analyticsrepo`;GORM 共用一套,方言 SQL 放 `dialect_*.go`。零值 id 用 `idgen.NextUint64ID()`。
6. **`buildStore`**:CH / GORM 两分支都挂上。
7. **写入**:独立 `batchwriter`;`FlushFunc` → `logstore.Active`。节点日志/可观测走 `SetAccessLogHooks` / `SetObservabilityHooks`,不要让 apps 碰 `ChConn`。
8. **切换任务**:`clearTarget` + `copy*` 增加该表;源数据不删,失败不翻转。
9. **清理**:访问类走 `log_retention_days_*`;性能指标走 `metric_retention_days`。不要擅自共用错误的 TTL。
10. **import-lint**:apps 新增对 `analytics` 或 `infra/persistence`(`batchwriter`/`idgen` 除外)的 import 必须失败。
## 禁止
- apps 直连 `analyticsrepo` / `db.ChConn` / `db.ChDB` 做日志读写
- 只建 CH、不建主库回落
- Handler 内逐条 `PrepareBatch`
- 业务表塞进 logstore
- 管理端改 `log_database` / `log_db_migration`
## 验证
```bash
go test ./internal/repository/logstore ./internal/repository/analytics
go test ./internal/apps/openflare/... ./internal/apps/admin/logs ./internal/apps/admin/status
make swagger
make code-check
```
对照:`of_node_access_logs` 或 `w_user_access_logs` 的 model、三库 goose、`logstore` 双实现、`chwriter`/`risk_control` flush、`LogDBSwitchHandler`。