response_parser.go 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145
  1. package influxdb
  2. import (
  3. "encoding/json"
  4. "fmt"
  5. "regexp"
  6. "strconv"
  7. "strings"
  8. "github.com/grafana/grafana/pkg/components/null"
  9. "github.com/grafana/grafana/pkg/tsdb"
  10. )
  11. type ResponseParser struct{}
  12. var (
  13. legendFormat *regexp.Regexp
  14. )
  15. func init() {
  16. legendFormat = regexp.MustCompile(`\[\[(\w+?)*\]\]*|\$\s*(\w+?)*`)
  17. }
  18. func (rp *ResponseParser) Parse(response *Response, query *Query) *tsdb.QueryResult {
  19. queryRes := tsdb.NewQueryResult()
  20. for _, result := range response.Results {
  21. queryRes.Series = append(queryRes.Series, rp.transformRows(result.Series, queryRes, query)...)
  22. }
  23. return queryRes
  24. }
  25. func (rp *ResponseParser) transformRows(rows []Row, queryResult *tsdb.QueryResult, query *Query) tsdb.TimeSeriesSlice {
  26. var result tsdb.TimeSeriesSlice
  27. for _, row := range rows {
  28. for columnIndex, column := range row.Columns {
  29. if column == "time" {
  30. continue
  31. }
  32. var points tsdb.TimeSeriesPoints
  33. for _, valuePair := range row.Values {
  34. point, err := rp.parseTimepoint(valuePair, columnIndex)
  35. if err == nil {
  36. points = append(points, point)
  37. }
  38. }
  39. result = append(result, &tsdb.TimeSeries{
  40. Name: rp.formatSerieName(row, column, query),
  41. Points: points,
  42. })
  43. }
  44. }
  45. return result
  46. }
  47. func (rp *ResponseParser) formatSerieName(row Row, column string, query *Query) string {
  48. if query.Alias == "" {
  49. return rp.buildSerieNameFromQuery(row, column)
  50. }
  51. nameSegment := strings.Split(row.Name, ".")
  52. result := legendFormat.ReplaceAllFunc([]byte(query.Alias), func(in []byte) []byte {
  53. aliasFormat := string(in)
  54. aliasFormat = strings.Replace(aliasFormat, "[[", "", 1)
  55. aliasFormat = strings.Replace(aliasFormat, "]]", "", 1)
  56. aliasFormat = strings.Replace(aliasFormat, "$", "", 1)
  57. if aliasFormat == "m" || aliasFormat == "measurement" {
  58. return []byte(query.Measurement)
  59. }
  60. if aliasFormat == "col" {
  61. return []byte(column)
  62. }
  63. pos, err := strconv.Atoi(aliasFormat)
  64. if err == nil && len(nameSegment) >= pos {
  65. return []byte(nameSegment[pos])
  66. }
  67. if !strings.HasPrefix(aliasFormat, "tag_") {
  68. return in
  69. }
  70. tagKey := strings.Replace(aliasFormat, "tag_", "", 1)
  71. tagValue, exist := row.Tags[tagKey]
  72. if exist {
  73. return []byte(tagValue)
  74. }
  75. return in
  76. })
  77. return string(result)
  78. }
  79. func (rp *ResponseParser) buildSerieNameFromQuery(row Row, column string) string {
  80. var tags []string
  81. for k, v := range row.Tags {
  82. tags = append(tags, fmt.Sprintf("%s: %s", k, v))
  83. }
  84. tagText := ""
  85. if len(tags) > 0 {
  86. tagText = fmt.Sprintf(" { %s }", strings.Join(tags, " "))
  87. }
  88. return fmt.Sprintf("%s.%s%s", row.Name, column, tagText)
  89. }
  90. func (rp *ResponseParser) parseTimepoint(valuePair []interface{}, valuePosition int) (tsdb.TimePoint, error) {
  91. var value null.Float = rp.parseValue(valuePair[valuePosition])
  92. timestampNumber, _ := valuePair[0].(json.Number)
  93. timestamp, err := timestampNumber.Float64()
  94. if err != nil {
  95. return tsdb.TimePoint{}, err
  96. }
  97. return tsdb.NewTimePoint(value, timestamp), nil
  98. }
  99. func (rp *ResponseParser) parseValue(value interface{}) null.Float {
  100. number, ok := value.(json.Number)
  101. if !ok {
  102. return null.FloatFromPtr(nil)
  103. }
  104. fvalue, err := number.Float64()
  105. if err == nil {
  106. return null.FloatFrom(fvalue)
  107. }
  108. ivalue, err := number.Int64()
  109. if err == nil {
  110. return null.FloatFrom(float64(ivalue))
  111. }
  112. return null.FloatFromPtr(nil)
  113. }