mirror of
https://hubproxy.babadafafafafa.cn/https://github.com/yunionio/cloudpods.git
synced 2026-09-20 08:03:53 +08:00
188 lines
5.5 KiB
Go
188 lines
5.5 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 monitor
|
||
|
||
import (
|
||
"strconv"
|
||
"strings"
|
||
"time"
|
||
|
||
"yunion.io/x/jsonutils"
|
||
"yunion.io/x/pkg/errors"
|
||
|
||
api "yunion.io/x/onecloud/pkg/apis/monitor"
|
||
"yunion.io/x/onecloud/pkg/mcclient/modules/monitor"
|
||
)
|
||
|
||
type ResourceMetricsOptions struct {
|
||
RES_TYPE string `help:"resource type: host or guest" choices:"host|guest"`
|
||
ResIds []string `help:"resource IDs" json:"res_ids" nargs:"+"`
|
||
StartTime string `help:"start time (RFC3339). e.g.: 2023-12-06T21:54:42Z" json:"-"`
|
||
EndTime string `help:"end time (RFC3339). e.g.: 2023-12-18T21:54:42Z" json:"-"`
|
||
Interval string `help:"query interval. e.g.: 5m, 1h" json:"interval"`
|
||
}
|
||
|
||
func (o *ResourceMetricsOptions) GetInput() (*api.ResourceMetricsQueryInput, error) {
|
||
input := &api.ResourceMetricsQueryInput{
|
||
ResType: o.RES_TYPE,
|
||
ResIds: o.ResIds,
|
||
Interval: o.Interval,
|
||
}
|
||
if o.StartTime != "" {
|
||
t, err := time.Parse(time.RFC3339, o.StartTime)
|
||
if err != nil {
|
||
return nil, errors.Wrapf(err, "invalid start_time %q", o.StartTime)
|
||
}
|
||
input.StartTime = t
|
||
}
|
||
if o.EndTime != "" {
|
||
t, err := time.Parse(time.RFC3339, o.EndTime)
|
||
if err != nil {
|
||
return nil, errors.Wrapf(err, "invalid end_time %q", o.EndTime)
|
||
}
|
||
input.EndTime = t
|
||
}
|
||
return input, nil
|
||
}
|
||
|
||
type MeasurementsQueryOptions struct {
|
||
Scope string `json:"scope" mcp:"true"`
|
||
ProjectDomainId string `json:"project_domin_id" mcp:"true"`
|
||
ProjectId string `json:"project_id" mcp:"true"`
|
||
}
|
||
|
||
func (o MeasurementsQueryOptions) Params() (jsonutils.JSONObject, error) {
|
||
return jsonutils.Marshal(o), nil
|
||
}
|
||
|
||
func (o MeasurementsQueryOptions) Property() string {
|
||
return "measurements"
|
||
}
|
||
|
||
type DatabasesQueryOptions struct{}
|
||
|
||
func (o DatabasesQueryOptions) Params() (jsonutils.JSONObject, error) {
|
||
return nil, nil
|
||
}
|
||
|
||
func (o DatabasesQueryOptions) Property() string {
|
||
return "databases"
|
||
}
|
||
|
||
type MetricQueryOptions struct {
|
||
_ struct{} `mcp-desc:"查询云平台监控指标时序(unifiedmonitor,非 QEMU)。必填 MEASUREMENT+FIELD;过滤用 from/to/interval/tags。不要用 climc_server_monitor"`
|
||
|
||
MeasurementsQueryOptions
|
||
|
||
MEASUREMENT string `help:"metric measurement. e.g.: cpu, vm_cpu, vm_mem, disk..."`
|
||
FIELD string `help:"metric field. e.g.: usage_active, free..."`
|
||
|
||
Interval string `help:"metric interval. e.g.: 5m, 1h" mcp:"true"`
|
||
From string `help:"start time(RFC3339 format). e.g.: 2023-12-06T21:54:42.123Z" mcp:"true"`
|
||
To string `help:"end time(RFC3339 format). e.g.: 2023-12-18T21:54:42.123Z" mcp:"true"`
|
||
Tags []string `help:"filter tags. e.g.: vm_name=vm1" mcp:"true"`
|
||
GroupBy []string `help:"group by tag" mcp:"true"`
|
||
UseMean bool `help:"calcuate mean result for field" mcp:"true"`
|
||
SkipCheckSeries bool `help:"skip checking series: not fetch extra tags from region service" mcp:"true"`
|
||
Reducer string `help:"series result reducer. e.g.: sum, percentile(95)" mcp:"true"`
|
||
}
|
||
|
||
func (o MetricQueryOptions) GetQueryInput() (*api.MetricQueryInput, error) {
|
||
input := monitor.NewMetricQueryInput(o.MEASUREMENT)
|
||
input.Interval(o.Interval)
|
||
if o.SkipCheckSeries {
|
||
input.SkipCheckSeries(true)
|
||
}
|
||
input.Scope(o.Scope)
|
||
|
||
// parse time
|
||
if o.From != "" {
|
||
fromTime, err := time.Parse(time.RFC3339, o.From)
|
||
if err != nil {
|
||
return nil, errors.Wrapf(err, "invalid from time: %q", o.From)
|
||
}
|
||
input.From(fromTime)
|
||
}
|
||
if o.To != "" {
|
||
toTime, err := time.Parse(time.RFC3339, o.To)
|
||
if err != nil {
|
||
return nil, errors.Wrapf(err, "invalid to time: %q", o.To)
|
||
}
|
||
input.To(toTime)
|
||
}
|
||
|
||
sel := input.Selects().Select(o.FIELD)
|
||
if o.UseMean {
|
||
sel.MEAN()
|
||
}
|
||
|
||
where := input.Where()
|
||
for _, tag := range o.Tags {
|
||
if strings.Contains(tag, "=") {
|
||
info := strings.Split(tag, "=")
|
||
if len(info) == 2 {
|
||
where.Equal(info[0], info[1])
|
||
} else {
|
||
return nil, errors.Errorf("invalid tag: %q, len: %d", tag, len(info))
|
||
}
|
||
} else {
|
||
return nil, errors.Errorf("invalid tag: %q", tag)
|
||
}
|
||
}
|
||
|
||
groupBy := input.GroupBy()
|
||
for _, tag := range o.GroupBy {
|
||
groupBy.TAG(tag)
|
||
}
|
||
|
||
if o.Reducer != "" {
|
||
r, err := o.parseReducer(o.Reducer)
|
||
if err != nil {
|
||
return nil, errors.Wrapf(err, "invalid reducer: %q", o.Reducer)
|
||
}
|
||
input.Reducer(r.Type, r.Params)
|
||
}
|
||
|
||
return input.ToQueryData(), nil
|
||
}
|
||
|
||
func (o MetricQueryOptions) parseReducer(reducer string) (*api.Condition, error) {
|
||
if reducer == "" {
|
||
return nil, errors.Errorf("invalid reducer %q", reducer)
|
||
}
|
||
parts := strings.Split(reducer, "(")
|
||
if len(parts) < 1 {
|
||
return nil, errors.Errorf("invalid reducer %q", reducer)
|
||
}
|
||
rType := parts[0]
|
||
cond := &api.Condition{
|
||
Type: rType,
|
||
}
|
||
if len(parts) > 1 {
|
||
params := []float64{}
|
||
paramStr := parts[1]
|
||
paramsStr := strings.Split(strings.TrimSuffix(paramStr, ")"), ",")
|
||
for _, param := range paramsStr {
|
||
f, err := strconv.ParseFloat(strings.ReplaceAll(param, " ", ""), 64)
|
||
if err != nil {
|
||
return nil, errors.Wrapf(err, "invalid reducer param %q", param)
|
||
}
|
||
params = append(params, f)
|
||
}
|
||
cond.Params = params
|
||
}
|
||
return cond, nil
|
||
}
|