跳转到内容

日志存储解耦

你会学到:哪些表属于日志用途、为什么不能绑死 ClickHouse,以及新增一张日志表时必须走哪条代码路径。

观测字段与上报协议仍以 观测上报协议与表结构 为准;本文只约定存到哪、怎么切库


1. 目标

  • ClickHouse 可选:不启用时,PostgreSQL(或关闭主库时的 SQLite)完整承接写入、查询、聚合与清理。
  • 上层不碰底层库:apps 只面向 internal/repository/logstore(或 repository 门面)。repository/analyticsdb.ChConn / db.ChDB 仅供 logstore 的 ClickHouse 实现使用。
  • 可切换:任务管理里的「切换日志数据库」在 PostgreSQL/SQLite 与 ClickHouse 之间复制数据并翻转主库;迁移期间冻结写入,成功才切换,源数据不删。

2. 什么算日志表

同时满足才进 logstore:

  • 追加写入,几乎不更新单行
  • 按时间查询或聚合,允许按保留天数删除
  • 关闭 ClickHouse 后仍要能写、能查
  • 不参与网站 / 节点 / 证书等事务一致性

不要做成日志表:Zone、节点、配置版本、任务执行、上传元数据。这些走业务主库 repository

当前日志域:

接口
节点访问日志AccessLogStoreof_node_access_logs
可观测时序ObservabilityStoreof_node_metric_snapshots / of_node_edge_health / of_node_obs_frps / of_node_obs_frpc
用户访问审计UserAccessLogStorew_user_access_logs

ClickHouse 上的小时级物化视图(如 of_access_log_hourly)只服务 CH 查询加速。PostgreSQL / SQLite 不建同构聚合表,查询时从原始日志实时聚合。


3. 分层

层级路径职责
抽象internal/repository/logstore接口 + Active / BuildForMigration;按 log_database 选实现
CH 实现logstore/clickhouse_store.go委托 repository/analytics(原生批量 + 现有聚合 SQL)
主库实现logstore/postgres_store.goPostgreSQL(高频表按月分区)与 SQLite(普通表)共用 GORM
Modelinternal/model/analytics实体与批量 SQL,无 IO
入队chwriter / risk_control + batchwriterFlushFunclogstore.Active;节点日志 / 可观测经 hooks 入队
约束logstore/imports_test.goapps 禁止 import repository/analytics

log_database 只有两种合法状态:随业务主库postgressqlite)或 clickhouse。不存在「主库 PostgreSQL + 日志 SQLite」。log_database / log_db_migration 受保护,管理端不可改。

启动时:log_database=clickhouse 但 ClickHouse 未启用会拒绝启动,须先重新启用 ClickHouse 并切回主库后再关掉。


4. 切换协议

任务类型 of_log_db_switch(管理端名称「切换日志数据库」),参数 target

  1. 校验目标合法且不等于当前库。
  2. log_db_migration=migrating,排空在途 batchwriter(Drain,不要 Stop writer)。此后写入返回明确错误(HTTP 503),不排队积压。
  3. 清空目标日志表后按 id 分页复制;复制前对 PostgreSQL 目标 EnsurePartitions
  4. 全部成功才写 log_database=target 并清除迁移标记;失败清除标记,写入继续走源库。
  5. 源数据不删;重试前重新清空目标以保证幂等。

不要另起切换协议,也不要在任务里直连 analyticsrepo


5. 新增一张日志表

列名必须在 ClickHouse / PostgreSQL / SQLite 三套 goose 迁移中一致。要点:

  • 高频表:CH 用 MergeTree + toYYYYMM;PG 用 PARTITION BY RANGE(时间列),主键含分区键;SQLite 普通表 + 索引。
  • ID 用 snowflake uint64,迁移时原样保留。
  • 写入走独立 batchwriter;flush 调 logstore.Active,不要 analyticsrepo.BatchInsert
  • 切换任务的 copy* 必须覆盖新表;清理走已有 log_retention_days_*metric_retention_days,不要用错 TTL。

运行时配置见 配置项参考 · 日志存储


6. 相关文档

基于 Apache License 2.0 发布