| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185 |
- // 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"`
- ProjectDomainId string `json:"project_domin_id"`
- ProjectId string `json:"project_id"`
- }
- 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 {
- 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"`
- From string `help:"start time(RFC3339 format). e.g.: 2023-12-06T21:54:42.123Z"`
- To string `help:"end time(RFC3339 format). e.g.: 2023-12-18T21:54:42.123Z"`
- Tags []string `help:"filter tags. e.g.: vm_name=vm1"`
- GroupBy []string `help:"group by tag"`
- UseMean bool `help:"calcuate mean result for field"`
- SkipCheckSeries bool `help:"skip checking series: not fetch extra tags from region service"`
- Reducer string `help:"series result reducer. e.g.: sum, percentile(95)"`
- }
- 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
- }
|