nodataquery.go 7.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208
  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 conditions
  15. import (
  16. "fmt"
  17. "yunion.io/x/jsonutils"
  18. "yunion.io/x/log"
  19. "yunion.io/x/pkg/errors"
  20. "yunion.io/x/onecloud/pkg/apis/monitor"
  21. "yunion.io/x/onecloud/pkg/hostman/hostinfo/hostconsts"
  22. "yunion.io/x/onecloud/pkg/mcclient/auth"
  23. "yunion.io/x/onecloud/pkg/monitor/alerting"
  24. "yunion.io/x/onecloud/pkg/monitor/models"
  25. "yunion.io/x/onecloud/pkg/monitor/tsdb"
  26. )
  27. const (
  28. NO_DATA = "nodata"
  29. HOST_TAG_NAME = "name"
  30. HOST_TAG_ID = "id"
  31. HOST_TAG_IP = "access_ip"
  32. RESOURCE_TAG_IP = "ips"
  33. HOST_TAG_BRAND = "brand"
  34. )
  35. func init() {
  36. alerting.RegisterCondition(monitor.METRIC_QUERY_TYPE_NO_DATA, func(model *monitor.AlertCondition, index int) (alerting.Condition,
  37. error) {
  38. return newNoDataQueryCondition(model, index)
  39. })
  40. }
  41. type NoDataQueryCondition struct {
  42. *QueryCondition
  43. }
  44. func (c *NoDataQueryCondition) Eval(context *alerting.EvalContext) (*alerting.ConditionResult, error) {
  45. timeRange := tsdb.NewTimeRange(c.Query.From, c.Query.To)
  46. ret, err := c.executeQuery(context, timeRange)
  47. if err != nil {
  48. return nil, err
  49. }
  50. seriesList := ret.series
  51. var matches []*monitor.EvalMatch
  52. var alertOkmatches []*monitor.EvalMatch
  53. normalHostIds := make(map[string]*monitor.EvalMatch, 0)
  54. alert, err := models.CommonAlertManager.GetAlert(context.Rule.Id)
  55. if err != nil {
  56. return nil, errors.Wrap(err, "GetAlert to NewEvalMatch error")
  57. }
  58. serLoop:
  59. for _, series := range seriesList {
  60. tagId := monitor.GetMeasurementTagIdKeyByResTypeWithDefault(context.Rule.RuleDescription[0].ResType)
  61. for key, val := range series.Tags {
  62. if key == tagId {
  63. if len(context.Rule.RuleDescription) == 0 {
  64. return &alerting.ConditionResult{
  65. Firing: false,
  66. NoDataFound: true,
  67. Operator: c.Operator,
  68. EvalMatches: matches,
  69. AlertOkEvalMatches: alertOkmatches,
  70. }, nil
  71. }
  72. reducedValue, valStrArr := c.Reducer.Reduce(series)
  73. match, err := c.NewEvalMatch(alert, context, *series, nil, reducedValue, valStrArr, false)
  74. if err != nil {
  75. return nil, errors.Wrap(err, "NoDataQueryCondition NewEvalMatch error")
  76. }
  77. normalHostIds[val] = match
  78. continue serLoop
  79. }
  80. }
  81. }
  82. allResources, err := c.GetQueryResources(auth.GetAdminSession(context.Ctx, ""), "system", true)
  83. if err != nil {
  84. return nil, errors.Wrap(err, "GetQueryResources err")
  85. }
  86. for _, host := range allResources {
  87. id, _ := host.GetString("id")
  88. evalMatch, err := c.NewNoDataEvalMatch(context, alert, host)
  89. if err != nil {
  90. return nil, errors.Wrapf(err, "NewNoDataEvalMatch of host: %s", host.String())
  91. }
  92. if normalMatch, ok := normalHostIds[id]; !ok {
  93. c.createEvalMatchTagFromHostJson(context, evalMatch, host)
  94. matches = append(matches, evalMatch)
  95. } else {
  96. c.createEvalMatchTagFromHostJson(context, normalMatch, host)
  97. if err := OkEvalMatchSetIsRecovery(alert, id, normalMatch); err != nil {
  98. log.Warningf("[NoDataQuery] set eval match %s to recovered: %v", jsonutils.Marshal(normalMatch), err)
  99. }
  100. alertOkmatches = append(alertOkmatches, normalMatch)
  101. }
  102. }
  103. return &alerting.ConditionResult{
  104. Firing: len(matches) > 0,
  105. NoDataFound: 0 == len(seriesList),
  106. Operator: c.Operator,
  107. EvalMatches: matches,
  108. AlertOkEvalMatches: alertOkmatches,
  109. }, nil
  110. }
  111. /*func (c *NoDataQueryCondition) convertTagsQuery(evalContext *alerting.EvalContext,
  112. query *jsonutils.JSONDict) (*jsonutils.JSONDict, error) {
  113. alertDetails, err := c.GetCommonAlertDetails(evalContext)
  114. if err != nil {
  115. return nil, err
  116. }
  117. for i, _ := range c.Query.Model.Tags {
  118. filterCount := 0
  119. if c.Query.Model.Tags[i].Operator == "=" {
  120. if tag, ok := monitor.MEASUREMENT_TAG_KEYWORD[alertDetails.ResType]; ok {
  121. if c.Query.Model.Tags[i].Key == tag {
  122. query.Set("name", jsonutils.NewString(c.Query.Model.Tags[i].Value))
  123. continue
  124. }
  125. }
  126. }
  127. query.Set(fmt.Sprintf("filter.%d", filterCount),
  128. jsonutils.NewString(fmt.Sprintf("%s.notin(%s)", c.Query.Model.Tags[i].Key, c.Query.Model.Tags[i].Value)))
  129. filterCount++
  130. }
  131. return query, nil
  132. }*/
  133. func (c *NoDataQueryCondition) NewNoDataEvalMatch(context *alerting.EvalContext, alert *models.SCommonAlert, host jsonutils.JSONObject) (*monitor.EvalMatch, error) {
  134. evalMatch := new(monitor.EvalMatch)
  135. settings, _ := alert.GetSettings()
  136. alertDetails := alert.GetCommonAlertMetricDetailsFromAlertCondition(c.Index, &settings.Conditions[c.Index])
  137. evalMatch.Metric = fmt.Sprintf("%s.%s", alertDetails.Measurement, alertDetails.Field)
  138. queryKeyInfo := ""
  139. if len(alertDetails.MeasurementDisplayName) > 0 && len(alertDetails.FieldDescription.DisplayName) > 0 {
  140. queryKeyInfo = fmt.Sprintf("%s.%s", alertDetails.MeasurementDisplayName, alertDetails.FieldDescription.DisplayName)
  141. }
  142. if len(queryKeyInfo) == 0 {
  143. queryKeyInfo = evalMatch.Metric
  144. }
  145. evalMatch.Unit = alertDetails.FieldDescription.Unit
  146. msg := fmt.Sprintf("%s.%s %s ", alertDetails.Measurement, alertDetails.Field,
  147. alertDetails.Comparator)
  148. context.Rule.Message = msg
  149. //evalMatch.Condition = c.GenerateFormatCond(meta, queryKeyInfo).String()
  150. evalMatch.ValueStr = NO_DATA
  151. evalMatch.AlertDetails = jsonutils.Marshal(alertDetails)
  152. return evalMatch, nil
  153. }
  154. func (c *NoDataQueryCondition) createEvalMatchTagFromHostJson(
  155. evalContext *alerting.EvalContext,
  156. evalMatch *monitor.EvalMatch,
  157. host jsonutils.JSONObject,
  158. ) {
  159. evalMatch.Tags = make(map[string]string, 0)
  160. ip, _ := host.GetString(HOST_TAG_IP)
  161. if ip == "" {
  162. ip, _ = host.GetString(RESOURCE_TAG_IP)
  163. }
  164. name, _ := host.GetString(HOST_TAG_NAME)
  165. id, _ := host.GetString("id")
  166. brand, _ := host.GetString(HOST_TAG_BRAND)
  167. evalMatch.Tags["ip"] = ip
  168. evalMatch.Tags[HOST_TAG_NAME] = name
  169. evalMatch.Tags[HOST_TAG_BRAND] = brand
  170. switch evalContext.Rule.RuleDescription[0].ResType {
  171. case monitor.METRIC_RES_TYPE_GUEST:
  172. case monitor.METRIC_RES_TYPE_RDS:
  173. case monitor.METRIC_RES_TYPE_REDIS:
  174. case monitor.METRIC_RES_TYPE_OSS:
  175. default:
  176. evalMatch.Tags["host"] = name
  177. evalMatch.Tags[monitor.GetMeasurementTagIdKeyByResType(monitor.METRIC_RES_TYPE_HOST)] = id
  178. evalMatch.Tags[hostconsts.TELEGRAF_TAG_KEY_RES_TYPE] = hostconsts.TELEGRAF_TAG_ONECLOUD_RES_TYPE
  179. evalMatch.Tags[hostconsts.TELEGRAF_TAG_KEY_HOST_TYPE] = hostconsts.TELEGRAF_TAG_ONECLOUD_HOST_TYPE_HOST
  180. }
  181. }
  182. func newNoDataQueryCondition(model *monitor.AlertCondition, index int) (*NoDataQueryCondition, error) {
  183. queryCondition, err := newQueryCondition(model, index)
  184. if err != nil {
  185. return nil, err
  186. }
  187. condition := new(NoDataQueryCondition)
  188. condition.QueryCondition = queryCondition
  189. return condition, nil
  190. }