mirror of
https://github.com/yunionio/cloudpods.git
synced 2026-05-31 13:00:41 +08:00
226 lines
6.4 KiB
Go
226 lines
6.4 KiB
Go
// Copyright 2019 Yunion
|
|
//
|
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
// you may not use this file except in compliance with the License.
|
|
// You may obtain a copy of the License at
|
|
//
|
|
// http://www.apache.org/licenses/LICENSE-2.0
|
|
//
|
|
// Unless required by applicable law or agreed to in writing, software
|
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
// See the License for the specific language governing permissions and
|
|
// limitations under the License.
|
|
|
|
package apsara
|
|
|
|
import (
|
|
"strconv"
|
|
"time"
|
|
|
|
alierr "github.com/aliyun/alibaba-cloud-sdk-go/sdk/errors"
|
|
|
|
"yunion.io/x/jsonutils"
|
|
"yunion.io/x/pkg/errors"
|
|
)
|
|
|
|
const (
|
|
APSARA_API_VERSION_METRICS = "2019-01-01"
|
|
)
|
|
|
|
func (r *SRegion) metricsRequest(action string, params map[string]string) (jsonutils.JSONObject, error) {
|
|
client, err := r.getSdkClient()
|
|
if err != nil {
|
|
return nil, errors.Wrap(err, "r.getSdkClient")
|
|
}
|
|
domain := r.client.getDomain(APSARA_PRODUCT_METRICS)
|
|
return r.productRequest(client, APSARA_PRODUCT_METRICS, domain, APSARA_API_VERSION_METRICS, action, params, r.client.debug)
|
|
}
|
|
|
|
type SResourceLabel struct {
|
|
Name string `json:"name"`
|
|
Value string `json:"value"`
|
|
}
|
|
|
|
type SResource struct {
|
|
Description string `json:"Description"`
|
|
Labels string `json:"Labels"`
|
|
Namespace string `json:"Namespace"`
|
|
}
|
|
|
|
func (r *SRegion) DescribeProjectMeta(limit, offset int) (int, []SResource, error) {
|
|
params := make(map[string]string)
|
|
if limit <= 0 {
|
|
limit = 30
|
|
}
|
|
params["PageSize"] = strconv.FormatInt(int64(limit), 10)
|
|
if offset > 0 {
|
|
pageNum := (offset / limit) + 1
|
|
params["PageNumber"] = strconv.FormatInt(int64(pageNum), 10)
|
|
}
|
|
body, err := r.metricsRequest("DescribeProjectMeta", params)
|
|
if err != nil {
|
|
return 0, nil, errors.Wrap(err, "r.metricsRequest DescribeProjectMeta")
|
|
}
|
|
total, _ := body.Int("Total")
|
|
res := make([]SResource, 0)
|
|
err = body.Unmarshal(&res, "Resources", "Resource")
|
|
if err != nil {
|
|
return 0, nil, errors.Wrap(err, "body.Unmarshal Resources Resource")
|
|
}
|
|
return int(total), res, nil
|
|
}
|
|
|
|
func (r *SRegion) FetchNamespaces() ([]SResource, error) {
|
|
resources := make([]SResource, 0)
|
|
total := -1
|
|
for total < 0 || len(resources) < total {
|
|
ntotal, res, err := r.DescribeProjectMeta(1000, len(resources))
|
|
if err != nil {
|
|
return nil, errors.Wrap(err, "r.DescribeProjectMeta")
|
|
}
|
|
if len(res) == 0 {
|
|
break
|
|
}
|
|
resources = append(resources, res...)
|
|
total = ntotal
|
|
}
|
|
return resources, nil
|
|
}
|
|
|
|
type SMetricMeta struct {
|
|
Description string `json:"Description"`
|
|
MetricName string `json:"MetricName"`
|
|
Statistics string `json:"Statistics"`
|
|
Labels string `json:"Labels"`
|
|
Dimensions string `json:"Dimensions"`
|
|
Namespace string `json:"Namespace"`
|
|
Periods string `json:"Periods"`
|
|
Unit string `json:"Unit"`
|
|
}
|
|
|
|
func (r *SRegion) DescribeMetricMetaList(ns string, limit, offset int) (int, []SMetricMeta, error) {
|
|
params := make(map[string]string)
|
|
if limit <= 0 {
|
|
limit = 30
|
|
}
|
|
params["Namespace"] = ns
|
|
params["PageSize"] = strconv.FormatInt(int64(limit), 10)
|
|
if offset > 0 {
|
|
pageNum := (offset / limit) + 1
|
|
params["PageNumber"] = strconv.FormatInt(int64(pageNum), 10)
|
|
}
|
|
body, err := r.metricsRequest("DescribeMetricMetaList", params)
|
|
if err != nil {
|
|
return 0, nil, errors.Wrap(err, "r.metricsRequest DescribeMetricMetaList")
|
|
}
|
|
total, _ := body.Int("TotalCount")
|
|
res := make([]SMetricMeta, 0)
|
|
err = body.Unmarshal(&res, "Resources", "Resource")
|
|
if err != nil {
|
|
return 0, nil, errors.Wrap(err, "body.Unmarshal Resources Resource")
|
|
}
|
|
return int(total), res, nil
|
|
}
|
|
|
|
func (r *SRegion) FetchMetrics(ns string) ([]SMetricMeta, error) {
|
|
metrics := make([]SMetricMeta, 0)
|
|
total := -1
|
|
for total < 0 || len(metrics) < total {
|
|
ntotal, res, err := r.DescribeMetricMetaList(ns, 1000, len(metrics))
|
|
if err != nil {
|
|
return nil, errors.Wrap(err, "r.DescribeMetricMetaList")
|
|
}
|
|
if len(res) == 0 {
|
|
break
|
|
}
|
|
metrics = append(metrics, res...)
|
|
total = ntotal
|
|
}
|
|
return metrics, nil
|
|
}
|
|
|
|
func (r *SRegion) DescribeMetricList(department, name string, ns string, since time.Time, until time.Time, nextToken string) ([]jsonutils.JSONObject, string, error) {
|
|
params := make(map[string]string)
|
|
params["MetricName"] = name
|
|
params["Namespace"] = ns
|
|
params["Period"] = "60"
|
|
params["Length"] = "2000"
|
|
if len(nextToken) > 0 {
|
|
params["NextToken"] = nextToken
|
|
}
|
|
if !since.IsZero() {
|
|
params["StartTime"] = strconv.FormatInt(since.Unix()*1000, 10)
|
|
}
|
|
if !until.IsZero() {
|
|
params["EndTime"] = strconv.FormatInt(until.Unix()*1000, 10)
|
|
}
|
|
if len(department) > 0 {
|
|
params["Department"] = department
|
|
}
|
|
body, err := r.metricsRequest("DescribeMetricList", params)
|
|
if err != nil {
|
|
return nil, "", errors.Wrap(err, "region.MetricRequest")
|
|
}
|
|
nToken, _ := body.GetString("NextToken")
|
|
dataStr, _ := body.GetString("Datapoints")
|
|
if len(dataStr) == 0 {
|
|
return nil, "", nil
|
|
}
|
|
dataJson, err := jsonutils.ParseString(dataStr)
|
|
if err != nil {
|
|
return nil, "", errors.Wrap(err, "jsonutils.ParseString")
|
|
}
|
|
dataArray, err := dataJson.GetArray()
|
|
if err != nil {
|
|
return nil, "", errors.Wrap(err, "dataJson.GetArray")
|
|
}
|
|
return dataArray, nToken, nil
|
|
}
|
|
|
|
func (r *SRegion) fetchMetricData(department string, name string, ns string, since time.Time, until time.Time) ([]jsonutils.JSONObject, error) {
|
|
data := make([]jsonutils.JSONObject, 0)
|
|
nextToken := ""
|
|
for {
|
|
datArray, next, err := r.DescribeMetricList(department, name, ns, since, until, nextToken)
|
|
if err != nil {
|
|
return nil, errors.Wrap(err, "r.DescribeMetricList")
|
|
}
|
|
data = append(data, datArray...)
|
|
if len(next) == 0 {
|
|
break
|
|
}
|
|
nextToken = next
|
|
}
|
|
return data, nil
|
|
}
|
|
|
|
func (r *SRegion) FetchMetricData(name string, ns string, since time.Time, until time.Time) ([]jsonutils.JSONObject, error) {
|
|
data := make([]jsonutils.JSONObject, 0)
|
|
part, err := r.fetchMetricData("1", name, ns, since, until)
|
|
if err == nil {
|
|
return part, nil
|
|
}
|
|
if err != nil {
|
|
if e, ok := errors.Cause(err).(*alierr.ServerError); ok && e.ErrorCode() != "NoPermission" {
|
|
return nil, errors.Wrapf(err, "fetchMetricData")
|
|
}
|
|
}
|
|
|
|
orgs, err := r.GetClient().GetOrganizationList()
|
|
if err != nil {
|
|
return nil, errors.Wrapf(err, "GetOrganizationList")
|
|
}
|
|
|
|
for i := range orgs {
|
|
if orgs[i].ParentId == "1" {
|
|
part, err := r.fetchMetricData(orgs[i].Id, name, ns, since, until)
|
|
if err != nil {
|
|
return nil, errors.Wrapf(err, "fetchMetricData")
|
|
}
|
|
data = append(data, part...)
|
|
}
|
|
}
|
|
return data, nil
|
|
}
|