2025-06-10 17:50:46 +08:00

98 lines
2.1 KiB
Go

package logging
import (
"time"
jsoniter "github.com/json-iterator/go"
"github.com/rs/xid"
"gorm.io/gorm"
)
type Logger struct {
ID string `gorm:"size:20;primaryKey;" json:"id"` // Unique ID
Level string `gorm:"size:20;index;" json:"level"` // Log level
TraceID string `gorm:"size:64;index;" json:"trace_id"` // Trace ID
UserID string `gorm:"size:20;index;" json:"user_id"` // User ID
Tag string `gorm:"size:32;index;" json:"tag"` // Log tag
Message string `gorm:"size:1024;" json:"message"` // Log message
Stack string `gorm:"type:text;" json:"stack"` // Error stack
Data string `gorm:"type:text;" json:"data"` // Log data
CreatedAt time.Time `gorm:"index;" json:"created_at"` // Create time
}
func NewGormHook(db *gorm.DB) *GormHook {
err := db.AutoMigrate(new(Logger))
if err != nil {
panic(err)
}
return &GormHook{
db: db,
}
}
// Gorm Logger Hook
type GormHook struct {
db *gorm.DB
}
func (h *GormHook) Exec(extra map[string]string, b []byte) error {
msg := &Logger{
ID: xid.New().String(),
}
data := make(map[string]interface{})
err := jsoniter.Unmarshal(b, &data)
if err != nil {
return err
}
if v, ok := data["ts"]; ok {
msg.CreatedAt = time.UnixMilli(int64(v.(float64)))
delete(data, "ts")
}
if v, ok := data["msg"]; ok {
msg.Message = v.(string)
delete(data, "msg")
}
if v, ok := data["tag"]; ok {
msg.Tag = v.(string)
delete(data, "tag")
}
if v, ok := data["trace_id"]; ok {
msg.TraceID = v.(string)
delete(data, "trace_id")
}
if v, ok := data["user_id"]; ok {
msg.UserID = v.(string)
delete(data, "user_id")
}
if v, ok := data["level"]; ok {
msg.Level = v.(string)
delete(data, "level")
}
if v, ok := data["stack"]; ok {
msg.Stack = v.(string)
delete(data, "stack")
}
delete(data, "caller")
for k, v := range extra {
data[k] = v
}
if len(data) > 0 {
buf, _ := jsoniter.Marshal(data)
msg.Data = string(buf)
}
return h.db.Create(msg).Error
}
func (h *GormHook) Close() error {
db, err := h.db.DB()
if err != nil {
return err
}
return db.Close()
}