119 lines
2.3 KiB
Go
119 lines
2.3 KiB
Go
|
package oplog
|
||
|
|
||
|
import (
|
||
|
"context"
|
||
|
"sync"
|
||
|
"time"
|
||
|
|
||
|
"esway/internal/database/db"
|
||
|
"esway/internal/model"
|
||
|
"esway/internal/opt"
|
||
|
"esway/internal/sqlType"
|
||
|
"esway/internal/tool"
|
||
|
|
||
|
"github.com/loveuer/nf"
|
||
|
"github.com/loveuer/nf/nft/log"
|
||
|
)
|
||
|
|
||
|
var (
|
||
|
_once = &sync.Once{}
|
||
|
lc = make(chan *model.OpLog, 1024)
|
||
|
)
|
||
|
|
||
|
// NewOpLog
|
||
|
//
|
||
|
// * 记录操作日志的 中间件使用方法如下:
|
||
|
//
|
||
|
// app := nf.New()
|
||
|
// app.Post("/login", oplog.NewOpLog(ctx), HandleLog)
|
||
|
//
|
||
|
// func HandleLog(c *nf.Ctx) error {
|
||
|
// // 你的操作逻辑
|
||
|
// c.Local(opt.OpLogLocalKey, &oplog.OpLog{})
|
||
|
// // 剩下某些逻辑
|
||
|
// // return xxx
|
||
|
// }
|
||
|
func NewOpLog(ctx context.Context) nf.HandlerFunc {
|
||
|
_once.Do(func() {
|
||
|
go func() {
|
||
|
var (
|
||
|
err error
|
||
|
ticker = time.NewTicker(time.Duration(opt.OpLogWriteDurationSecond) * time.Second)
|
||
|
list = make([]*model.OpLog, 0, 1024)
|
||
|
|
||
|
write = func() {
|
||
|
if len(list) == 0 {
|
||
|
return
|
||
|
}
|
||
|
|
||
|
if err = db.Default.Session(tool.Timeout(10)).
|
||
|
Model(&model.OpLog{}).
|
||
|
Create(&list).
|
||
|
Error; err != nil {
|
||
|
log.Error("middleware.NewOpLog: write logs err=%v", err)
|
||
|
}
|
||
|
|
||
|
list = list[:0]
|
||
|
}
|
||
|
)
|
||
|
|
||
|
Loop:
|
||
|
for {
|
||
|
select {
|
||
|
case <-ctx.Done():
|
||
|
break Loop
|
||
|
case <-ticker.C:
|
||
|
write()
|
||
|
case item, ok := <-lc:
|
||
|
if !ok {
|
||
|
return
|
||
|
}
|
||
|
|
||
|
list = append(list, item)
|
||
|
|
||
|
if len(list) >= 100 {
|
||
|
write()
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
write()
|
||
|
}()
|
||
|
})
|
||
|
|
||
|
return func(c *nf.Ctx) error {
|
||
|
now := time.Now()
|
||
|
|
||
|
err := c.Next()
|
||
|
|
||
|
op, ok := c.Locals("user").(*model.User)
|
||
|
|
||
|
opv := c.Locals(opt.OpLogLocalKey)
|
||
|
logItem, ok := opv.(*OpLog)
|
||
|
if !ok {
|
||
|
log.Warn("middleware.NewOpLog: %s - %s local '%s' to [*OpLog] invalid", c.Method(), c.Path(), opt.OpLogLocalKey)
|
||
|
return err
|
||
|
}
|
||
|
|
||
|
logItem.Content["time"] = now.UnixMilli()
|
||
|
logItem.Content["user_id"] = op.Id
|
||
|
logItem.Content["username"] = op.Username
|
||
|
logItem.Content["created_at"] = now.UnixMilli()
|
||
|
|
||
|
select {
|
||
|
case lc <- &model.OpLog{
|
||
|
CreatedAt: now.UnixMilli(),
|
||
|
UpdatedAt: now.UnixMilli(),
|
||
|
UserId: op.Id,
|
||
|
Username: op.Username,
|
||
|
Type: logItem.Type,
|
||
|
Content: sqlType.NewJSONB(logItem.Content),
|
||
|
}:
|
||
|
case <-tool.Timeout(3).Done():
|
||
|
log.Warn("middleware.NewOpLog: %s - %s log -> chan timeout[3s]", c.Method, c.Path())
|
||
|
}
|
||
|
|
||
|
return err
|
||
|
}
|
||
|
}
|