Collector 的可插拔 Storage Backend 分成兩個功能層級。分界線是查詢模式 — SQLite 能高效處理的查詢定義了簡單版的功能邊界,超出的查詢需求觸發 PostgreSQL 的引入。所有事件都經過同一個 Ingestion domain,差異在 Query 和 Dashboard domain 能提供什麼能力。

SQLite 層:開發者工具

SQLite 層提供的功能聚焦在「開發者自己 debug 和監控」。所有查詢都是單一維度的 — 按時間、按類型、按名稱過濾,不需要跨事件 JOIN 或跨使用者聚合。

承載的功能

功能查詢模式SQL 範例
最近 error 列表按 type + 時間過濾WHERE type='error' ORDER BY ts DESC LIMIT 20
Error 計數(按 name 分群)單表 GROUP BYSELECT name, COUNT(*) FROM events WHERE type='error' GROUP BY name
單次 session 回放按 session_id 過濾WHERE session_id='xxx' ORDER BY ts
事件時間軸按時間排序WHERE ts BETWEEN ? AND ? ORDER BY ts
基本 rule engine逐筆事件評估收到事件時逐條比對 rule(不需要查歷史)
CLI 查詢任意過濾WHERE type=? AND name LIKE ? AND ts > ?

這些功能覆蓋開發者日常 debug 和監控的核心操作 — 查錯誤、看時間軸、回放 session、設規則告警。

對應的 Dashboard 視圖

視圖顯示
總覽頁最近 1 小時的事件計數(按 type 分)+ 最近 error 列表
事件詳情單筆事件的完整 JSON
Session 回放單次 session 內的事件序列

對應的事件消費

SQLite 層消費所有四類事件,但消費方式是「單筆或單 session 級查詢」:

事件類型消費方式保留需求
event按名稱計數、按 session 排列原始 7 天(debug)
error按名稱分群、按時間排列、看 stack trace原始 30 天(error 追蹤價值較長)
metric按名稱查最近 N 筆的值原始 7 天 + 每小時聚合 90 天
lifecycle按 session 排列、看狀態轉換原始 7 天

PostgreSQL 層:行為分析

PostgreSQL 層在 SQLite 層的基礎上加入「跨 session、跨使用者的聚合分析」。這些查詢需要 JOIN 多張表、計算時間窗口、處理大量資料的 GROUP BY — SQLite 的單寫者模型和有限的查詢最佳化器在這些場景下效能不足。

觸發引入 PostgreSQL 的功能需求

功能需求為什麼 SQLite 不夠PostgreSQL 提供什麼
Funnel 分析跨大量 session 的 multi-step JOIN 和聚合效能不足Window functions + 高效 JOIN
Cohort 留存需要按「註冊週」分群、計算每週的回訪率Date functions + 大規模 GROUP BY
RFM 分群需要跨所有使用者計算 recency/frequency/monetary全表聚合 + 分位數計算
時間趨勢 dashboard需要「過去 30 天每小時的 error P95」時間分桶 + percentile 函數
高併發寫入多個 SDK 同時 flush 且持續出現 database is locked連線池 + 並行寫入
長期保留 + 聚合降採樣的 materialized viewREFRESH MATERIALIZED VIEW

判斷公式

1需要 funnel / cohort / RFM 任一 → PostgreSQL
2需要跨使用者聚合(不只看自己的資料) → PostgreSQL
3需要高併發寫入(多個 SDK 同時 flush 且持續出現 database is locked 錯誤) → PostgreSQL
4以上都不需要 → SQLite 足夠

對應的 Dashboard 視圖(SQLite 層不提供)

視圖查詢模式
Funnel 漏斗多步驟轉換率(session 級 JOIN)
Cohort 留存表時間窗口 × 群組矩陣
RFM 分群散佈三維度分位數計算
Error 趨勢圖(長期)30 天 × 每小時的時間序列
效能 P95 趨勢percentile_cont 視窗函數

對應的事件消費

PostgreSQL 層消費的事件和 SQLite 相同(Ingestion 不變),但消費方式從「單筆/單 session」擴展到「跨 session/跨使用者」:

事件類型SQLite 層消費PostgreSQL 層新增消費
event按名稱計數funnel 步驟轉換、cohort 行為分群
error按名稱分群跨版本 error 率比較、P95 回應時間趨勢
metric最近 N 筆值長期趨勢(materialized view 預聚合)
lifecycle單 session 排列session 長度分佈、留存率計算

Domain 的分層影響

DomainSQLite 層PostgreSQL 層新增
IngestionHTTP POST → 驗證 → 寫入不變(寫入目標換 backend)
StorageSQLite embeddedPostgreSQL + 連線池
Query單表過濾 + 單表 GROUP BYJOIN + window function + percentile
Rule逐筆事件即時評估不變(rule 不依賴聚合查詢)
Dashboard總覽 + 事件詳情 + session 回放新增 funnel / cohort / RFM / 趨勢圖

Ingestion 和 Rule 兩個 domain 和 storage backend 無關 — 事件進來的方式和規則評估的邏輯不因 backend 改變。Query 和 Dashboard 是分層影響最大的兩個 domain — PostgreSQL 層的查詢能力決定了 Dashboard 能提供什麼視圖。

實作邊界

Storage interface 用 Go 的 interface composition 分成兩層:

 1type BasicStorage interface {
 2    Store(event Event) error
 3    Query(filter QueryFilter) ([]Event, error)
 4    Close() error
 5    Downsample() error
 6    Purge() error
 7}
 8
 9type AnalyticsStorage interface {
10    BasicStorage
11    Aggregate(spec AggregateSpec) (AggregateResult, error)
12    Funnel(steps []string, timeWindow Duration) (FunnelResult, error)
13    Cohort(groupBy string, metric string) (CohortResult, error)
14}

SQLite implementation 只實作 BasicStorage。PostgreSQL implementation 實作 AnalyticsStorage。Dashboard 用 Go 的 type assertion(if as, ok := storage.(AnalyticsStorage); ok { ... })判斷能力 — funnel/cohort 視圖在 SQLite 模式下不顯示入口,而非顯示後報錯。

下一步路由