query_part.go 6.7 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 influxdb
  15. import (
  16. "fmt"
  17. "strings"
  18. "yunion.io/x/onecloud/pkg/monitor/tsdb"
  19. )
  20. var renders map[string]QueryDefinition
  21. type DefinitionParameters struct {
  22. Name string
  23. Type string
  24. }
  25. type QueryDefinition struct {
  26. Renderer func(query *Query, queryCtx *tsdb.TsdbQuery, part *QueryPart, innerExpr string) string
  27. Params []DefinitionParameters
  28. }
  29. func init() {
  30. renders = make(map[string]QueryDefinition)
  31. renders["field"] = QueryDefinition{Renderer: fieldRenderer}
  32. renders["func_field"] = QueryDefinition{Renderer: funFieldRenderer}
  33. renders["spread"] = QueryDefinition{Renderer: functionRenderer}
  34. renders["count"] = QueryDefinition{Renderer: functionRenderer}
  35. renders["distinct"] = QueryDefinition{Renderer: functionRenderer}
  36. renders["integral"] = QueryDefinition{Renderer: functionRenderer}
  37. renders["mean"] = QueryDefinition{Renderer: functionRenderer}
  38. renders["median"] = QueryDefinition{Renderer: functionRenderer}
  39. renders["sum"] = QueryDefinition{Renderer: functionRenderer}
  40. renders["mode"] = QueryDefinition{Renderer: functionRenderer}
  41. renders["cumulative_sum"] = QueryDefinition{Renderer: functionRenderer}
  42. renders["non_negative_difference"] = QueryDefinition{Renderer: functionRenderer}
  43. renders["holt_winters"] = QueryDefinition{
  44. Renderer: functionRenderer,
  45. Params: []DefinitionParameters{{Name: "number", Type: "number"}, {Name: "season", Type: "number"}},
  46. }
  47. renders["holt_winters_with_fit"] = QueryDefinition{
  48. Renderer: functionRenderer,
  49. Params: []DefinitionParameters{{Name: "number", Type: "number"}, {Name: "season", Type: "number"}},
  50. }
  51. renders["derivative"] = QueryDefinition{
  52. Renderer: functionRenderer,
  53. Params: []DefinitionParameters{{Name: "duration", Type: "interval"}},
  54. }
  55. renders["non_negative_derivative"] = QueryDefinition{
  56. Renderer: functionRenderer,
  57. Params: []DefinitionParameters{{Name: "duration", Type: "interval"}},
  58. }
  59. renders["difference"] = QueryDefinition{Renderer: functionRenderer}
  60. renders["moving_average"] = QueryDefinition{
  61. Renderer: functionRenderer,
  62. Params: []DefinitionParameters{{Name: "window", Type: "number"}},
  63. }
  64. renders["stddev"] = QueryDefinition{Renderer: functionRenderer}
  65. renders["time"] = QueryDefinition{
  66. Renderer: functionRenderer,
  67. Params: []DefinitionParameters{{Name: "interval", Type: "time"}, {Name: "offset", Type: "time"}},
  68. }
  69. renders["fill"] = QueryDefinition{
  70. Renderer: functionRenderer,
  71. Params: []DefinitionParameters{{Name: "fill", Type: "string"}},
  72. }
  73. renders["elapsed"] = QueryDefinition{
  74. Renderer: functionRenderer,
  75. Params: []DefinitionParameters{{Name: "duration", Type: "interval"}},
  76. }
  77. renders["bottom"] = QueryDefinition{
  78. Renderer: functionRenderer,
  79. Params: []DefinitionParameters{{Name: "count", Type: "int"}},
  80. }
  81. renders["first"] = QueryDefinition{Renderer: functionRenderer}
  82. renders["last"] = QueryDefinition{Renderer: functionRenderer}
  83. renders["max"] = QueryDefinition{Renderer: functionRenderer}
  84. renders["min"] = QueryDefinition{Renderer: functionRenderer}
  85. renders["abs"] = QueryDefinition{Renderer: functionRenderer}
  86. renders["percentile"] = QueryDefinition{
  87. Renderer: functionRenderer,
  88. Params: []DefinitionParameters{{Name: "nth", Type: "int"}},
  89. }
  90. renders["top"] = QueryDefinition{
  91. Renderer: functionRenderer,
  92. Params: []DefinitionParameters{{Name: "count", Type: "int"}},
  93. }
  94. renders["tag"] = QueryDefinition{
  95. Renderer: tagRenderer,
  96. Params: []DefinitionParameters{{Name: "tag", Type: "string"}},
  97. }
  98. renders["math"] = QueryDefinition{Renderer: suffixRenderer}
  99. renders["alias"] = QueryDefinition{Renderer: aliasRenderer}
  100. renders["slimit"] = QueryDefinition{Renderer: typeRenderer}
  101. renders["soffset"] = QueryDefinition{Renderer: typeRenderer}
  102. }
  103. func fieldRenderer(query *Query, queryCtx *tsdb.TsdbQuery, part *QueryPart, innerExpr string) string {
  104. if part.Params[0] == "*" {
  105. // return "*::field"
  106. return "*"
  107. }
  108. // return fmt.Sprintf(`"%s"::field`, part.Params[0])
  109. return fmt.Sprintf(`"%s"`, part.Params[0])
  110. }
  111. func funFieldRenderer(query *Query, queryCtx *tsdb.TsdbQuery, part *QueryPart, innerExpr string) string {
  112. if part.Params[0] == "*" {
  113. // return "*::field"
  114. return "*"
  115. }
  116. if len(innerExpr) != 0 {
  117. part.Params = append([]string{innerExpr}, part.Params...)
  118. }
  119. stringB := strings.Builder{}
  120. for i, str := range part.Params {
  121. stringB.WriteString(fmt.Sprintf(`"%s"`, str))
  122. if i != len(part.Params)-1 {
  123. stringB.WriteString(",")
  124. }
  125. }
  126. return stringB.String()
  127. }
  128. func tagRenderer(query *Query, queryCtx *tsdb.TsdbQuery, part *QueryPart, innerExpr string) string {
  129. if part.Params[0] == "*" {
  130. // return "*::tag"
  131. return "*"
  132. }
  133. // return fmt.Sprintf(`"%s"::tag`, part.Params[0])
  134. return fmt.Sprintf(`"%s"`, part.Params[0])
  135. }
  136. func functionRenderer(query *Query, queryCtx *tsdb.TsdbQuery, part *QueryPart, innerExpr string) string {
  137. for i, param := range part.Params {
  138. if part.Type == "time" && param == "auto" {
  139. part.Params[i] = "$__interval"
  140. }
  141. }
  142. if innerExpr != "" {
  143. part.Params = append([]string{innerExpr}, part.Params...)
  144. }
  145. params := strings.Join(part.Params, ", ")
  146. return fmt.Sprintf("%s(%s)", part.Type, params)
  147. }
  148. func suffixRenderer(query *Query, queryCtx *tsdb.TsdbQuery, part *QueryPart, innerExpr string) string {
  149. return fmt.Sprintf("%s %s", innerExpr, part.Params[0])
  150. }
  151. func aliasRenderer(query *Query, queryCtx *tsdb.TsdbQuery, part *QueryPart, innerExpr string) string {
  152. return fmt.Sprintf(`%s AS "%s"`, innerExpr, part.Params[0])
  153. }
  154. func typeRenderer(query *Query, queryCtx *tsdb.TsdbQuery, part *QueryPart, innerExpr string) string {
  155. return fmt.Sprintf(" %s %s", part.Type, part.Params[0])
  156. }
  157. func (r QueryDefinition) Render(query *Query, queryCtx *tsdb.TsdbQuery, part *QueryPart, innerExpr string) string {
  158. return r.Renderer(query, queryCtx, part, innerExpr)
  159. }
  160. func NewQueryPart(typ string, params []string) (*QueryPart, error) {
  161. def, exist := renders[typ]
  162. if !exist {
  163. return nil, fmt.Errorf("Missing query definition for %s", typ)
  164. }
  165. return &QueryPart{
  166. Def: def,
  167. Type: typ,
  168. Params: params,
  169. }, nil
  170. }
  171. type QueryPart struct {
  172. Def QueryDefinition
  173. Type string
  174. Params []string
  175. }
  176. func (qp *QueryPart) Render(query *Query, queryCtx *tsdb.TsdbQuery, expr string) string {
  177. return qp.Def.Renderer(query, queryCtx, qp, expr)
  178. }