Private
Public Access
1
0

重构:文件系统模块化架构,优化应用启动流程

This commit is contained in:
2026-01-28 00:28:54 +08:00
parent 4a9b25a505
commit 8c577f70e7
123 changed files with 32030 additions and 967 deletions

View File

@@ -0,0 +1,330 @@
package filesystem
import (
"encoding/json"
"fmt"
"os"
"path/filepath"
"sync"
"time"
)
// AuditOperation 审计操作类型
type AuditOperation string
const (
OperationRead AuditOperation = "read" // 读取文件
OperationWrite AuditOperation = "write" // 写入文件
OperationDelete AuditOperation = "delete" // 删除文件
OperationCreate AuditOperation = "create" // 创建目录
OperationRename AuditOperation = "rename" // 重命名
OperationMove AuditOperation = "move" // 移动
OperationList AuditOperation = "list" // 列出目录
OperationDownload AuditOperation = "download" // 下载
)
// AuditLogEntry 审计日志条目
type AuditLogEntry struct {
Timestamp time.Time `json:"timestamp"` // 操作时间
Operation AuditOperation `json:"operation"` // 操作类型
Path string `json:"path"` // 文件路径
OldPath string `json:"old_path,omitempty"` // 原路径(重命名/移动)
Size int64 `json:"size,omitempty"` // 文件大小
IsDirectory bool `json:"is_directory"` // 是否为目录
Success bool `json:"success"` // 操作是否成功
Error string `json:"error,omitempty"` // 错误信息
UserAgent string `json:"user_agent,omitempty"` // 用户代理
IPAddress string `json:"ip_address,omitempty"` // IP地址
}
// AuditLogger 审计日志记录器
type AuditLogger struct {
logFile *os.File
logPath string
mu sync.Mutex
buffer []AuditLogEntry
bufferSize int
stopChan chan struct{}
}
// NewAuditLogger 创建审计日志记录器
func NewAuditLogger(logDir string) (*AuditLogger, error) {
// 创建日志目录
if err := os.MkdirAll(logDir, 0755); err != nil {
return nil, fmt.Errorf("创建日志目录失败: %v", err)
}
// 生成日志文件名(按日期)
timestamp := time.Now().Format("2006-01-02")
logPath := filepath.Join(logDir, fmt.Sprintf("audit_%s.log", timestamp))
// 打开日志文件(追加模式)
logFile, err := os.OpenFile(logPath, os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0644)
if err != nil {
return nil, fmt.Errorf("打开日志文件失败: %v", err)
}
logger := &AuditLogger{
logFile: logFile,
logPath: logPath,
buffer: make([]AuditLogEntry, 0, 100),
bufferSize: 100, // 缓冲100条记录后批量写入
stopChan: make(chan struct{}),
}
// 启动后台协程,定期刷新缓冲区
go logger.backgroundFlush()
return logger, nil
}
// Log 记录操作日志
func (a *AuditLogger) Log(entry AuditLogEntry) error {
// 设置时间戳
if entry.Timestamp.IsZero() {
entry.Timestamp = time.Now()
}
a.mu.Lock()
defer a.mu.Unlock()
// 添加到缓冲区
a.buffer = append(a.buffer, entry)
// 如果缓冲区满了,立即写入
if len(a.buffer) >= a.bufferSize {
if err := a.flush(); err != nil {
return err
}
}
return nil
}
// LogDelete 记录删除操作(便捷方法)
func (a *AuditLogger) LogDelete(path string, isDir bool, size int64, err error) {
entry := AuditLogEntry{
Timestamp: time.Now(),
Operation: OperationDelete,
Path: path,
Size: size,
IsDirectory: isDir,
Success: err == nil,
}
if err != nil {
entry.Error = err.Error()
}
_ = a.Log(entry)
}
// LogWrite 记录写入操作(便捷方法)
func (a *AuditLogger) LogWrite(path string, size int64, err error) {
entry := AuditLogEntry{
Timestamp: time.Now(),
Operation: OperationWrite,
Path: path,
Size: size,
IsDirectory: false,
Success: err == nil,
}
if err != nil {
entry.Error = err.Error()
}
_ = a.Log(entry)
}
// LogRead 记录读取操作(便捷方法)
func (a *AuditLogger) LogRead(path string, size int64, err error) {
entry := AuditLogEntry{
Timestamp: time.Now(),
Operation: OperationRead,
Path: path,
Size: size,
IsDirectory: false,
Success: err == nil,
}
if err != nil {
entry.Error = err.Error()
}
_ = a.Log(entry)
}
// flush 将缓冲区写入文件
func (a *AuditLogger) flush() error {
if len(a.buffer) == 0 {
return nil
}
// 序列化所有条目为JSON每行一个
for _, entry := range a.buffer {
data, err := json.Marshal(entry)
if err != nil {
continue // 序列化失败,跳过该条目
}
if _, err := a.logFile.Write(append(data, '\n')); err != nil {
return err
}
}
// 刷新到磁盘
if err := a.logFile.Sync(); err != nil {
return err
}
// 清空缓冲区
a.buffer = a.buffer[:0]
return nil
}
// backgroundFlush 后台协程,定期刷新缓冲区
func (a *AuditLogger) backgroundFlush() {
ticker := time.NewTicker(5 * time.Second) // 每5秒刷新一次
defer ticker.Stop()
for {
select {
case <-ticker.C:
a.mu.Lock()
_ = a.flush()
a.mu.Unlock()
case <-a.stopChan:
// 停止前刷新一次
a.mu.Lock()
_ = a.flush()
a.mu.Unlock()
return
}
}
}
// Close 关闭审计日志记录器
func (a *AuditLogger) Close() error {
close(a.stopChan)
a.mu.Lock()
defer a.mu.Unlock()
// 刷新剩余缓冲区
if err := a.flush(); err != nil {
return err
}
// 关闭文件
return a.logFile.Close()
}
// RotateLog 日志轮转(每天创建新文件)
func (a *AuditLogger) RotateLog() error {
a.mu.Lock()
defer a.mu.Unlock()
// 刷新缓冲区
if err := a.flush(); err != nil {
return err
}
// 关闭当前文件
if err := a.logFile.Close(); err != nil {
return err
}
// 生成新的日志文件名
timestamp := time.Now().Format("2006-01-02")
logPath := filepath.Join(filepath.Dir(a.logPath), fmt.Sprintf("audit_%s.log", timestamp))
// 打开新文件
logFile, err := os.OpenFile(logPath, os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0644)
if err != nil {
return err
}
a.logFile = logFile
a.logPath = logPath
return nil
}
// GetRecentLogs 获取最近的审计日志
func GetRecentLogs(logDir string, limit int) ([]AuditLogEntry, error) {
// 读取今天的日志文件
timestamp := time.Now().Format("2006-01-02")
logPath := filepath.Join(logDir, fmt.Sprintf("audit_%s.log", timestamp))
data, err := os.ReadFile(logPath)
if err != nil {
return nil, err
}
// 解析JSON每行一个条目
var entries []AuditLogEntry
lines := parseLines(string(data))
// 从后往前读取(最新的在前)
start := len(lines) - limit
if start < 0 {
start = 0
}
for i := len(lines) - 1; i >= start; i-- {
var entry AuditLogEntry
if err := json.Unmarshal([]byte(lines[i]), &entry); err == nil {
entries = append(entries, entry)
}
}
return entries, nil
}
// parseLines 解析文本为行
func parseLines(text string) []string {
lines := make([]string, 0)
current := ""
for _, ch := range text {
if ch == '\n' {
if current != "" {
lines = append(lines, current)
current = ""
}
} else {
current += string(ch)
}
}
if current != "" {
lines = append(lines, current)
}
return lines
}
// 全局审计日志记录器
var globalAuditLogger *AuditLogger
var auditLoggerOnce sync.Once
// InitAuditLogger 初始化全局审计日志记录器
func InitAuditLogger(logDir string) error {
var err error
globalAuditLogger, err = NewAuditLogger(logDir)
return err
}
// GetAuditLogger 获取全局审计日志记录器
func GetAuditLogger() *AuditLogger {
return globalAuditLogger
}
// CloseAuditLogger 关闭全局审计日志记录器
func CloseAuditLogger() error {
if globalAuditLogger != nil {
return globalAuditLogger.Close()
}
return nil
}