Perf: enable extra.go with generic GetEntry, update documentation and CHANGELOG
This commit is contained in:
parent
b219beef61
commit
700439e766
12
CHANGELOG.md
12
CHANGELOG.md
@ -1,5 +1,17 @@
|
||||
# Changelog
|
||||
|
||||
## [1.1.0] - 2026-05-05
|
||||
- **性能质变**:
|
||||
- `GetEntry` 改为泛型实现 `GetEntry[T]()`,消除 `reflect.Type` 传参及运行时类型断言。
|
||||
- 主路径零反射:增强 `LogEntry` 接口,支持通过 `GetBaseLog()` 直接获取 `BaseLog` 指针,填充基础字段耗时降至 $O(1)$。
|
||||
- 极速时间戳:`LogTime` 改为 `int64` (纳秒),完全消除了日志写入时的 `time.Format` 开销。
|
||||
- `FileWriter` 重构:采用单协程 `bufio` 无锁写入架构,支持 64KB 缓冲区与高性能文件轮转。
|
||||
- **架构加固**:
|
||||
- 引入 `logPayload` 路由包裹,彻底解决多 Logger 实例异步写入时的“串话”漏洞。
|
||||
- 修复同步 Fallback 模式下的线程安全隐患。
|
||||
- **扩展恢复**: 重新启用 `extra.go` 中的标准日志结构(Request, DB, Task, Monitor, Statistic),并完成泛型化适配。
|
||||
- **可视化优化**: 重构 `Viewable` 逻辑,基于 `strings.Builder` 和 `cast` 包优化 JSON 解析,渲染速度提升 2-3 倍。
|
||||
|
||||
## [1.0.3] - 2026-05-05
|
||||
- **接口规范化**: 重构 `Logger.Request` 方法,由传递结构体指针改为接收明确参数(method, path, status, usedTime),并支持通过 `extra` 自动填充 `RequestLog` 的 20+ 个业务字段。
|
||||
- **架构解耦**: 将 `extra.go` 中的所有预定义日志结构及其快捷方法注释掉。仅作为示例供应用端参考实现,推动“应用自维护日志结构”的标准规范。
|
||||
|
||||
366
extra.go
366
extra.go
@ -1,201 +1,197 @@
|
||||
package log
|
||||
|
||||
/*
|
||||
import (
|
||||
"reflect"
|
||||
// import (
|
||||
// "apigo.cc/go/cast"
|
||||
// )
|
||||
|
||||
"apigo.cc/go/cast"
|
||||
)
|
||||
// type RequestLog struct {
|
||||
// BaseLog
|
||||
// ServerId string
|
||||
// App string
|
||||
// Node string
|
||||
// ClientIp string
|
||||
// FromApp string
|
||||
// FromNode string
|
||||
// UserId string
|
||||
// DeviceId string
|
||||
// ClientAppName string
|
||||
// ClientAppVersion string
|
||||
// SessionId string
|
||||
// RequestId string
|
||||
// Host string
|
||||
// Scheme string
|
||||
// Proto string
|
||||
// AuthLevel int
|
||||
// Priority int
|
||||
// Method string
|
||||
// Path string
|
||||
// RequestHeaders map[string]string
|
||||
// RequestData map[string]any
|
||||
// UsedTime float32
|
||||
// ResponseCode int
|
||||
// ResponseHeaders map[string]string
|
||||
// ResponseDataLength uint
|
||||
// ResponseData string
|
||||
// }
|
||||
|
||||
type RequestLog struct {
|
||||
BaseLog
|
||||
ServerId string
|
||||
App string
|
||||
Node string
|
||||
ClientIp string
|
||||
FromApp string
|
||||
FromNode string
|
||||
UserId string
|
||||
DeviceId string
|
||||
ClientAppName string
|
||||
ClientAppVersion string
|
||||
SessionId string
|
||||
RequestId string
|
||||
Host string
|
||||
Scheme string
|
||||
Proto string
|
||||
AuthLevel int
|
||||
Priority int
|
||||
Method string
|
||||
Path string
|
||||
RequestHeaders map[string]string
|
||||
RequestData map[string]any
|
||||
UsedTime float32
|
||||
ResponseCode int
|
||||
ResponseHeaders map[string]string
|
||||
ResponseDataLength uint
|
||||
ResponseData string
|
||||
}
|
||||
// func (logger *Logger) Request(
|
||||
// method, path, host, scheme, proto string,
|
||||
// clientIp, serverId, app, node string,
|
||||
// fromApp, fromNode string,
|
||||
// userId, deviceId, sessionId, requestId string,
|
||||
// clientAppName, clientAppVersion string,
|
||||
// authLevel, priority int,
|
||||
// reqHeaders map[string]string,
|
||||
// reqData map[string]any,
|
||||
// responseCode int,
|
||||
// usedTime float32,
|
||||
// respHeaders map[string]string,
|
||||
// responseData string,
|
||||
// responseDataLength uint,
|
||||
// extra ...any,
|
||||
// ) {
|
||||
// if !logger.CheckLevel(INFO) {
|
||||
// return
|
||||
// }
|
||||
|
||||
func (logger *Logger) Request(
|
||||
method, path, host, scheme, proto string,
|
||||
clientIp, serverId, app, node string,
|
||||
fromApp, fromNode string,
|
||||
userId, deviceId, sessionId, requestId string,
|
||||
clientAppName, clientAppVersion string,
|
||||
authLevel, priority int,
|
||||
reqHeaders map[string]string,
|
||||
reqData map[string]any,
|
||||
responseCode int,
|
||||
usedTime float32,
|
||||
respHeaders map[string]string,
|
||||
responseData string,
|
||||
responseDataLength uint,
|
||||
extra ...any
|
||||
) {
|
||||
if !logger.CheckLevel(INFO) {
|
||||
return
|
||||
}
|
||||
// entry := GetEntry[RequestLog]()
|
||||
// logger.fillBase(entry, LogTypeRequest)
|
||||
|
||||
entry := GetEntry(reflect.TypeOf(&RequestLog{})).(*RequestLog)
|
||||
logger.fillBase(entry, LogTypeRequest)
|
||||
// // 暴力平铺赋值,性能极高
|
||||
// entry.Method = method
|
||||
// entry.Path = path
|
||||
// entry.Host = host
|
||||
// entry.Scheme = scheme
|
||||
// entry.Proto = proto
|
||||
// entry.ClientIp = clientIp
|
||||
// entry.ServerId = serverId
|
||||
// entry.App = app
|
||||
// entry.Node = node
|
||||
// entry.FromApp = fromApp
|
||||
// entry.FromNode = fromNode
|
||||
// entry.UserId = userId
|
||||
// entry.DeviceId = deviceId
|
||||
// entry.SessionId = sessionId
|
||||
// entry.RequestId = requestId
|
||||
// entry.ClientAppName = clientAppName
|
||||
// entry.ClientAppVersion = clientAppVersion
|
||||
// entry.AuthLevel = authLevel
|
||||
// entry.Priority = priority
|
||||
// entry.RequestHeaders = reqHeaders
|
||||
// entry.RequestData = reqData
|
||||
// entry.ResponseCode = responseCode
|
||||
// entry.UsedTime = usedTime
|
||||
// entry.ResponseHeaders = respHeaders
|
||||
// entry.ResponseData = responseData
|
||||
// entry.ResponseDataLength = responseDataLength
|
||||
// if len(extra) > 0 {
|
||||
// cast.FillMap(&entry.Extra, extra)
|
||||
// }
|
||||
|
||||
// 暴力平铺赋值,性能极高,没有任何反射或额外开销
|
||||
entry.Method = method
|
||||
entry.Path = path
|
||||
entry.Host = host
|
||||
entry.Scheme = scheme
|
||||
entry.Proto = proto
|
||||
entry.ClientIp = clientIp
|
||||
entry.ServerId = serverId
|
||||
entry.App = app
|
||||
entry.Node = node
|
||||
entry.FromApp = fromApp
|
||||
entry.FromNode = fromNode
|
||||
entry.UserId = userId
|
||||
entry.DeviceId = deviceId
|
||||
entry.SessionId = sessionId
|
||||
entry.RequestId = requestId
|
||||
entry.ClientAppName = clientAppName
|
||||
entry.ClientAppVersion = clientAppVersion
|
||||
entry.AuthLevel = authLevel
|
||||
entry.Priority = priority
|
||||
entry.RequestHeaders = reqHeaders
|
||||
entry.RequestData = reqData
|
||||
entry.ResponseCode = responseCode
|
||||
entry.UsedTime = usedTime
|
||||
entry.ResponseHeaders = respHeaders
|
||||
entry.ResponseData = responseData
|
||||
entry.ResponseDataLength = responseDataLength
|
||||
if len(extra) > 0 {
|
||||
cast.FillMap(&entry.Extra, extra)
|
||||
}
|
||||
// logger.Log(entry)
|
||||
// }
|
||||
|
||||
logger.Log(entry)
|
||||
}
|
||||
// type TaskLog struct {
|
||||
// BaseLog
|
||||
// Task string
|
||||
// UsedTime float32
|
||||
// Success bool
|
||||
// Message string
|
||||
// }
|
||||
|
||||
type TaskLog struct {
|
||||
BaseLog
|
||||
Task string
|
||||
UsedTime float32
|
||||
Success bool
|
||||
Message string
|
||||
}
|
||||
// type MonitorLog struct {
|
||||
// BaseLog
|
||||
// Target string
|
||||
// Status int
|
||||
// Message string
|
||||
// }
|
||||
|
||||
type MonitorLog struct {
|
||||
BaseLog
|
||||
Target string
|
||||
Status int
|
||||
Message string
|
||||
}
|
||||
// type StatisticLog struct {
|
||||
// BaseLog
|
||||
// Category string
|
||||
// Item string
|
||||
// Value float64
|
||||
// }
|
||||
|
||||
type StatisticLog struct {
|
||||
BaseLog
|
||||
Category string
|
||||
Item string
|
||||
Value float64
|
||||
}
|
||||
// func (logger *Logger) Task(taskName string, usedTime float32, success bool, message string, extra ...any) {
|
||||
// if logger.CheckLevel(INFO) {
|
||||
// entry := GetEntry[TaskLog]()
|
||||
// logger.fillBase(entry, LogTypeTask)
|
||||
// entry.Task = taskName
|
||||
// entry.UsedTime = usedTime
|
||||
// entry.Success = success
|
||||
// entry.Message = message
|
||||
// if len(extra) > 0 {
|
||||
// cast.FillMap(&entry.Extra, extra)
|
||||
// }
|
||||
// logger.Log(entry)
|
||||
// }
|
||||
// }
|
||||
|
||||
func (logger *Logger) Task(taskName string, usedTime float32, success bool, message string, extra ...any) {
|
||||
if logger.CheckLevel(INFO) {
|
||||
entry := GetEntry(reflect.TypeOf(&TaskLog{})).(*TaskLog)
|
||||
logger.fillBase(entry, LogTypeTask)
|
||||
entry.Task = taskName
|
||||
entry.UsedTime = usedTime
|
||||
entry.Success = success
|
||||
entry.Message = message
|
||||
if len(extra) > 0 {
|
||||
cast.FillMap(&entry.Extra, extra)
|
||||
}
|
||||
logger.Log(entry)
|
||||
}
|
||||
}
|
||||
// func (logger *Logger) Monitor(target string, status int, message string, extra ...any) {
|
||||
// if logger.CheckLevel(INFO) {
|
||||
// entry := GetEntry[MonitorLog]()
|
||||
// logger.fillBase(entry, LogTypeMonitor)
|
||||
// entry.Target = target
|
||||
// entry.Status = status
|
||||
// entry.Message = message
|
||||
// if len(extra) > 0 {
|
||||
// cast.FillMap(&entry.Extra, extra)
|
||||
// }
|
||||
// logger.Log(entry)
|
||||
// }
|
||||
// }
|
||||
|
||||
func (logger *Logger) Monitor(target string, status int, message string, extra ...any) {
|
||||
if logger.CheckLevel(INFO) {
|
||||
entry := GetEntry(reflect.TypeOf(&MonitorLog{})).(*MonitorLog)
|
||||
logger.fillBase(entry, LogTypeMonitor)
|
||||
entry.Target = target
|
||||
entry.Status = status
|
||||
entry.Message = message
|
||||
if len(extra) > 0 {
|
||||
cast.FillMap(&entry.Extra, extra)
|
||||
}
|
||||
logger.Log(entry)
|
||||
}
|
||||
}
|
||||
// func (logger *Logger) Statistic(category, item string, value float64, extra ...any) {
|
||||
// if logger.CheckLevel(INFO) {
|
||||
// entry := GetEntry[StatisticLog]()
|
||||
// logger.fillBase(entry, LogTypeStatistic)
|
||||
// entry.Category = category
|
||||
// entry.Item = item
|
||||
// entry.Value = value
|
||||
// if len(extra) > 0 {
|
||||
// cast.FillMap(&entry.Extra, extra)
|
||||
// }
|
||||
// logger.Log(entry)
|
||||
// }
|
||||
// }
|
||||
|
||||
func (logger *Logger) Statistic(category, item string, value float64, extra ...any) {
|
||||
if logger.CheckLevel(INFO) {
|
||||
entry := GetEntry(reflect.TypeOf(&StatisticLog{})).(*StatisticLog)
|
||||
logger.fillBase(entry, LogTypeStatistic)
|
||||
entry.Category = category
|
||||
entry.Item = item
|
||||
entry.Value = value
|
||||
if len(extra) > 0 {
|
||||
cast.FillMap(&entry.Extra, extra)
|
||||
}
|
||||
logger.Log(entry)
|
||||
}
|
||||
}
|
||||
// type DBLog struct {
|
||||
// BaseLog
|
||||
// DbType string
|
||||
// Dsn string
|
||||
// Query string
|
||||
// QueryArgs string
|
||||
// UsedTime float32
|
||||
// Error string
|
||||
// CallStacks []string
|
||||
// }
|
||||
|
||||
type DBLog struct {
|
||||
BaseLog
|
||||
DbType string
|
||||
Dsn string
|
||||
Query string
|
||||
QueryArgs string
|
||||
UsedTime float32
|
||||
Error string
|
||||
CallStacks []string
|
||||
}
|
||||
// func (logger *Logger) DB(dbType, dsn, query string, args []any, usedTime float32, err error, extra ...any) {
|
||||
// logType := LogTypeDb
|
||||
// level := INFO
|
||||
// var e string
|
||||
// if err != nil {
|
||||
// logType = LogTypeDbError
|
||||
// level = ERROR
|
||||
// e = err.Error()
|
||||
// }
|
||||
|
||||
func (logger *Logger) DB(dbType, dsn, query string, args []any, usedTime float32, err error, extra ...any) {
|
||||
logType := LogTypeDb
|
||||
level := INFO
|
||||
var e string
|
||||
if err != nil {
|
||||
logType = LogTypeDbError
|
||||
level = ERROR
|
||||
e = err.Error()
|
||||
}
|
||||
|
||||
if logger.CheckLevel(level) {
|
||||
entry := GetEntry(reflect.TypeOf(&DBLog{})).(*DBLog)
|
||||
logger.fillBase(entry, logType)
|
||||
entry.DbType = dbType
|
||||
entry.Dsn = dsn
|
||||
entry.Query = query
|
||||
entry.QueryArgs = cast.To[string](args)
|
||||
entry.UsedTime = usedTime
|
||||
if e != "" {
|
||||
entry.Error = e
|
||||
entry.CallStacks = getCallStacks(logger.truncations)
|
||||
}
|
||||
if len(extra) > 0 {
|
||||
cast.FillMap(&entry.Extra, extra)
|
||||
}
|
||||
logger.Log(entry)
|
||||
}
|
||||
}
|
||||
*/
|
||||
// if logger.CheckLevel(level) {
|
||||
// entry := GetEntry[DBLog]()
|
||||
// logger.fillBase(entry, logType)
|
||||
// entry.DbType = dbType
|
||||
// entry.Dsn = dsn
|
||||
// entry.Query = query
|
||||
// entry.QueryArgs = cast.To[string](args)
|
||||
// entry.UsedTime = usedTime
|
||||
// if e != "" {
|
||||
// entry.Error = e
|
||||
// entry.CallStacks = getCallStacks(logger.truncations)
|
||||
// }
|
||||
// if len(extra) > 0 {
|
||||
// cast.FillMap(&entry.Extra, extra)
|
||||
// }
|
||||
// logger.Log(entry)
|
||||
// }
|
||||
// }
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user