Files
cloudpods/pkg/mcclient/options/monitor/unifiedmonitor.go

188 lines
5.5 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

// 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
}