types.go 2.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137
  1. package mqe
  2. import (
  3. "fmt"
  4. "strings"
  5. "regexp"
  6. "github.com/grafana/grafana/pkg/log"
  7. "github.com/grafana/grafana/pkg/tsdb"
  8. )
  9. type Metric struct {
  10. Metric string
  11. Alias string
  12. }
  13. type Function struct {
  14. Func string
  15. }
  16. type Query struct {
  17. Metrics []Metric
  18. Hosts []string
  19. Cluster []string
  20. FunctionList []Function
  21. AddClusterToAlias bool
  22. AddHostToAlias bool
  23. TimeRange *tsdb.TimeRange
  24. UseRawQuery bool
  25. RawQuery string
  26. }
  27. var (
  28. containsWildcardPattern *regexp.Regexp = regexp.MustCompile(`\*`)
  29. )
  30. func (q *Query) Build(availableSeries []string) ([]QueryToSend, error) {
  31. var queriesToSend []QueryToSend
  32. where := q.buildWhereClause()
  33. functions := q.buildFunctionList()
  34. for _, metric := range q.Metrics {
  35. alias := ""
  36. if metric.Alias != "" {
  37. alias = fmt.Sprintf(" {%s}", metric.Alias)
  38. }
  39. if !containsWildcardPattern.Match([]byte(metric.Metric)) {
  40. rawQuery := q.renderQuerystring(metric.Metric, functions, alias, where, q.TimeRange)
  41. queriesToSend = append(queriesToSend, QueryToSend{
  42. RawQuery: rawQuery,
  43. QueryRef: q,
  44. Metric: metric,
  45. })
  46. } else {
  47. m := strings.Replace(metric.Metric, "*", ".*", -1)
  48. mp, err := regexp.Compile(m)
  49. if err != nil {
  50. log.Error2("failed to compile regex for ", "metric", m)
  51. continue
  52. }
  53. //TODO: this lookup should be cached
  54. for _, wildcardMatch := range availableSeries {
  55. if mp.Match([]byte(wildcardMatch)) {
  56. rawQuery := q.renderQuerystring(wildcardMatch, functions, alias, where, q.TimeRange)
  57. queriesToSend = append(queriesToSend, QueryToSend{
  58. RawQuery: rawQuery,
  59. QueryRef: q,
  60. Metric: metric,
  61. })
  62. }
  63. }
  64. }
  65. }
  66. return queriesToSend, nil
  67. }
  68. func (q *Query) renderQuerystring(path, functions, alias, where string, timerange *tsdb.TimeRange) string {
  69. return fmt.Sprintf(
  70. "`%s`%s%s %s from %v to %v",
  71. path,
  72. functions,
  73. alias,
  74. where,
  75. q.TimeRange.GetFromAsMsEpoch(),
  76. q.TimeRange.GetToAsMsEpoch())
  77. }
  78. func (q *Query) buildFunctionList() string {
  79. functions := ""
  80. for _, v := range q.FunctionList {
  81. functions = fmt.Sprintf("%s|%s", functions, v.Func)
  82. }
  83. return functions
  84. }
  85. func (q *Query) buildWhereClause() string {
  86. hasApps := len(q.Cluster) > 0
  87. hasHosts := len(q.Hosts) > 0
  88. where := ""
  89. if hasHosts || hasApps {
  90. where += "where "
  91. }
  92. if hasApps {
  93. apps := strings.Join(q.Cluster, "', '")
  94. where += fmt.Sprintf("cluster in ('%s')", apps)
  95. }
  96. if hasHosts && hasApps {
  97. where += " and "
  98. }
  99. if hasHosts {
  100. hosts := strings.Join(q.Hosts, "', '")
  101. where += fmt.Sprintf("host in ('%s')", hosts)
  102. }
  103. return where
  104. }
  105. type TokenBody struct {
  106. Metrics []string
  107. }
  108. type TokenResponse struct {
  109. Success bool
  110. Body TokenBody
  111. }