package datacenter import ( "encoding/json" "fmt" "strings" "time" "91porn-server/app/appg" "91porn-server/common" "91porn-server/common/log" "91porn-server/models/v/usermod" "github.com/gin-gonic/gin" ) type OnlineStatData struct { UserId int64 `bson:"userId" json:"userId"` // 用户Id DistrictCode string `json:"districtCode" bson:"districtCode"` // 渠道码 WatchCount int64 `json:"watchCount,omitempty" bson:"watchCount"` // 观看次数 WatchTime int64 `json:"watchTime,omitempty" bson:"watchTime"` // 观看时长 AdClick int64 `json:"adClick,omitempty" bson:"adClick"` // 广告点击 AppClick int64 `json:"appClick,omitempty" bson:"appClick"` // APP点击 RequestCount int64 `json:"requestCount,omitempty" bson:"requestCount"` // 请求次数 RegisterAt time.Time `json:"registerAt,omitempty" bson:"registerAt"` // 注册时间(只统计最近一个月注册的渠道用户?) StatIndex int64 `json:"statIndex" bson:"statIndex"` // 统计数据更新时钟 SendIndex int64 `json:"sendIndex" bson:"sendIndex"` // 上次发送时钟 SendAt time.Time `json:"sendAt" bson:"sendAt"` // 上次发送时间 } // OnlineStat 统计用户在线时间和接口访问次数 func OnlineStat(ctx *gin.Context) { now := time.Now() var statInfo OnlineStatData // 查询用户 userId, err := common.GetUID(ctx) if userId <= 0 || err != nil { return } userOnlineKey := fmt.Sprintf("mdsmOnline:%s:%d", now.Format("20060102"), userId) onlineValue, err := appg.Redis.Get(userOnlineKey) if err != nil { log.Error("OnlineStat", log.E(err)) return } if onlineValue != nil && *onlineValue != "" { err = json.Unmarshal([]byte(*onlineValue), &statInfo) if err != nil { log.Error("OnlineStat", log.E(err)) return } } else { user, serr := usermod.FindUserByUID(userId) if serr != nil { return } statInfo = OnlineStatData{ UserId: int64(userId), DistrictCode: user.DistrictCode, RegisterAt: user.CreatedAt, WatchCount: 0, WatchTime: 0, AdClick: 0, AppClick: 0, RequestCount: 0, StatIndex: 0, SendIndex: 0, SendAt: now, } } // 统计数据 StatApiHandle(ctx, &statInfo) // 更新数据库埋点规则 () 后期只统计渠道用户 if (statInfo.StatIndex < 2) || //前1次直接发送 (statInfo.StatIndex-statInfo.SendIndex) > 50 || //每30次合并发送 statInfo.SendAt.Before(time.Now().Add(-time.Second*40)) { // 超过40秒 // 清理数据 statInfo.WatchCount = 0 statInfo.AdClick = 0 statInfo.AppClick = 0 statInfo.RequestCount = 0 statInfo.SendAt = now statInfo.SendIndex = statInfo.StatIndex } marshalStr, err := json.Marshal(statInfo) if err != nil { log.Error("OnlineStat", log.E(err)) return } _ = appg.Redis.Set(userOnlineKey, marshalStr, 24*time.Hour) } // StatApiHandle 统计Api和关键接口次数 func StatApiHandle(ctx *gin.Context, statInfo *OnlineStatData) { statInfo.StatIndex += 1 statInfo.RequestCount += 1 // 播放接口 if strings.HasPrefix(ctx.Request.URL.Path, "/api/app/vid/h5/m3u8/") || strings.HasPrefix(ctx.Request.URL.Path, "/api/app/vid/m3u8/") || strings.HasPrefix(ctx.Request.URL.Path, "/api/app/vid/h5/light/m3u8/") { statInfo.WatchCount += 1 statInfo.StatIndex += 1 } // 广告点击 if strings.Contains(ctx.Request.URL.Path, "/api/app/ads/click") || strings.Contains(ctx.Request.URL.Path, "/api/app/recreation/click") { statInfo.AdClick += 1 statInfo.StatIndex += 1 } // 其他关键监控指标 }