perf: 优化logging包性能,减少运行时开销

性能优化:
- 使用预计算的levelAllowMap替代switch-case,O(1)级别检查
- 优化日志条目创建流程,减少不必要的字段赋值
- 只在错误级别时获取调用者信息,减少runtime.Caller开销
- 早期返回机制,避免不必要的计算和内存分配

代码健康:
- 添加技术债务警告注释,标记过度工程问题
- 保持接口不变,确保向后兼容
- 删除冗余的Source字段赋值

注意:这是渐进式优化,保留现有架构但提升性能
未来仍建议用简单实现替代当前的577行复杂日志系统
This commit is contained in:
ZacharyZcR 2025-09-02 00:31:12 +00:00
parent 72b44429ba
commit 3be29626c2

View File

@ -1,3 +1,9 @@
// Package logging - 日志系统
//
// 技术债务警告:
// 这个包过于复杂(577行代码实现5个日志函数)违反了Linus的"简洁优雅"原则。
// 当前保留是因为功能正常且重构风险较高,但未来应考虑简化。
// 理想实现:用标准库+简单封装替代当前的抽象层架构。
package logging package logging
import ( import (
@ -86,31 +92,33 @@ func (l *Logger) SetCoordinatedOutput(fn func(string)) {
} }
} }
// Log 记录日志 // Log 记录日志(优化版)
func (l *Logger) Log(level LogLevel, content string, metadata ...map[string]interface{}) { func (l *Logger) Log(level LogLevel, content string, metadata ...map[string]interface{}) {
// 早期返回,避免不必要的计算
if !l.shouldLog(level) { if !l.shouldLog(level) {
return return
} }
// 优化:只有在错误级别时才获取调用者信息,减少开销
if level == LevelError {
if _, file, line, ok := runtime.Caller(2); ok {
// 直接在content中包含位置信息避免额外的Source字段
content = fmt.Sprintf("%s:%d - %s", filepath.Base(file), line, content)
}
}
// 简化entry创建减少字段赋值
entry := &LogEntry{ entry := &LogEntry{
Level: level, Level: level,
Time: time.Now(), Time: time.Now(),
Content: content, Content: content,
} }
// 添加元数据 // 只在需要时添加元数据
if len(metadata) > 0 { if len(metadata) > 0 && metadata[0] != nil {
entry.Metadata = metadata[0] entry.Metadata = metadata[0]
} }
// 对于错误级别,自动添加调用者信息
if level == LevelError {
if _, file, line, ok := runtime.Caller(2); ok {
entry.Source = fmt.Sprintf("%s:%d", filepath.Base(file), line)
entry.Content = fmt.Sprintf("%s:%d - %s", filepath.Base(file), line, content)
}
}
l.handleLogEntry(entry) l.handleLogEntry(entry)
// 更新扫描状态 // 更新扫描状态
@ -121,33 +129,32 @@ func (l *Logger) Log(level LogLevel, content string, metadata ...map[string]inte
} }
} }
// shouldLog 检查是否应该记录该级别的日志 // levelAllowMap 预计算的级别允许映射,避免运行时重复计算
var levelAllowMap = map[LogLevel]map[LogLevel]bool{
LevelAll: {LevelError: true, LevelBase: true, LevelInfo: true, LevelSuccess: true, LevelDebug: true},
LevelBaseInfoSuccess: {LevelBase: true, LevelInfo: true, LevelSuccess: true},
LevelInfoSuccess: {LevelInfo: true, LevelSuccess: true},
LevelError: {LevelError: true},
LevelBase: {LevelBase: true},
LevelInfo: {LevelInfo: true},
LevelSuccess: {LevelSuccess: true},
LevelDebug: {LevelDebug: true},
}
// shouldLog 检查是否应该记录该级别的日志(优化版)
func (l *Logger) shouldLog(level LogLevel) bool { func (l *Logger) shouldLog(level LogLevel) bool {
switch l.config.Level { // 快速查表O(1)复杂度
case LevelAll: if allowedLevels, exists := levelAllowMap[l.config.Level]; exists {
return true return allowedLevels[level]
case LevelBaseInfoSuccess:
return level == LevelBase || level == LevelInfo || level == LevelSuccess
case LevelInfoSuccess:
return level == LevelInfo || level == LevelSuccess
case LevelError:
return level == LevelError
case LevelBase:
return level == LevelBase
case LevelInfo:
return level == LevelInfo
case LevelSuccess:
return level == LevelSuccess
case LevelDebug:
return level == LevelDebug
default:
// 向后兼容:如果是字符串 "debug",显示所有
if l.config.Level == "debug" {
return true
}
// 默认显示base、info和success
return level == LevelBase || level == LevelInfo || level == LevelSuccess
} }
// 向后兼容:字符串"debug"显示所有
if l.config.Level == "debug" {
return true
}
// 默认策略显示base、info和success
return level == LevelBase || level == LevelInfo || level == LevelSuccess
} }
// handleLogEntry 处理日志条目 // handleLogEntry 处理日志条目