You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
92 lines
2.9 KiB
92 lines
2.9 KiB
package analyze
|
|
|
|
import (
|
|
"fmt"
|
|
"sync/atomic"
|
|
"time"
|
|
|
|
"yunyan/utils"
|
|
)
|
|
|
|
// statLoc 统计日界时区,由模块 Init 经 setStatLoc 写入(默认 Asia/Shanghai)。
|
|
// 埋点(Report)与同步(sync)两侧共用,保证 0 点切日口径一致;未初始化时回退固定 UTC+8。
|
|
var statLoc atomic.Value // *time.Location
|
|
|
|
func setStatLoc(loc *time.Location) { statLoc.Store(loc) }
|
|
|
|
func statLocation() *time.Location {
|
|
if v := statLoc.Load(); v != nil {
|
|
return v.(*time.Location)
|
|
}
|
|
return time.FixedZone("UTC+8", 8*3600)
|
|
}
|
|
|
|
// dayNumber 把时间转成 YYYYMMDD 形式的统计日(按固定统计时区,跨部署口径一致)。
|
|
func dayNumber(t time.Time) uint32 {
|
|
return utils.StatDayNumber(t, statLocation())
|
|
}
|
|
|
|
// ============================ Redis 键 ============================
|
|
|
|
// keyPrefix 形如 {集群标签}:analyze:{应用ID}:{区域},由 setupKeys 写入;
|
|
// 多集群 / 多应用 / 多区域共用一套 Redis 时互不串台。
|
|
// 用 atomic 保证 setupKeys(启动期) 与 Report(运行期) 间无竞态。
|
|
var keyPrefix atomic.Value // string
|
|
|
|
func prefix() string {
|
|
if p := keyPrefix.Load(); p != nil {
|
|
return p.(string)
|
|
}
|
|
return ""
|
|
}
|
|
|
|
// indexKey 活跃统计分区的索引集合:成员为 "产品ID:统计日"。
|
|
func indexKey() string { return prefix() + ":idx" }
|
|
|
|
// hashKey 某 [产品×日] 累加计数的哈希。
|
|
func hashKey(productId, statDay uint32) string {
|
|
return fmt.Sprintf("%s:%d:%d", prefix(), productId, statDay)
|
|
}
|
|
|
|
// hllKey 某 [产品×日] 某去重指标的 HyperLogLog。
|
|
func hllKey(productId, statDay uint32, metric string) string {
|
|
return fmt.Sprintf("%s:%d:%d:u:%s", prefix(), productId, statDay, metric)
|
|
}
|
|
|
|
// partition 索引集合的成员,标识一个 产品:日 分区。
|
|
func partition(productId, statDay uint32) string {
|
|
return fmt.Sprintf("%d:%d", productId, statDay)
|
|
}
|
|
|
|
// 统计哈希的字段名,与 stats_global_day 表列名保持一致,便于追溯。
|
|
const (
|
|
fLoginCount = "login_count"
|
|
fNewUserCount = "new_user_count"
|
|
fActiveDeviceCount = "active_device_count"
|
|
fBindDeviceCount = "bind_device_count"
|
|
fQRActiveCount = "qr_active_count"
|
|
fOrderCreateCount = "order_create_count"
|
|
fOrderPaidCount = "order_paid_count"
|
|
fOrderFailedCount = "order_failed_count"
|
|
fOrderCreateAmount = "order_create_amount"
|
|
fOrderPaidAmount = "order_paid_amount"
|
|
fGrantVipDay = "grant_vip_day"
|
|
fGrantAiIntegral = "grant_ai_integral"
|
|
fGrantTradeSecond = "grant_trade_second"
|
|
fGrantMeetSecond = "grant_meet_second"
|
|
fAiChatCount = "ai_chat_count"
|
|
fAiUpToken = "ai_up_token"
|
|
fAiDownToken = "ai_down_token"
|
|
fTradeCount = "trade_count"
|
|
fTradeSecond = "trade_second"
|
|
fTradeWords = "trade_words"
|
|
fMeetCount = "meet_count"
|
|
fMeetSecond = "meet_second"
|
|
)
|
|
|
|
// 去重指标的 HLL 名(对应 stats_global_day 的 *_user_count 列)。
|
|
const (
|
|
uLogin = "login"
|
|
uActive = "active"
|
|
uPay = "pay"
|
|
)
|
|
|