unifiedmonitor.go 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185
  1. // Copyright 2019 Yunion
  2. //
  3. // Licensed under the Apache License, Version 2.0 (the "License");
  4. // you may not use this file except in compliance with the License.
  5. // You may obtain a copy of the License at
  6. //
  7. // http://www.apache.org/licenses/LICENSE-2.0
  8. //
  9. // Unless required by applicable law or agreed to in writing, software
  10. // distributed under the License is distributed on an "AS IS" BASIS,
  11. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12. // See the License for the specific language governing permissions and
  13. // limitations under the License.
  14. package monitor
  15. import (
  16. "strconv"
  17. "strings"
  18. "time"
  19. "yunion.io/x/jsonutils"
  20. "yunion.io/x/pkg/errors"
  21. api "yunion.io/x/onecloud/pkg/apis/monitor"
  22. "yunion.io/x/onecloud/pkg/mcclient/modules/monitor"
  23. )
  24. type ResourceMetricsOptions struct {
  25. RES_TYPE string `help:"resource type: host or guest" choices:"host|guest"`
  26. ResIds []string `help:"resource IDs" json:"res_ids" nargs:"+"`
  27. StartTime string `help:"start time (RFC3339). e.g.: 2023-12-06T21:54:42Z" json:"-"`
  28. EndTime string `help:"end time (RFC3339). e.g.: 2023-12-18T21:54:42Z" json:"-"`
  29. Interval string `help:"query interval. e.g.: 5m, 1h" json:"interval"`
  30. }
  31. func (o *ResourceMetricsOptions) GetInput() (*api.ResourceMetricsQueryInput, error) {
  32. input := &api.ResourceMetricsQueryInput{
  33. ResType: o.RES_TYPE,
  34. ResIds: o.ResIds,
  35. Interval: o.Interval,
  36. }
  37. if o.StartTime != "" {
  38. t, err := time.Parse(time.RFC3339, o.StartTime)
  39. if err != nil {
  40. return nil, errors.Wrapf(err, "invalid start_time %q", o.StartTime)
  41. }
  42. input.StartTime = t
  43. }
  44. if o.EndTime != "" {
  45. t, err := time.Parse(time.RFC3339, o.EndTime)
  46. if err != nil {
  47. return nil, errors.Wrapf(err, "invalid end_time %q", o.EndTime)
  48. }
  49. input.EndTime = t
  50. }
  51. return input, nil
  52. }
  53. type MeasurementsQueryOptions struct {
  54. Scope string `json:"scope"`
  55. ProjectDomainId string `json:"project_domin_id"`
  56. ProjectId string `json:"project_id"`
  57. }
  58. func (o MeasurementsQueryOptions) Params() (jsonutils.JSONObject, error) {
  59. return jsonutils.Marshal(o), nil
  60. }
  61. func (o MeasurementsQueryOptions) Property() string {
  62. return "measurements"
  63. }
  64. type DatabasesQueryOptions struct{}
  65. func (o DatabasesQueryOptions) Params() (jsonutils.JSONObject, error) {
  66. return nil, nil
  67. }
  68. func (o DatabasesQueryOptions) Property() string {
  69. return "databases"
  70. }
  71. type MetricQueryOptions struct {
  72. MeasurementsQueryOptions
  73. MEASUREMENT string `help:"metric measurement. e.g.: cpu, vm_cpu, vm_mem, disk..."`
  74. FIELD string `help:"metric field. e.g.: usage_active, free..."`
  75. Interval string `help:"metric interval. e.g.: 5m, 1h"`
  76. From string `help:"start time(RFC3339 format). e.g.: 2023-12-06T21:54:42.123Z"`
  77. To string `help:"end time(RFC3339 format). e.g.: 2023-12-18T21:54:42.123Z"`
  78. Tags []string `help:"filter tags. e.g.: vm_name=vm1"`
  79. GroupBy []string `help:"group by tag"`
  80. UseMean bool `help:"calcuate mean result for field"`
  81. SkipCheckSeries bool `help:"skip checking series: not fetch extra tags from region service"`
  82. Reducer string `help:"series result reducer. e.g.: sum, percentile(95)"`
  83. }
  84. func (o MetricQueryOptions) GetQueryInput() (*api.MetricQueryInput, error) {
  85. input := monitor.NewMetricQueryInput(o.MEASUREMENT)
  86. input.Interval(o.Interval)
  87. if o.SkipCheckSeries {
  88. input.SkipCheckSeries(true)
  89. }
  90. input.Scope(o.Scope)
  91. // parse time
  92. if o.From != "" {
  93. fromTime, err := time.Parse(time.RFC3339, o.From)
  94. if err != nil {
  95. return nil, errors.Wrapf(err, "invalid from time: %q", o.From)
  96. }
  97. input.From(fromTime)
  98. }
  99. if o.To != "" {
  100. toTime, err := time.Parse(time.RFC3339, o.To)
  101. if err != nil {
  102. return nil, errors.Wrapf(err, "invalid to time: %q", o.To)
  103. }
  104. input.To(toTime)
  105. }
  106. sel := input.Selects().Select(o.FIELD)
  107. if o.UseMean {
  108. sel.MEAN()
  109. }
  110. where := input.Where()
  111. for _, tag := range o.Tags {
  112. if strings.Contains(tag, "=") {
  113. info := strings.Split(tag, "=")
  114. if len(info) == 2 {
  115. where.Equal(info[0], info[1])
  116. } else {
  117. return nil, errors.Errorf("invalid tag: %q, len: %d", tag, len(info))
  118. }
  119. } else {
  120. return nil, errors.Errorf("invalid tag: %q", tag)
  121. }
  122. }
  123. groupBy := input.GroupBy()
  124. for _, tag := range o.GroupBy {
  125. groupBy.TAG(tag)
  126. }
  127. if o.Reducer != "" {
  128. r, err := o.parseReducer(o.Reducer)
  129. if err != nil {
  130. return nil, errors.Wrapf(err, "invalid reducer: %q", o.Reducer)
  131. }
  132. input.Reducer(r.Type, r.Params)
  133. }
  134. return input.ToQueryData(), nil
  135. }
  136. func (o MetricQueryOptions) parseReducer(reducer string) (*api.Condition, error) {
  137. if reducer == "" {
  138. return nil, errors.Errorf("invalid reducer %q", reducer)
  139. }
  140. parts := strings.Split(reducer, "(")
  141. if len(parts) < 1 {
  142. return nil, errors.Errorf("invalid reducer %q", reducer)
  143. }
  144. rType := parts[0]
  145. cond := &api.Condition{
  146. Type: rType,
  147. }
  148. if len(parts) > 1 {
  149. params := []float64{}
  150. paramStr := parts[1]
  151. paramsStr := strings.Split(strings.TrimSuffix(paramStr, ")"), ",")
  152. for _, param := range paramsStr {
  153. f, err := strconv.ParseFloat(strings.ReplaceAll(param, " ", ""), 64)
  154. if err != nil {
  155. return nil, errors.Wrapf(err, "invalid reducer param %q", param)
  156. }
  157. params = append(params, f)
  158. }
  159. cond.Params = params
  160. }
  161. return cond, nil
  162. }