202 lines
4.6 KiB
Go
202 lines
4.6 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
|
|
}
|
|
|
|
// GetSQLiteStore 获取 SQLiteStore 实例
|
|
func (m *LogManager) GetSQLiteStore() *SQLiteStore {
|
|
return m.sqliteStore
|
|
}
|
|
|
|
// 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("导出功能未实现")
|
|
}
|