From 837820639f8737addde74aa3d36ac30a012fc118 Mon Sep 17 00:00:00 2001 From: wood chen Date: Tue, 3 Dec 2024 18:25:23 +0800 Subject: [PATCH] feat(metrics): implement database initialization and cleanup for metrics tracking - Added initTables function to create necessary tables for metrics history, status statistics, and path statistics in the database. - Implemented indexing on timestamp columns to enhance query performance. - Introduced a cleanupRoutine function to periodically delete old metrics data based on retention policies, improving database management. - Integrated logging for cleanup operations to monitor success and errors during the cleanup process. --- internal/models/metrics.go | 114 +++++++++++++++++++++++++++++++++++++ 1 file changed, 114 insertions(+) diff --git a/internal/models/metrics.go b/internal/models/metrics.go index d399035..b7d06b9 100644 --- a/internal/models/metrics.go +++ b/internal/models/metrics.go @@ -2,6 +2,8 @@ package models import ( "database/sql" + "log" + "proxy-go/internal/constants" "sync/atomic" "time" @@ -50,9 +52,121 @@ func NewMetricsDB(dbPath string) (*MetricsDB, error) { if err != nil { return nil, err } + + // 创建必要的表 + if err := initTables(db); err != nil { + db.Close() + return nil, err + } + return &MetricsDB{DB: db}, nil } +func initTables(db *sql.DB) error { + // 创建指标历史表 + _, err := db.Exec(` + CREATE TABLE IF NOT EXISTS metrics_history ( + id INTEGER PRIMARY KEY AUTOINCREMENT, + timestamp DATETIME DEFAULT CURRENT_TIMESTAMP, + total_requests INTEGER, + total_errors INTEGER, + total_bytes INTEGER, + avg_latency INTEGER, + error_rate REAL + ) + `) + if err != nil { + return err + } + + // 创建状态码统计表 + _, err = db.Exec(` + CREATE TABLE IF NOT EXISTS status_stats ( + id INTEGER PRIMARY KEY AUTOINCREMENT, + timestamp DATETIME DEFAULT CURRENT_TIMESTAMP, + status_group TEXT, + count INTEGER + ) + `) + if err != nil { + return err + } + + // 创建路径统计表 + _, err = db.Exec(` + CREATE TABLE IF NOT EXISTS path_stats ( + id INTEGER PRIMARY KEY AUTOINCREMENT, + timestamp DATETIME DEFAULT CURRENT_TIMESTAMP, + path TEXT, + requests INTEGER, + errors INTEGER, + bytes INTEGER, + avg_latency INTEGER + ) + `) + if err != nil { + return err + } + + // 添加索引以提高查询性能 + _, err = db.Exec(` + CREATE INDEX IF NOT EXISTS idx_metrics_timestamp ON metrics_history(timestamp); + CREATE INDEX IF NOT EXISTS idx_status_timestamp ON status_stats(timestamp); + CREATE INDEX IF NOT EXISTS idx_path_timestamp ON path_stats(timestamp); + `) + if err != nil { + return err + } + + // 启动定期清理任务 + go cleanupRoutine(db) + + return nil +} + +// 定期清理旧数据 +func cleanupRoutine(db *sql.DB) { + ticker := time.NewTicker(constants.CleanupInterval) + for range ticker.C { + // 开始事务 + tx, err := db.Begin() + if err != nil { + log.Printf("Error starting cleanup transaction: %v", err) + continue + } + + // 删除超过保留期限的数据 + cutoff := time.Now().Add(-constants.DataRetention) + _, err = tx.Exec(`DELETE FROM metrics_history WHERE timestamp < ?`, cutoff) + if err != nil { + tx.Rollback() + log.Printf("Error cleaning metrics_history: %v", err) + continue + } + + _, err = tx.Exec(`DELETE FROM status_stats WHERE timestamp < ?`, cutoff) + if err != nil { + tx.Rollback() + log.Printf("Error cleaning status_stats: %v", err) + continue + } + + _, err = tx.Exec(`DELETE FROM path_stats WHERE timestamp < ?`, cutoff) + if err != nil { + tx.Rollback() + log.Printf("Error cleaning path_stats: %v", err) + continue + } + + // 提交事务 + if err := tx.Commit(); err != nil { + log.Printf("Error committing cleanup transaction: %v", err) + } else { + log.Printf("Successfully cleaned up old metrics data") + } + } +} + func (db *MetricsDB) SaveMetrics(stats map[string]interface{}) error { tx, err := db.DB.Begin() if err != nil {