diff --git a/internal/db/models/nameservers/ns_node_dao.go b/internal/db/models/nameservers/ns_node_dao.go index 269da324..e42eab2f 100644 --- a/internal/db/models/nameservers/ns_node_dao.go +++ b/internal/db/models/nameservers/ns_node_dao.go @@ -75,6 +75,15 @@ func (this *NSNodeDAO) FindEnabledNSNode(tx *dbs.Tx, id int64) (*NSNode, error) return result.(*NSNode), err } +// FindEnabledNSNodeName 查找节点名称 +func (this *NSNodeDAO) FindEnabledNSNodeName(tx *dbs.Tx, nodeId int64) (string, error) { + return this.Query(tx). + Pk(nodeId). + State(NSNodeStateEnabled). + Result("name"). + FindStringCol("") +} + // FindAllEnabledNodesWithClusterId 查找一个集群下的所有节点 func (this *NSNodeDAO) FindAllEnabledNodesWithClusterId(tx *dbs.Tx, clusterId int64) (result []*NSNode, err error) { _, err = this.Query(tx). @@ -94,6 +103,15 @@ func (this *NSNodeDAO) CountAllEnabledNodes(tx *dbs.Tx) (int64, error) { Count() } +// CountAllOfflineNodes 计算离线节点数量 +func (this *NSNodeDAO) CountAllOfflineNodes(tx *dbs.Tx) (int64, error) { + return this.Query(tx). + State(NSNodeStateEnabled). + Where("(status IS NULL OR JSON_EXTRACT(status, '$.updatedAt') *NSRecordHourlyStat + for _, one := range ones { + m[one.(*NSRecordHourlyStat).Hour] = one.(*NSRecordHourlyStat) + } + hours, err := utils.RangeHours(hourFrom, hourTo) + if err != nil { + return nil, err + } + for _, hour := range hours { + stat, ok := m[hour] + if ok { + result = append(result, stat) + } else { + result = append(result, &NSRecordHourlyStat{ + Hour: hour, + }) + } + } + return +} + +// FindDailyStats 按天统计 +func (this *NSRecordHourlyStatDAO) FindDailyStats(tx *dbs.Tx, dayFrom string, dayTo string) (result []*NSRecordHourlyStat, err error) { + ones, err := this.Query(tx). + Result("day", "SUM(countRequests) AS countRequests", "SUM(bytes) AS bytes"). + Between("day", dayFrom, dayTo). + Group("day"). + FindAll() + if err != nil { + return nil, err + } + var m = map[string]*NSRecordHourlyStat{} // day => *NSRecordHourlyStat + for _, one := range ones { + m[one.(*NSRecordHourlyStat).Day] = one.(*NSRecordHourlyStat) + } + days, err := utils.RangeDays(dayFrom, dayTo) + if err != nil { + return nil, err + } + for _, day := range days { + stat, ok := m[day] + if ok { + result = append(result, stat) + } else { + result = append(result, &NSRecordHourlyStat{ + Day: day, + }) + } + } + return +} + +// ListTopNodes 节点排行 +func (this *NSRecordHourlyStatDAO) ListTopNodes(tx *dbs.Tx, hourFrom string, hourTo string, size int64) (result []*NSRecordHourlyStat, err error) { + _, err = this.Query(tx). + Result("MIN(clusterId) AS clusterId", "nodeId", "SUM(countRequests) AS countRequests", "SUM(bytes) AS bytes"). + Between("hour", hourFrom, hourTo). + Group("nodeId"). + Limit(size). + Slice(&result). + FindAll() + return +} + +// ListTopDomains 域名排行 +func (this *NSRecordHourlyStatDAO) ListTopDomains(tx *dbs.Tx, hourFrom string, hourTo string, size int64) (result []*NSRecordHourlyStat, err error) { + _, err = this.Query(tx). + Result("domainId", "SUM(countRequests) AS countRequests", "SUM(bytes) AS bytes"). + Between("hour", hourFrom, hourTo). + Group("domainId"). + Limit(size). + Slice(&result). + FindAll() + return +} + +// Clean 清理历史数据 +func (this *NSRecordHourlyStatDAO) Clean(tx *dbs.Tx, days int) error { + var hour = timeutil.Format("Ymd00", time.Now().AddDate(0, 0, -days)) + _, err := this.Query(tx). + Lt("hour", hour). + Delete() + return err +} diff --git a/internal/db/models/nameservers/ns_record_hourly_stat_dao_test.go b/internal/db/models/nameservers/ns_record_hourly_stat_dao_test.go new file mode 100644 index 00000000..e29fe962 --- /dev/null +++ b/internal/db/models/nameservers/ns_record_hourly_stat_dao_test.go @@ -0,0 +1,6 @@ +package nameservers + +import ( + _ "github.com/go-sql-driver/mysql" + _ "github.com/iwind/TeaGo/bootstrap" +) diff --git a/internal/db/models/nameservers/ns_record_hourly_stat_model.go b/internal/db/models/nameservers/ns_record_hourly_stat_model.go new file mode 100644 index 00000000..d1053197 --- /dev/null +++ b/internal/db/models/nameservers/ns_record_hourly_stat_model.go @@ -0,0 +1,30 @@ +package nameservers + +// NSRecordHourlyStat NS记录统计 +type NSRecordHourlyStat struct { + Id uint64 `field:"id"` // ID + ClusterId uint32 `field:"clusterId"` // 集群ID + NodeId uint32 `field:"nodeId"` // 节点ID + DomainId uint32 `field:"domainId"` // 域名ID + RecordId uint64 `field:"recordId"` // 记录ID + Day string `field:"day"` // YYYYMMDD + Hour string `field:"hour"` // YYYYMMDDHH + CountRequests uint32 `field:"countRequests"` // 请求数 + Bytes uint64 `field:"bytes"` // 流量 +} + +type NSRecordHourlyStatOperator struct { + Id interface{} // ID + ClusterId interface{} // 集群ID + NodeId interface{} // 节点ID + DomainId interface{} // 域名ID + RecordId interface{} // 记录ID + Day interface{} // YYYYMMDD + Hour interface{} // YYYYMMDDHH + CountRequests interface{} // 请求数 + Bytes interface{} // 流量 +} + +func NewNSRecordHourlyStatOperator() *NSRecordHourlyStatOperator { + return &NSRecordHourlyStatOperator{} +} diff --git a/internal/db/models/nameservers/ns_record_hourly_stat_model_ext.go b/internal/db/models/nameservers/ns_record_hourly_stat_model_ext.go new file mode 100644 index 00000000..e0f8e7e2 --- /dev/null +++ b/internal/db/models/nameservers/ns_record_hourly_stat_model_ext.go @@ -0,0 +1 @@ +package nameservers diff --git a/internal/db/models/node_value_dao.go b/internal/db/models/node_value_dao.go index 56b8cc72..0bab8478 100644 --- a/internal/db/models/node_value_dao.go +++ b/internal/db/models/node_value_dao.go @@ -140,6 +140,31 @@ func (this *NodeValueDAO) ListValuesForUserNodes(tx *dbs.Tx, item string, key st return } + +// ListValuesForNSNodes 列出用户节点相关的平均数据 +func (this *NodeValueDAO) ListValuesForNSNodes(tx *dbs.Tx, item string, key string, timeRange nodeconfigs.NodeValueRange) (result []*NodeValue, err error) { + query := this.Query(tx). + Attr("role", "dns"). + Attr("item", item). + Result("AVG(JSON_EXTRACT(value, '$." + key + "')) AS value, MIN(createdAt) AS createdAt") + + switch timeRange { + // TODO 支持更多的时间范围 + case nodeconfigs.NodeValueRangeMinute: + fromMinute := timeutil.FormatTime("YmdHi", time.Now().Unix()-3600) // 一个小时之前的 + query.Gte("minute", fromMinute) + query.Result("minute") + query.Group("minute") + default: + err = errors.New("invalid 'range' value: '" + timeRange + "'") + return + } + + _, err = query.Slice(&result). + FindAll() + return +} + // SumValues 计算某项参数值 func (this *NodeValueDAO) SumValues(tx *dbs.Tx, role string, nodeId int64, item string, param string, method nodeconfigs.NodeValueSumMethod, duration int32, durationUnit nodeconfigs.NodeValueDurationUnit) (float64, error) { if duration <= 0 { diff --git a/internal/db/models/user_node_dao.go b/internal/db/models/user_node_dao.go index 193e808d..9a98b699 100644 --- a/internal/db/models/user_node_dao.go +++ b/internal/db/models/user_node_dao.go @@ -270,6 +270,6 @@ func (this *UserNodeDAO) CountAllLowerVersionNodes(tx *dbs.Tx, version string) ( func (this *UserNodeDAO) CountOfflineNodes(tx *dbs.Tx) (int64, error) { return this.Query(tx). State(UserNodeStateEnabled). - Where("status IS NULL OR JSON_EXTRACT(status, '$.updatedAt')