package logger import ( "database/sql" "fmt" "time" _ "modernc.org/sqlite" ) // auditConfig 审计配置 type auditConfig struct { enabled bool dbPath string retentionDays int bufferSize int } // AuditOption 审计配置选项 type AuditOption func(*auditConfig) // WithDatabasePath 设置数据库路径 func WithDatabasePath(path string) AuditOption { return func(c *auditConfig) { c.dbPath = path } } // WithRetention 设置保留天数 func WithRetention(days int) AuditOption { return func(c *auditConfig) { c.retentionDays = days } } // WithBufferSize 设置缓冲区大小 func WithBufferSize(size int) AuditOption { return func(c *auditConfig) { c.bufferSize = size } } // WithEnabled 设置是否启用审计 func WithEnabled(enabled bool) AuditOption { return func(c *auditConfig) { c.enabled = enabled } } // sqliteAuditLogger SQLite审计日志器实现 type sqliteAuditLogger struct { db *sql.DB config *auditConfig } // NewAuditLogger 创建审计日志器 func NewAuditLogger(opts ...AuditOption) (AuditLogger, error) { config := &auditConfig{ enabled: true, dbPath: "audit.db", retentionDays: 90, bufferSize: 1000, } for _, opt := range opts { opt(config) } if !config.enabled { return &noOpAuditLogger{}, nil } db, err := sql.Open("sqlite", config.dbPath) if err != nil { return nil, fmt.Errorf("failed to open database: %w", err) } if err := initAuditTable(db); err != nil { db.Close() return nil, fmt.Errorf("failed to initialize audit table: %w", err) } return &sqliteAuditLogger{ db: db, config: config, }, nil } // Record 记录审计事件 func (a *sqliteAuditLogger) Record(entry *AuditEntry) error { if entry == nil { return fmt.Errorf("audit entry cannot be nil") } if entry.ID == "" { entry.ID = fmt.Sprintf("%d", time.Now().UnixNano()) } if entry.Timestamp.IsZero() { entry.Timestamp = time.Now() } query := ` INSERT INTO audit_logs (id, timestamp, user_id, username, action, resource, details, ip, user_agent, success, error) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?) ` _, err := a.db.Exec(query, entry.ID, entry.Timestamp, entry.UserID, entry.Username, entry.Action, entry.Resource, entry.Details, entry.IP, entry.UserAgent, entry.Success, entry.Error, ) if err != nil { return fmt.Errorf("failed to record audit entry: %w", err) } return nil } // Query 查询审计日志 func (a *sqliteAuditLogger) Query(filter *AuditFilter) ([]*AuditEntry, error) { if filter == nil { filter = &AuditFilter{} } query := `SELECT id, timestamp, user_id, username, action, resource, details, ip, user_agent, success, error FROM audit_logs WHERE 1=1` args := []interface{}{} if filter.UserID != "" { query += " AND user_id = ?" args = append(args, filter.UserID) } if filter.Action != "" { query += " AND action = ?" args = append(args, filter.Action) } if filter.Resource != "" { query += " AND resource = ?" args = append(args, filter.Resource) } if filter.StartTime != nil { query += " AND timestamp >= ?" args = append(args, *filter.StartTime) } if filter.EndTime != nil { query += " AND timestamp <= ?" args = append(args, *filter.EndTime) } if filter.Success != nil { query += " AND success = ?" args = append(args, *filter.Success) } query += " ORDER BY timestamp DESC" if filter.Limit > 0 { query += " LIMIT ?" args = append(args, filter.Limit) } if filter.Offset > 0 { query += " OFFSET ?" args = append(args, filter.Offset) } rows, err := a.db.Query(query, args...) if err != nil { return nil, fmt.Errorf("failed to query audit logs: %w", err) } defer rows.Close() var entries []*AuditEntry for rows.Next() { entry := &AuditEntry{} err := rows.Scan( &entry.ID, &entry.Timestamp, &entry.UserID, &entry.Username, &entry.Action, &entry.Resource, &entry.Details, &entry.IP, &entry.UserAgent, &entry.Success, &entry.Error, ) if err != nil { return nil, fmt.Errorf("failed to scan audit entry: %w", err) } entries = append(entries, entry) } return entries, nil } // Cleanup 清理过期数据 func (a *sqliteAuditLogger) Cleanup(retention time.Duration) error { cutoff := time.Now().Add(-retention) query := "DELETE FROM audit_logs WHERE timestamp < ?" _, err := a.db.Exec(query, cutoff) if err != nil { return fmt.Errorf("failed to cleanup audit logs: %w", err) } // 优化数据库 _, err = a.db.Exec("VACUUM") if err != nil { return fmt.Errorf("failed to vacuum database: %w", err) } return nil } // Sync 同步数据到磁盘 func (a *sqliteAuditLogger) Sync() error { _, err := a.db.Exec("PRAGMA wal_checkpoint(FULL)") return err } // initAuditTable 初始化审计表 func initAuditTable(db *sql.DB) error { query := ` CREATE TABLE IF NOT EXISTS audit_logs ( id TEXT PRIMARY KEY, timestamp DATETIME NOT NULL, user_id TEXT, username TEXT, action TEXT NOT NULL, resource TEXT, details TEXT, ip TEXT, user_agent TEXT, success BOOLEAN, error TEXT ); CREATE INDEX IF NOT EXISTS idx_audit_timestamp ON audit_logs(timestamp); CREATE INDEX IF NOT EXISTS idx_audit_user ON audit_logs(user_id); CREATE INDEX IF NOT EXISTS idx_audit_action ON audit_logs(action); CREATE INDEX IF NOT EXISTS idx_audit_resource ON audit_logs(resource); ` _, err := db.Exec(query) return err } // noOpAuditLogger 空操作审计日志器(当审计被禁用时使用) type noOpAuditLogger struct{} func (n *noOpAuditLogger) Record(entry *AuditEntry) error { return nil } func (n *noOpAuditLogger) Query(filter *AuditFilter) ([]*AuditEntry, error) { return []*AuditEntry{}, nil } func (n *noOpAuditLogger) Cleanup(retention time.Duration) error { return nil } func (n *noOpAuditLogger) Sync() error { return nil }