From 52fa73a631173bc32b276608794b1edde28519c9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=B0=8F=E6=9E=97=E4=BB=94?= Date: Wed, 21 Sep 2022 15:50:47 +0800 Subject: [PATCH] support simple query --- cmd/climc/shell/monitor/unifiedmonitor.go | 26 +++++++ pkg/apis/monitor/unifiedmonitor_const.go | 24 ++++++ pkg/mcclient/options/monitor/simplequery.go | 52 +++++++++++++ pkg/monitor/models/unifiedmonitor.go | 86 +++++++++++++++++++++ 4 files changed, 188 insertions(+) create mode 100644 cmd/climc/shell/monitor/unifiedmonitor.go create mode 100644 pkg/mcclient/options/monitor/simplequery.go diff --git a/cmd/climc/shell/monitor/unifiedmonitor.go b/cmd/climc/shell/monitor/unifiedmonitor.go new file mode 100644 index 0000000000..454857cb08 --- /dev/null +++ b/cmd/climc/shell/monitor/unifiedmonitor.go @@ -0,0 +1,26 @@ +// 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 ( + "yunion.io/x/onecloud/cmd/climc/shell" + "yunion.io/x/onecloud/pkg/mcclient/modules/monitor" + options "yunion.io/x/onecloud/pkg/mcclient/options/monitor" +) + +func init() { + cmd := shell.NewResourceCmd(monitor.UnifiedMonitorManager).WithKeyword("monitor") + cmd.Show(&options.SimpleQueryOptions{}) +} diff --git a/pkg/apis/monitor/unifiedmonitor_const.go b/pkg/apis/monitor/unifiedmonitor_const.go index 5cc3842019..5d241a3285 100644 --- a/pkg/apis/monitor/unifiedmonitor_const.go +++ b/pkg/apis/monitor/unifiedmonitor_const.go @@ -14,6 +14,8 @@ package monitor +import "time" + var ( UNIFIED_MONITOR_FIELD_OPT_TYPE = []string{"Aggregations", "Selectors"} UNIFIED_MONITOR_GROUPBY_OPT_TYPE = []string{"time", "tag", "fill"} @@ -83,3 +85,25 @@ type MetricInputQuery struct { Signature string `json:"signature"` ShowMeta bool `json:"show_meta"` } + +type SimpleQueryInput struct { + // 资源Id, 可以不填, 代表查询指定监控的所有监控数据 + Id string `json:"id"` + // 查询指定数据库 + // default: telegraf + Database string `json:"database"` + // 监控指标: https://github.com/codelinz/cloudpods/blob/monitor/pkg/cloudprovider/metrics.go + MetricName string `json:"metric_name"` + // 开始时间 + StartTime time.Time `json:"start_time"` + // 结束时间 + EndTime time.Time `json:"end_time"` + // 指定标签 + Tags map[string]string `json:"tags"` +} + +type SimpleQueryOutput struct { + Id string `json:"id"` + Time time.Time `json:"time"` + Value float64 `json:"value"` +} diff --git a/pkg/mcclient/options/monitor/simplequery.go b/pkg/mcclient/options/monitor/simplequery.go new file mode 100644 index 0000000000..ad93e14e81 --- /dev/null +++ b/pkg/mcclient/options/monitor/simplequery.go @@ -0,0 +1,52 @@ +// 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 ( + "strings" + + "yunion.io/x/jsonutils" +) + +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"` + Tags []string `json:"tags"` +} + +func (o *SimpleQueryOptions) GetId() string { + return "simple-query" +} + +func (o *SimpleQueryOptions) Params() (jsonutils.JSONObject, error) { + ret := jsonutils.Marshal(o).(*jsonutils.JSONDict) + ret.Remove("tags") + tags := map[string]string{} + for _, tag := range o.Tags { + if strings.Contains(tag, "=") { + info := strings.Split(tag, "=") + if len(info) == 2 { + tags[info[0]] = info[1] + } + } + } + if len(tags) > 0 { + ret.Set("tags", jsonutils.Marshal(tags)) + } + return ret, nil +} diff --git a/pkg/monitor/models/unifiedmonitor.go b/pkg/monitor/models/unifiedmonitor.go index 5e04111fb5..b48fd63506 100644 --- a/pkg/monitor/models/unifiedmonitor.go +++ b/pkg/monitor/models/unifiedmonitor.go @@ -23,6 +23,7 @@ import ( "yunion.io/x/jsonutils" "yunion.io/x/log" "yunion.io/x/pkg/errors" + "yunion.io/x/pkg/gotypes" "yunion.io/x/onecloud/pkg/apis/monitor" "yunion.io/x/onecloud/pkg/cloudcommon/db" @@ -33,6 +34,7 @@ import ( mq "yunion.io/x/onecloud/pkg/monitor/metricquery" "yunion.io/x/onecloud/pkg/monitor/tsdb" "yunion.io/x/onecloud/pkg/monitor/validators" + "yunion.io/x/onecloud/pkg/util/influxdb" "yunion.io/x/onecloud/pkg/util/rbacutils" ) @@ -507,3 +509,87 @@ func fillSerieTags(series *tsdb.TimeSeriesSlice) { (*series)[i] = serie } } + +func (self *SUnifiedMonitorManager) GetPropertySimpleQuery(ctx context.Context, userCred mcclient.TokenCredential, + input *monitor.SimpleQueryInput) ([]monitor.SimpleQueryOutput, error) { + if len(input.Database) == 0 { + input.Database = "telegraf" + } + if len(input.MetricName) == 0 { + return nil, httperrors.NewMissingParameterError("metric_name") + } + metric := strings.Split(input.MetricName, ".") + if len(metric) != 2 { + return nil, httperrors.NewInputParameterError("invalid metric_name %s", input.MetricName) + } + measurement, field := metric[0], metric[1] + sqlstr := "select id, " + field + " from " + measurement + " where " + if input.Tags == nil { + input.Tags = map[string]string{} + } + if len(input.Id) > 0 { + input.Tags["id"] = input.Id + } + if input.EndTime.IsZero() { + input.EndTime = time.Now() + } + if input.StartTime.IsZero() { + input.StartTime = input.EndTime.Add(time.Hour * -1) + } + if input.EndTime.Sub(input.StartTime).Hours() > 1 { + return nil, httperrors.NewInputParameterError("The query interval is greater than one hour") + } + st := input.StartTime.Format("2006-01-02T15:04:05Z") + et := input.EndTime.Format("2006-01-02T15:04:05Z") + conditions := []string{} + for k, v := range input.Tags { + conditions = append(conditions, fmt.Sprintf("%s = %s", k, v)) + } + conditions = append(conditions, fmt.Sprintf("time >= '%s'", st)) + conditions = append(conditions, fmt.Sprintf("time <= '%s'", et)) + sqlstr += strings.Join(conditions, " and ") + dataSource, err := DataSourceManager.GetDefaultSource() + if err != nil { + return nil, errors.Wrap(err, "s.GetDefaultSource") + } + db := influxdb.NewInfluxdb(dataSource.Url) + err = db.SetDatabase(input.Database) + if err != nil { + return nil, httperrors.NewInputParameterError("not support database %s", input.Database) + } + dbRtn, err := db.Query(sqlstr) + if err != nil { + return nil, errors.Wrap(err, "sql selected error") + } + ret := []monitor.SimpleQueryOutput{} + for _, dbResults := range dbRtn { + for _, dbResult := range dbResults { + for _, value := range dbResult.Values { + if len(value) != 3 || + gotypes.IsNil(value[0]) || + gotypes.IsNil(value[1]) || + gotypes.IsNil(value[2]) { + continue + } + timestamp, err := value[0].Int() + if err != nil { + continue + } + id, err := value[1].GetString() + if err != nil { + continue + } + v, err := value[2].Float() + if err != nil { + continue + } + ret = append(ret, monitor.SimpleQueryOutput{ + Id: id, + Time: time.UnixMilli(timestamp), + Value: v, + }) + } + } + } + return ret, nil +}