Files
dns-server/log/log_manager.go
T
Alex Yang efebce3c39 whois
2026-04-01 12:22:55 +08:00

197 lines
4.5 KiB
Go

package log
import (
"fmt"
"sync"
"time"
)
// LogManager 日志管理器
type LogManager struct {
ringBuffer *RingBuffer
sqliteStore *SQLiteStore
mu sync.RWMutex
closed bool
}
// LogManagerConfig 日志管理器配置
type LogManagerConfig struct {
RingBufferSize int // 环形缓冲区大小
DatabasePath string // SQLite 数据库路径
EnableSQLite bool // 是否启用 SQLite 存储
}
// DefaultConfig 默认配置
func DefaultConfig() LogManagerConfig {
return LogManagerConfig{
RingBufferSize: 10000,
DatabasePath: "data/query_logs.db",
EnableSQLite: true,
}
}
// NewLogManager 创建日志管理器
func NewLogManager(config LogManagerConfig) (*LogManager, error) {
manager := &LogManager{
ringBuffer: NewRingBuffer(config.RingBufferSize),
}
if config.EnableSQLite {
sqliteStore, err := NewSQLiteStore(config.DatabasePath)
if err != nil {
return nil, fmt.Errorf("创建 SQLite 存储失败:%w", err)
}
manager.sqliteStore = sqliteStore
}
return manager, nil
}
// Log 记录日志(同步写入多个存储)
func (m *LogManager) Log(log QueryLog) error {
m.mu.RLock()
defer m.mu.RUnlock()
if m.closed {
return fmt.Errorf("日志管理器已关闭")
}
// 写入环形缓冲区(总是成功)
m.ringBuffer.Push(log)
// 写入 SQLite(如果启用)
if m.sqliteStore != nil {
err := m.sqliteStore.Log(log)
if err != nil {
// SQLite 写入失败不影响环形缓冲区
fmt.Printf("SQLite 写入失败:%v\n", err)
}
}
return nil
}
// QueryLogs 查询日志(优先从 SQLite 查询,失败则从环形缓冲区查询)
func (m *LogManager) QueryLogs(filter LogFilter, page PageParams) ([]QueryLog, int64, error) {
m.mu.RLock()
defer m.mu.RUnlock()
// 如果启用了 SQLite,优先从 SQLite 查询
if m.sqliteStore != nil {
logs, total, err := m.sqliteStore.QueryLogs(filter, page)
if err == nil {
return logs, total, nil
}
// SQLite 查询失败,降级到环形缓冲区
fmt.Printf("SQLite 查询失败,降级到环形缓冲区:%v\n", err)
}
// 从环形缓冲区查询
return m.ringBuffer.Query(filter, page)
}
// GetStats 获取统计信息(合并多个存储的统计)
func (m *LogManager) GetStats(timeRange TimeRange) (*LogStats, error) {
m.mu.RLock()
defer m.mu.RUnlock()
// 如果启用了 SQLite,使用 SQLite 的统计
if m.sqliteStore != nil {
return m.sqliteStore.GetStats(timeRange)
}
// 否则使用环形缓冲区的统计
return m.ringBuffer.GetStats(timeRange)
}
// Close 关闭日志管理器
func (m *LogManager) Close() error {
m.mu.Lock()
defer m.mu.Unlock()
if m.closed {
return nil
}
m.closed = true
var err error
if m.sqliteStore != nil {
err = m.sqliteStore.Close()
}
return err
}
// GetRingBufferCount 获取环形缓冲区中的日志数量
func (m *LogManager) GetRingBufferCount() int {
return m.ringBuffer.Count()
}
// IsSQLiteEnabled 检查是否启用了 SQLite
func (m *LogManager) IsSQLiteEnabled() bool {
return m.sqliteStore != nil
}
// MigrateFromJSON 从 JSON 文件迁移历史数据
func (m *LogManager) MigrateFromJSON(jsonPath string) error {
if m.sqliteStore == nil {
return fmt.Errorf("SQLite 未启用,无法迁移数据")
}
return m.sqliteStore.MigrateFromJSON(jsonPath)
}
// CleanupOldLogs 清理旧日志
func (m *LogManager) CleanupOldLogs(olderThan time.Time) (int64, error) {
if m.sqliteStore == nil {
return 0, fmt.Errorf("SQLite 未启用,无法清理日志")
}
// 开启事务
tx, err := m.sqliteStore.db.Begin()
if err != nil {
return 0, fmt.Errorf("开启事务失败:%w", err)
}
// 删除旧日志
result, err := tx.Exec("DELETE FROM query_logs WHERE timestamp < ?", olderThan)
if err != nil {
tx.Rollback()
return 0, fmt.Errorf("删除旧日志失败:%w", err)
}
// 获取删除的行数
deleted, err := result.RowsAffected()
if err != nil {
tx.Rollback()
return 0, fmt.Errorf("获取删除行数失败:%w", err)
}
// 提交事务
err = tx.Commit()
if err != nil {
return 0, fmt.Errorf("提交事务失败:%w", err)
}
return deleted, nil
}
// ExportLogs 导出日志到 JSON
func (m *LogManager) ExportLogs(filter LogFilter, outputPath string) error {
// 查询所有符合条件的日志
page := PageParams{
Limit: 100000, // 大量导出
Offset: 0,
}
_, _, err := m.QueryLogs(filter, page)
if err != nil {
return fmt.Errorf("查询日志失败:%w", err)
}
// TODO: 写入到 JSON 文件
// 由于导入限制,暂时返回错误
return fmt.Errorf("导出功能未实现")
}