Browse Source

update 后台操作记录由mongodb切换为logstash

Alvin 8 months ago
parent
commit
9929ab19c7

+ 69 - 20
game/game_cluster/nodes/webadmin/router/middleware.go

@@ -7,32 +7,46 @@ import (
 
 	"github.com/gin-gonic/gin"
 	"github.com/go-redis/redis/v8"
+	jsoniter "github.com/json-iterator/go"
 	mhayaTime "github.com/mhaya/extend/time"
 	cfacade "github.com/mhaya/facade"
 	"github.com/mhaya/game/game_cluster/internal/code"
 	"github.com/mhaya/game/game_cluster/internal/constant"
 	"github.com/mhaya/game/game_cluster/internal/mdb"
+	"github.com/mhaya/game/game_cluster/internal/mdb/eventmodels"
 	"github.com/mhaya/game/game_cluster/internal/mdb/models"
+	"github.com/mhaya/game/game_cluster/internal/param"
+	rpcLogstash "github.com/mhaya/game/game_cluster/internal/rpc/logstash"
 	"github.com/mhaya/game/game_cluster/nodes/webadmin/common"
-	"github.com/mhaya/game/game_cluster/nodes/webadmin/model"
-	"github.com/mhaya/game/game_cluster/nodes/webadmin/service"
 	mhayaLogger "github.com/mhaya/logger"
 	"go.mongodb.org/mongo-driver/bson"
 	"go.mongodb.org/mongo-driver/mongo"
 )
 
-func Auth(settingObj cfacade.ProfileJSON) gin.HandlerFunc {
+var (
+	json = jsoniter.ConfigCompatibleWithStandardLibrary
+)
+
+func Auth(app cfacade.IApplication) gin.HandlerFunc {
 	return func(c *gin.Context) {
 		// 请求开始时间
 		startTime := mhayaTime.Now().UnixMilli()
 
-		tokenString := c.GetHeader("Token")
+		tokenString := ""
+		roleId := ""
+		var err error
+
+		defer func() {
+			sendLogRecord(c, app, tokenString, roleId, startTime)
+		}()
+
+		tokenString = c.GetHeader("Token")
 		if tokenString == "" {
 			common.PackUnauthorizedResult(c, code.UnauthorizedError, "token is empty")
 			return
 		}
 
-		roleId, err := mdb.RDB.Get(context.Background(), tokenString).Result()
+		roleId, err = mdb.RDB.Get(context.Background(), tokenString).Result()
 		if err != nil && err != redis.Nil {
 			mhayaLogger.Warnf("Auth Get error: %s", err.Error())
 			common.PackUnauthorizedResult(c, code.InternalError, "token is empty")
@@ -58,7 +72,7 @@ func Auth(settingObj cfacade.ProfileJSON) gin.HandlerFunc {
 			}
 
 			// 非管理员需要进行ip校验
-			openIpWhitelist := settingObj.Get("open_ip_whitelist").ToBool()
+			openIpWhitelist := app.Settings().Get("open_ip_whitelist").ToBool()
 			if openIpWhitelist {
 				err = checkIPWhitelist(c)
 				if err != nil {
@@ -83,20 +97,6 @@ func Auth(settingObj cfacade.ProfileJSON) gin.HandlerFunc {
 		}
 
 		c.Next()
-
-		userName, err := mdb.RDB.Get(context.Background(), common.GetUserNameKey(tokenString)).Result()
-		if err == nil {
-			service.NewSynthesis().InsertRecord(model.UserOperationLog{
-				Username:     userName,
-				RoleId:       roleId,
-				Path:         c.Request.URL.Path,
-				Method:       c.Request.Method,
-				StatusCode:   c.Writer.Status(),
-				Dur:          mhayaTime.Now().UnixMilli() - startTime,
-				ClientIP:     c.ClientIP(),
-				ErrorMessage: c.Errors.ByType(gin.ErrorTypePrivate).String(),
-			})
-		}
 	}
 }
 
@@ -124,3 +124,52 @@ func checkIPWhitelist(c *gin.Context) error {
 
 	return nil // 允许访问
 }
+
+func sendLogRecord(c *gin.Context, app cfacade.IApplication, tokenString, roleId string, startTime int64) {
+	userName, err := mdb.RDB.Get(context.Background(), common.GetUserNameKey(tokenString)).Result()
+	if err != nil {
+		mhayaLogger.Warnf("sendLogRecord Get userName error: %s, token: %s", err.Error(), tokenString)
+		return
+	}
+
+	nodeId := app.NodeId()
+	req, err := packBackendOperationEventReq(nodeId, &eventmodels.BackendOperationEventContent{
+		UserBasic: eventmodels.UserBasic{
+			UserName: userName,
+			IsRobot:  false,
+		},
+		EventBasic: eventmodels.EventBasic{
+			ServerId: nodeId,
+			IsSuccess: func() bool {
+				return c.Writer.Status() == int(code.OK)
+			}(),
+			CreateAt: mhayaTime.Now().Unix(),
+		},
+		RoleId:       roleId,
+		Path:         c.Request.URL.Path,
+		Method:       c.Request.Method,
+		StatusCode:   c.Writer.Status(),
+		Dur:          mhayaTime.Now().UnixMilli() - startTime,
+		ClientIP:     c.ClientIP(),
+		ErrorMessage: c.Errors.ByType(gin.ErrorTypePrivate).String(),
+	})
+	if err != nil {
+		mhayaLogger.Warnf("sendLogRecord packBackendOperationEventReq error: %s, token: %s", err.Error(), tokenString)
+		return
+	}
+
+	rpcLogstash.HandleLogRecord(app, req)
+}
+
+func packBackendOperationEventReq(nodeId string, content *eventmodels.BackendOperationEventContent) (*param.HandleLogReq, error) {
+	bytes, err := json.Marshal(content)
+	if err != nil {
+		return nil, err
+	}
+
+	return &param.HandleLogReq{
+		ServerId:    nodeId,
+		EventName:   content.EventName(),
+		JsonContent: string(bytes),
+	}, nil
+}

+ 1 - 1
game/game_cluster/nodes/webadmin/router/router.go

@@ -37,7 +37,7 @@ func (c *Controller) SetRouter() {
 }
 
 func (c *Controller) InitApiRouter(u *gin.RouterGroup) {
-	u.Use(Auth(c.App.Settings()))
+	u.Use(Auth(c.App))
 
 	// 综合统计
 	u.POST("/statistics/overview", controller.NewSynthesis().Overview)

+ 34 - 0
game/game_cluster/nodes/webadmin/service/common.go

@@ -1,5 +1,7 @@
 package service
 
+import "gorm.io/gorm"
+
 func checkPageParam(page, pageSize int) (int, int) {
 	retPage := 0
 	retPageSize := 0
@@ -12,9 +14,41 @@ func checkPageParam(page, pageSize int) (int, int) {
 
 	if pageSize <= 0 {
 		retPageSize = 20
+	} else if pageSize > 100 {
+		retPageSize = 100
 	} else {
 		retPageSize = pageSize
 	}
 
 	return retPage, retPageSize
 }
+
+type PaginationResult struct {
+	Count int64
+	Limit func(db *gorm.DB) *gorm.DB
+}
+
+func Paginate(db *gorm.DB, page int, size int) *PaginationResult {
+	var count int64
+	db.Count(&count)
+
+	limit := func(db *gorm.DB) *gorm.DB {
+		if page <= 0 {
+			page = 1
+		}
+
+		switch {
+		case size > 100:
+			size = 100
+		case size <= 0:
+			size = 10
+		}
+
+		return db.Offset((page - 1) * size).Limit(size)
+	}
+
+	return &PaginationResult{
+		Count: count,
+		Limit: limit,
+	}
+}

+ 40 - 61
game/game_cluster/nodes/webadmin/service/synthesis.go

@@ -9,6 +9,7 @@ import (
 	"github.com/mhaya/game/game_cluster/internal/code"
 	"github.com/mhaya/game/game_cluster/internal/constant"
 	"github.com/mhaya/game/game_cluster/internal/mdb"
+	"github.com/mhaya/game/game_cluster/internal/mdb/eventmodels"
 	"github.com/mhaya/game/game_cluster/internal/mdb/models"
 	"github.com/mhaya/game/game_cluster/nodes/webadmin/common"
 	"github.com/mhaya/game/game_cluster/nodes/webadmin/entity"
@@ -19,6 +20,7 @@ import (
 	"go.mongodb.org/mongo-driver/bson/primitive"
 	"go.mongodb.org/mongo-driver/mongo"
 	"go.mongodb.org/mongo-driver/mongo/options"
+	"gorm.io/gorm"
 )
 
 type Synthesis struct {
@@ -714,77 +716,54 @@ func (s *Synthesis) InsertRecord(param model.UserOperationLog) {
 func (s *Synthesis) RecordList(req entity.RecordListReq) (*entity.RecordListResp, *code.Result) {
 	page, pageSize := checkPageParam(req.Page, req.Size)
 
-	record := new(model.UserOperationLog)
-	collection := mdb.MDB.Collection(record.TableName())
-
-	// 构建过滤器
-	filter := bson.M{}
-
-	if req.UserName != "" {
-		filter["userName"] = req.UserName
-	}
-	if req.RoleId != "" {
-		filter["role_id"] = req.RoleId
-	}
-	if req.ID != "" {
-		id, err := primitive.ObjectIDFromHex(req.ID)
-		if err != nil {
-			mhayaLogger.Warnf("RecordList ObjectIDFromHex error:%v, req.ID:%s", err, req.ID)
-			return nil, common.NewResult(code.ParamError)
-		}
-
-		filter["id"] = id
-	}
-
-	if req.StartTime != 0 {
-		filter["createAt"] = bson.M{
-			"$gte": req.StartTime,
-			"$lte": req.EndTime,
-		}
-	}
-
-	// 设置分页选项
-	findOptions := options.Find()
-	findOptions.SetSkip(int64((page - 1) * pageSize))
-	findOptions.SetLimit(int64(pageSize))
-	findOptions.SetSort(bson.D{{"created_at", -1}})
+	var records *[]eventmodels.BackendOperationEventContent
 
-	// 获取总数total
-	ctx, cancel := context.WithTimeout(context.Background(), 100*time.Second)
-	defer cancel()
-	count, err := collection.CountDocuments(ctx, filter)
-	if err != nil {
-		mhayaLogger.Warnf("RecordList CountDocuments error:%v", err)
-		return nil, common.NewResult(code.InternalError)
-	}
-
-	// 查询数据
-	var results []*entity.RecordListDetail
-	cursor, err := collection.Find(ctx, filter, findOptions)
-	if err != nil {
+	// TODO 筛选条件
+	where := &eventmodels.BackendOperationEventContent{
+		UserBasic: eventmodels.UserBasic{
+			UserName: req.UserName,
+		},
+		EventBasic: eventmodels.EventBasic{
+			ServerId:  "",
+			IsSuccess: false,
+			CreateAt:  0,
+		},
+		RoleId:       req.RoleId,
+		Path:         "/v1/admin/user/log",
+		Method:       "",
+		StatusCode:   0,
+		Dur:          0,
+		ClientIP:     "",
+		ErrorMessage: "",
+	}
+	db := mdb.LogstashDB.Model(&eventmodels.BackendOperationEventContent{}).Where(where).Order("create_at")
+
+	pages := Paginate(db, page, pageSize)
+	err := db.Scopes(pages.Limit).Find(&records).Error
+	if err != nil && err != gorm.ErrRecordNotFound {
 		mhayaLogger.Warnf("RecordList Find error:%v", err)
 		return nil, common.NewResult(code.InternalError)
 	}
-	defer cursor.Close(ctx)
 
-	// 解析结果
-	for cursor.Next(ctx) {
-		var result entity.RecordListDetail
-		if err := cursor.Decode(&result); err != nil {
-			mhayaLogger.Warnf("RecordList Decode error:%v", err)
-			return nil, common.NewResult(code.InternalError)
-		}
-		results = append(results, &result)
-	}
+	var results []*entity.RecordListDetail
 
-	if err := cursor.Err(); err != nil {
-		mhayaLogger.Warnf("RecordList cursor error:%v", err)
-		return nil, common.NewResult(code.InternalError)
+	for _, v := range *records {
+		results = append(results, &entity.RecordListDetail{
+			Username:     v.UserName,
+			RoleId:       v.RoleId,
+			Path:         v.Path,
+			Method:       v.Method,
+			StatusCode:   v.StatusCode,
+			Dur:          v.Dur,
+			ClientIP:     v.ClientIP,
+			ErrorMessage: v.ErrorMessage,
+			CreatedAt:    v.CreateAt,
+		})
 	}
 
 	return &entity.RecordListResp{
 		Details: results,
-		Total:   count,
+		Total:   pages.Count,
 	}, nil
 }