From 590cba97bbbcb07801c23d7c9ea57811dbf43c22 Mon Sep 17 00:00:00 2001 From: Zexi Li Date: Fri, 8 Dec 2023 01:19:01 +0800 Subject: [PATCH] feat(climc): add monitor-unifiedmonitor-query command --- cmd/climc/shell/monitor/unifiedmonitor.go | 18 ++++- pkg/apis/monitor/types_test.go | 15 ---- .../modules/monitor/mod_unifiedmonitor.go | 5 +- pkg/mcclient/options/monitor/simplequery.go | 4 +- .../options/monitor/unifiedmonitor.go | 77 ++++++++++++++++++- pkg/monitor/models/unifiedmonitor.go | 2 +- 6 files changed, 100 insertions(+), 21 deletions(-) delete mode 100644 pkg/apis/monitor/types_test.go diff --git a/cmd/climc/shell/monitor/unifiedmonitor.go b/cmd/climc/shell/monitor/unifiedmonitor.go index f8174d5295..5d8b26b9d1 100644 --- a/cmd/climc/shell/monitor/unifiedmonitor.go +++ b/cmd/climc/shell/monitor/unifiedmonitor.go @@ -15,7 +15,10 @@ package monitor import ( + "yunion.io/x/pkg/errors" + "yunion.io/x/onecloud/cmd/climc/shell" + "yunion.io/x/onecloud/pkg/mcclient" "yunion.io/x/onecloud/pkg/mcclient/modules/monitor" options "yunion.io/x/onecloud/pkg/mcclient/options/monitor" ) @@ -24,5 +27,18 @@ func init() { cmd := shell.NewResourceCmd(monitor.UnifiedMonitorManager).SetPrefix("monitor") cmd.Show(&options.SimpleQueryOptions{}) cmd.GetProperty(&options.MeasurementsQueryOptions{}) - cmd.GetProperty(&options.DatabasesQueryOptions{}) + // cmd.GetProperty(&options.DatabasesQueryOptions{}) + + R(new(options.MetricQueryOptions), "monitor-unifiedmonitor-query", "Perform metrics query", func(s *mcclient.ClientSession, opts *options.MetricQueryOptions) error { + input, err := opts.GetQueryInput() + if err != nil { + return err + } + resp, err := monitor.UnifiedMonitorManager.PerformQuery(s, input) + if err != nil { + return errors.Wrap(err, "PerformQuery") + } + printObject(resp) + return nil + }) } diff --git a/pkg/apis/monitor/types_test.go b/pkg/apis/monitor/types_test.go deleted file mode 100644 index 88cb500ff6..0000000000 --- a/pkg/apis/monitor/types_test.go +++ /dev/null @@ -1,15 +0,0 @@ -package monitor - -import ( - "testing" - - "yunion.io/x/jsonutils" - "yunion.io/x/log" -) - -func TestMetricQueryInput_AddMetric(t *testing.T) { - q := NewMetricQuery("cpu") - q.Select("usage_active").MEAN() - q.Select("usage_active_per_core") - log.Infof("%s", jsonutils.Marshal(q)) -} diff --git a/pkg/mcclient/modules/monitor/mod_unifiedmonitor.go b/pkg/mcclient/modules/monitor/mod_unifiedmonitor.go index 3fd461df33..ceae683a7b 100644 --- a/pkg/mcclient/modules/monitor/mod_unifiedmonitor.go +++ b/pkg/mcclient/modules/monitor/mod_unifiedmonitor.go @@ -15,6 +15,8 @@ package monitor import ( + "yunion.io/x/jsonutils" + "yunion.io/x/onecloud/pkg/apis/monitor" "yunion.io/x/onecloud/pkg/mcclient" "yunion.io/x/onecloud/pkg/mcclient/modulebase" @@ -47,5 +49,6 @@ func NewUnifiedMonitorManager() *SUnifiedMonitorManager { } } -func (m *SUnifiedMonitorManager) PerformQuery(s *mcclient.ClientSession, input *monitor.MetricQueryInput) { +func (m *SUnifiedMonitorManager) PerformQuery(s *mcclient.ClientSession, input *monitor.MetricQueryInput) (jsonutils.JSONObject, error) { + return m.PerformClassAction(s, "query", jsonutils.Marshal(input)) } diff --git a/pkg/mcclient/options/monitor/simplequery.go b/pkg/mcclient/options/monitor/simplequery.go index 2e4b10f404..027b237435 100644 --- a/pkg/mcclient/options/monitor/simplequery.go +++ b/pkg/mcclient/options/monitor/simplequery.go @@ -24,8 +24,8 @@ type SimpleQueryOptions struct { Id string `json:"id"` Database string `json:"database"` MetricName string `json:"metric_name"` - StartTime string `json:"start_time"` - EndTime string `json:"end_time"` + StartTime string `json:"start_time" help:"e.g.: 2023-12-06T21:54:42.123Z"` + EndTime string `json:"end_time" help:"e.g.: 2023-12-18T21:54:42.123Z"` Tags []string `json:"tags"` } diff --git a/pkg/mcclient/options/monitor/unifiedmonitor.go b/pkg/mcclient/options/monitor/unifiedmonitor.go index 9cb232a67c..00f7e55a84 100644 --- a/pkg/mcclient/options/monitor/unifiedmonitor.go +++ b/pkg/mcclient/options/monitor/unifiedmonitor.go @@ -14,7 +14,16 @@ package monitor -import "yunion.io/x/jsonutils" +import ( + "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 MeasurementsQueryOptions struct { Scope string `json:"scope"` @@ -39,3 +48,69 @@ func (o DatabasesQueryOptions) Params() (jsonutils.JSONObject, error) { 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"` +} + +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) + } + + return input.ToQueryData(), nil +} diff --git a/pkg/monitor/models/unifiedmonitor.go b/pkg/monitor/models/unifiedmonitor.go index 3ec9372c2b..6d2bb3e2af 100644 --- a/pkg/monitor/models/unifiedmonitor.go +++ b/pkg/monitor/models/unifiedmonitor.go @@ -554,7 +554,7 @@ func (self *SUnifiedMonitorManager) GetPropertySimpleQuery(ctx context.Context, queryData := data.ToQueryData() dbRtn, err := self.performQuery(ctx, userCred, queryData) if err != nil { - return nil, errors.Wrapf(err, "performQuery with data: %s", queryData) + return nil, errors.Wrapf(err, "performQuery with data: %s", jsonutils.Marshal(queryData)) } ret := []monitor.SimpleQueryOutput{}