wip: alpha version
This commit is contained in:
117
internal/middleware/oplog/new.go
Normal file
117
internal/middleware/oplog/new.go
Normal file
@ -0,0 +1,117 @@
|
||||
package oplog
|
||||
|
||||
import (
|
||||
"context"
|
||||
"github.com/loveuer/nf"
|
||||
"github.com/loveuer/nfflow/internal/database"
|
||||
"github.com/loveuer/nfflow/internal/model"
|
||||
"github.com/loveuer/nfflow/internal/opt"
|
||||
"github.com/loveuer/nfflow/internal/sqlType"
|
||||
"github.com/loveuer/nfflow/internal/util"
|
||||
"github.com/sirupsen/logrus"
|
||||
"sync"
|
||||
"time"
|
||||
)
|
||||
|
||||
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 = database.DB.Session(util.Timeout(10)).
|
||||
Model(&model.OpLog{}).
|
||||
Create(&list).
|
||||
Error; err != nil {
|
||||
logrus.Errorf("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)
|
||||
log, ok := opv.(*OpLog)
|
||||
if !ok {
|
||||
logrus.Warnf("middleware.NewOpLog: %s - %s local '%s' to [*OpLog] invalid", c.Method(), c.Path(), opt.OpLogLocalKey)
|
||||
return err
|
||||
}
|
||||
|
||||
log.Content["time"] = now.UnixMilli()
|
||||
log.Content["user_id"] = op.Id
|
||||
log.Content["username"] = op.Username
|
||||
log.Content["created_at"] = now.UnixMilli()
|
||||
|
||||
select {
|
||||
case lc <- &model.OpLog{
|
||||
CreatedAt: now.UnixMilli(),
|
||||
UpdatedAt: now.UnixMilli(),
|
||||
UserId: op.Id,
|
||||
Username: op.Username,
|
||||
Type: log.Type,
|
||||
Content: sqlType.NewJSONB(log.Content),
|
||||
}:
|
||||
case <-util.Timeout(3).Done():
|
||||
logrus.Warnf("middleware.NewOpLog: %s - %s log -> chan timeout[3s]", c.Method, c.Path())
|
||||
}
|
||||
|
||||
return err
|
||||
}
|
||||
}
|
8
internal/middleware/oplog/oplog.go
Normal file
8
internal/middleware/oplog/oplog.go
Normal file
@ -0,0 +1,8 @@
|
||||
package oplog
|
||||
|
||||
import "github.com/loveuer/nfflow/internal/model"
|
||||
|
||||
type OpLog struct {
|
||||
Type model.OpLogType
|
||||
Content map[string]any
|
||||
}
|
Reference in New Issue
Block a user