租户项目粒度某类资源top数量 (#499)

* 租户项目粒度某类资源top数量

* 租户项目粒度某类资源top数量

* resname->rescate

Co-authored-by: alickliming <alickliming@didi.global.com>
This commit is contained in:
alick-liming 2021-01-11 12:58:32 +08:00 committed by GitHub
parent f9cfcaeabe
commit a9cf307cbf
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 208 additions and 0 deletions

View File

@ -77,3 +77,34 @@ func ResIdsGetByNodeIds(nids []int64) ([]int64, error) {
err := DB["rdb"].Table(new(NodeResource)).In("node_id", nids).Select("res_id").Find(&ids)
return ids, err
}
// ResCountGetByNodeIdsAndWhere 根据叶子节点和Where条件获取资源数量表
func ResCountGetByNodeIdsAndCate(nids []int64, cate string) (int, error) {
if len(nids) == 0 {
return 0, nil
}
var nodeRess []NodeResource
err := DB["rdb"].Table(new(NodeResource)).In("node_id", nids).Find(&nodeRess)
if err != nil {
return 0, err
}
cnt := 0
for _, res := range nodeRess {
res, err := ResourceGet("id=?", res.ResId)
if err != nil {
return 0, err
}
if res == nil {
continue
}
if res.Cate == cate {
cnt++
}
}
return cnt, nil
}

View File

@ -87,6 +87,9 @@ func Config(r *gin.Engine) {
rootLogin.GET("/sso/clients/:clientId", ssoClientGet)
rootLogin.PUT("/sso/clients/:clientId", ssoClientPut)
rootLogin.DELETE("/sso/clients/:clientId", ssoClientDel)
rootLogin.GET("/resources/tenant-rank", tenantResourcesCountRank)
rootLogin.GET("/resources/project-rank", projectResourcesCountRank)
}
userLogin := r.Group("/api/rdb").Use(shouldBeLogin())

View File

@ -2,6 +2,7 @@ package http
import (
"fmt"
"sort"
"strings"
"github.com/gin-gonic/gin"
@ -570,3 +571,176 @@ func renderAllResourcesCountByCate(c *gin.Context) {
renderData(c, list, nil)
}
// 租户项目粒度资源排行
type resourceRank struct {
Name string `json:"name"`
Count int `json:"count"`
}
func tenantResourcesCountRank(c *gin.Context) {
resCate := queryStr(c, "resource_cate", "virtual")
top := queryInt(c, "top", 0)
if top < 0 {
dangerous(fmt.Errorf("param top < 0"))
}
tenantNode, err := models.NodeGets("cate=?", "tenant")
dangerous(err)
tenantNodeLen := len(tenantNode)
tenantNodeName := make(map[string]string, tenantNodeLen)
for _, node := range tenantNode {
if node.Ident != "" && node.Name != "" {
tenantNodeName[node.Ident] = node.Name
}
}
ress, err := models.ResourceGets("cate=?", resCate)
dangerous(err)
resMap := make(map[string]int, 50)
for _, res := range ress {
tenant := res.Tenant
if tenant != "" {
if _, ok := resMap[tenant]; !ok {
resMap[tenant] = 0
}
resMap[tenant]++
}
}
var ret []*resourceRank
for k, v := range resMap {
tR := new(resourceRank)
name, ok := tenantNodeName[k]
if !ok {
name = k
}
tR.Name = name
tR.Count = v
ret = append(ret, tR)
}
retLen := len(ret)
if retLen > 0 {
sort.Slice(ret, func(i, j int) bool { return ret[i].Count > ret[j].Count })
}
if top == 0 {
renderData(c, ret, nil)
return
}
if retLen > top {
renderData(c, ret[:top], nil)
return
}
renderData(c, ret, nil)
}
func projectResourcesCountRank(c *gin.Context) {
resCate := queryStr(c, "resource_cate", "virtual")
top := queryInt(c, "top", 0)
if top < 0 {
dangerous(fmt.Errorf("param top < 0"))
}
// 获取全部project
projectNodes, err := models.NodeGets("cate=?", "project")
dangerous(err)
projectNodesLen := len(projectNodes)
workerNum := 50
if projectNodesLen < workerNum {
workerNum = projectNodesLen
}
worker := make(chan struct{}, workerNum) // 控制 goroutine 并发数
dataChan := make(chan *resourceRank, projectNodesLen)
done := make(chan struct{}, 1)
resp := make([]*resourceRank, 0)
go func() {
defer func() { done <- struct{}{} }()
for d := range dataChan {
resp = append(resp, d)
}
}()
for _, pN := range projectNodes {
worker <- struct{}{}
go singleProjectResCount(pN.Id, resCate, worker,
dataChan)
}
// 等待所有 goroutine 执行完成
for i := 0; i < workerNum; i++ {
worker <- struct{}{}
}
close(dataChan)
// 等待所有 dataChan 被消费完
<-done
//整理resp中数据
respLen := len(resp)
if respLen > 0 {
sort.Slice(resp, func(i, j int) bool { return resp[i].Count > resp[j].Count })
}
if top == 0 {
renderData(c, resp, nil)
return
}
if respLen > top {
renderData(c, resp[:top], nil)
return
}
renderData(c, resp, nil)
}
func singleProjectResCount(id int64, resCate string, worker chan struct{}, dataChan chan *resourceRank) {
defer func() {
<-worker
}()
node, err := models.NodeGet("id=?", id)
if err != nil {
logger.Error(err)
return
}
if node == nil {
logger.Errorf("node id %d is nil", id)
return
}
leafIds, err := node.LeafIds()
if err != nil {
logger.Error(err)
return
}
cnt, err := models.ResCountGetByNodeIdsAndCate(leafIds, resCate)
if err != nil {
logger.Error(err)
return
}
data := new(resourceRank)
nodeName := node.Name
if nodeName != "" {
data.Name = nodeName
} else {
data.Name = node.Ident
}
data.Count = cnt
dataChan <- data
}