diff --git a/README.md b/README.md index 639d3c4..11bf94a 100644 --- a/README.md +++ b/README.md @@ -17,7 +17,6 @@ mindmap /notify 通知功能接口定义 /planner 策划相关工具目录 /pce 配置导表功能实现 - /report 数据埋点及上报功能 /server 网络服务器支持 /cross 内置跨服功能实现 /router 内置路由器功能实现 diff --git a/report/README.md b/report/README.md deleted file mode 100644 index f5bcf73..0000000 --- a/report/README.md +++ /dev/null @@ -1,17 +0,0 @@ -# Report -用于数据上报,其中数据埋点是线程安全的 - -# 全局埋点 GlobalBuried -全局埋点适用于活跃用户数、用户总量等全局的数据统计 - -# 数据埋点 DataBuried -数据埋点适合进行用户数据、交易数据等存在多id情况的数据统计 - -# 跨进程上报 -通常数据埋点会占用一些系统资源而妨碍主进程的运行,这时候可以通过将上报工作独立出来减轻主进程负担 - -默认情况下的埋点数据是存储在执行进程的内存中的,可以通过可选项自定义存储位置,例如`Redis` - -> 实现思路,以`Redis`为例: -> - 在主进程创建埋点,并将数据读写更改为`Redis` -> - 上报进程中创建上报器,按照特定策略从`Redis`读取数据进行上报 diff --git a/report/data_buried.go b/report/data_buried.go deleted file mode 100644 index 9ccfaf1..0000000 --- a/report/data_buried.go +++ /dev/null @@ -1,60 +0,0 @@ -package report - -import ( - "github.com/kercylan98/minotaur/utils/concurrent" - "sync" -) - -// NewDataBuried 创建一个数据埋点 -func NewDataBuried[DataID comparable, Data any](name string, hitLogic HitLogic[Data], options ...DataBuriedOption[DataID, Data]) *DataBuried[DataID, Data] { - buried := &DataBuried[DataID, Data]{ - name: name, - data: concurrent.NewBalanceMap[DataID, Data](), - hitLogic: hitLogic, - } - buried.setData = func(id DataID, data Data) { - buried.data.Set(id, data) - } - buried.getData = func(id DataID) Data { - return buried.data.Get(id) - } - for _, option := range options { - option(buried) - } - return buried -} - -// DataBuried 数据埋点 -// - 数据埋点通常用于统计不同类型的数据,例如用户数据、商城数据等 -type DataBuried[DataID comparable, Data any] struct { - name string - data *concurrent.BalanceMap[DataID, Data] - hitLogic HitLogic[Data] - getData func(DataID) Data - setData func(id DataID, data Data) - rw sync.RWMutex -} - -// GetName 获取名称 -func (slf *DataBuried[DataID, Data]) GetName() string { - return slf.name -} - -// Hit 命中数据埋点 -func (slf *DataBuried[DataID, Data]) Hit(id DataID, data Data) { - slf.rw.Lock() - defer slf.rw.Unlock() - slf.setData(id, slf.hitLogic(slf.getData(id), data)) -} - -// GetData 获取数据 -func (slf *DataBuried[DataID, Data]) GetData(id DataID) Data { - slf.rw.RLock() - defer slf.rw.RUnlock() - return slf.getData(id) -} - -// GetSize 获取已触发该埋点的id数量 -func (slf *DataBuried[DataID, Data]) GetSize() int { - return slf.data.Size() -} diff --git a/report/data_buried_options.go b/report/data_buried_options.go deleted file mode 100644 index 9353164..0000000 --- a/report/data_buried_options.go +++ /dev/null @@ -1,13 +0,0 @@ -package report - -type DataBuriedOption[DataID comparable, Data any] func(buried *DataBuried[DataID, Data]) - -// WithDataBuriedStorage 通过特定的存储模式创建数据埋点 -// - 默认情况下埋点数据存储在内存中 -// - 使用该方式可以将埋点存储存储在其他如数据库、消息队列中 -func WithDataBuriedStorage[DataID comparable, Data any](getData func(id DataID) Data, setData func(id DataID, data Data)) DataBuriedOption[DataID, Data] { - return func(buried *DataBuried[DataID, Data]) { - buried.getData = getData - buried.setData = setData - } -} diff --git a/report/doc.go b/report/doc.go deleted file mode 100644 index 8c86daa..0000000 --- a/report/doc.go +++ /dev/null @@ -1,2 +0,0 @@ -// Package report 提供了对数据埋点及上报的实现 -package report diff --git a/report/global_buried.go b/report/global_buried.go deleted file mode 100644 index cc6a7d6..0000000 --- a/report/global_buried.go +++ /dev/null @@ -1,51 +0,0 @@ -package report - -import "sync" - -// NewGlobalBuried 创建一个全局埋点 -func NewGlobalBuried[Data any](name string, hitLogic HitLogic[Data], options ...GlobalBuriedOption[Data]) *GlobalBuried[Data] { - buried := &GlobalBuried[Data]{ - name: name, - hitLogic: hitLogic, - } - buried.setData = func(data Data) { - buried.data = data - } - buried.getData = func() Data { - return buried.data - } - for _, option := range options { - option(buried) - } - return buried -} - -// GlobalBuried 全局埋点 -// - 全局埋点适用于活跃用户数等统计 -type GlobalBuried[Data any] struct { - name string - data Data - hitLogic HitLogic[Data] - getData func() Data - setData func(data Data) - rw sync.RWMutex -} - -// GetName 获取名称 -func (slf *GlobalBuried[Data]) GetName() string { - return slf.name -} - -// Hit 命中数据埋点 -func (slf *GlobalBuried[Data]) Hit(data Data) { - slf.rw.Lock() - defer slf.rw.Unlock() - slf.setData(slf.hitLogic(slf.getData(), data)) -} - -// GetData 获取数据 -func (slf *GlobalBuried[Data]) GetData() Data { - slf.rw.RLock() - defer slf.rw.RUnlock() - return slf.getData() -} diff --git a/report/global_buried_options.go b/report/global_buried_options.go deleted file mode 100644 index adb3c5d..0000000 --- a/report/global_buried_options.go +++ /dev/null @@ -1,13 +0,0 @@ -package report - -type GlobalBuriedOption[Data any] func(buried *GlobalBuried[Data]) - -// WithGlobalBuriedStorage 通过特定的存储模式创建全局埋点 -// - 默认情况下埋点数据存储在内存中 -// - 使用该方式可以将埋点存储存储在其他如数据库、消息队列中 -func WithGlobalBuriedStorage[DataID comparable, Data any](getData func() Data, setData func(data Data)) GlobalBuriedOption[Data] { - return func(buried *GlobalBuried[Data]) { - buried.getData = getData - buried.setData = setData - } -} diff --git a/report/hit_logic.go b/report/hit_logic.go deleted file mode 100644 index 76747d1..0000000 --- a/report/hit_logic.go +++ /dev/null @@ -1,32 +0,0 @@ -package report - -import "github.com/kercylan98/minotaur/utils/generic" - -// HitLogic 埋点命中逻辑 -// - data: 当前数据 -// - input: 新输入的数据 -// - return: 设置当前数据 -type HitLogic[Data any] func(data Data, input Data) Data - -// WithHitLogicCustomize 通过自定义命中处理逻辑处理命中事件 -// - 通过对旧数据和新数据的处理,将返回的值作为新的数据值 -func WithHitLogicCustomize[Data any](logic func(data Data, input Data) Data) HitLogic[Data] { - return func(data Data, input Data) Data { - return logic(data, input) - } -} - -// WithHitLogicCover 通过覆盖原数值的方式处理命中事件 -func WithHitLogicCover[Data any]() HitLogic[Data] { - return func(data Data, input Data) Data { - return input - } -} - -// WithHitLogicOverlay 通过数值叠加的方式处理命中事件 -// - 例如原始值为100,新输入为200,最终结果为300 -func WithHitLogicOverlay[Data generic.Number]() HitLogic[Data] { - return func(data Data, input Data) Data { - return data + input - } -} diff --git a/report/reporter.go b/report/reporter.go deleted file mode 100644 index 7f87aa4..0000000 --- a/report/reporter.go +++ /dev/null @@ -1,32 +0,0 @@ -package report - -import "github.com/kercylan98/minotaur/utils/timer" - -func NewReporter(reportHandle func() error, options ...ReporterOption) *Reporter { - reporter := &Reporter{ - reportHandle: reportHandle, - } - for _, option := range options { - option(reporter) - } - if reporter.ticker == nil { - reporter.ticker = timer.GetTicker(50) - } - for _, strategy := range reporter.strategies { - strategy(reporter) - } - return reporter -} - -// Reporter 数据上报器 -type Reporter struct { - ticker *timer.Ticker - strategies []ReporterStrategy - reportHandle func() error - errorHandle func(reporter *Reporter, err error) -} - -// Report 上报 -func (slf *Reporter) Report() error { - return slf.reportHandle() -} diff --git a/report/reporter_options.go b/report/reporter_options.go deleted file mode 100644 index 2738794..0000000 --- a/report/reporter_options.go +++ /dev/null @@ -1,25 +0,0 @@ -package report - -import "github.com/kercylan98/minotaur/utils/timer" - -type ReporterOption func(reporter *Reporter) - -// WithReporterTicker 通过特定的定时器创建上报器 -func WithReporterTicker(ticker *timer.Ticker) ReporterOption { - return func(reporter *Reporter) { - reporter.ticker = ticker - } -} - -// WithReporterStrategies 通过特定上报策略进行创建 -func WithReporterStrategies(strategies ...ReporterStrategy) ReporterOption { - return func(reporter *Reporter) { - reporter.strategies = append(reporter.strategies, strategies...) - } -} - -func WithReporterErrorHandle(errorHandle func(reporter *Reporter, err error)) ReporterOption { - return func(reporter *Reporter) { - reporter.errorHandle = errorHandle - } -} diff --git a/report/reporter_strategy.go b/report/reporter_strategy.go deleted file mode 100644 index eecaaba..0000000 --- a/report/reporter_strategy.go +++ /dev/null @@ -1,41 +0,0 @@ -package report - -import ( - "fmt" - "github.com/kercylan98/minotaur/utils/timer" - "time" -) - -// ReporterStrategy 上报器策略 -type ReporterStrategy func(reporter *Reporter) - -// StrategyLoop 循环上报 -// - 将在创建后上报一次,并且在每隔一段时间后继续上报 -func StrategyLoop(t time.Duration) ReporterStrategy { - return func(reporter *Reporter) { - reporter.ticker.Loop(fmt.Sprintf("ReportStrategyLoop_%d", t.Milliseconds()), timer.Instantly, t, timer.Forever, func() { - if err := reporter.Report(); err != nil && reporter.errorHandle != nil { - reporter.errorHandle(reporter, err) - } - }) - } -} - -// StrategyFixedTime 将在每天的固定时间上报 -func StrategyFixedTime(hour, min, sec int) ReporterStrategy { - return func(reporter *Reporter) { - now := time.Now() - current := now.Unix() - next := time.Date(now.Year(), now.Month(), now.Day(), hour, min, sec, 0, now.Location()) - target := next.Unix() - if current >= target { - next = next.AddDate(0, 0, 1) - target = next.Unix() - } - reporter.ticker.Loop(fmt.Sprintf("ReportStrategyFixedTime_%d_%d_%d", hour, min, sec), time.Duration(target-current)*time.Second, 24*time.Hour, -1, func() { - if err := reporter.Report(); err != nil && reporter.errorHandle != nil { - reporter.errorHandle(reporter, err) - } - }) - } -}