response_parser.go 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146
  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+)(\.\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. Tags: row.Tags,
  43. })
  44. }
  45. }
  46. return result
  47. }
  48. func (rp *ResponseParser) formatSerieName(row Row, column string, query *Query) string {
  49. if query.Alias == "" {
  50. return rp.buildSerieNameFromQuery(row, column)
  51. }
  52. nameSegment := strings.Split(row.Name, ".")
  53. result := legendFormat.ReplaceAllFunc([]byte(query.Alias), func(in []byte) []byte {
  54. aliasFormat := string(in)
  55. aliasFormat = strings.Replace(aliasFormat, "[[", "", 1)
  56. aliasFormat = strings.Replace(aliasFormat, "]]", "", 1)
  57. aliasFormat = strings.Replace(aliasFormat, "$", "", 1)
  58. if aliasFormat == "m" || aliasFormat == "measurement" {
  59. return []byte(query.Measurement)
  60. }
  61. if aliasFormat == "col" {
  62. return []byte(column)
  63. }
  64. pos, err := strconv.Atoi(aliasFormat)
  65. if err == nil && len(nameSegment) >= pos {
  66. return []byte(nameSegment[pos])
  67. }
  68. if !strings.HasPrefix(aliasFormat, "tag_") {
  69. return in
  70. }
  71. tagKey := strings.Replace(aliasFormat, "tag_", "", 1)
  72. tagValue, exist := row.Tags[tagKey]
  73. if exist {
  74. return []byte(tagValue)
  75. }
  76. return in
  77. })
  78. return string(result)
  79. }
  80. func (rp *ResponseParser) buildSerieNameFromQuery(row Row, column string) string {
  81. var tags []string
  82. for k, v := range row.Tags {
  83. tags = append(tags, fmt.Sprintf("%s: %s", k, v))
  84. }
  85. tagText := ""
  86. if len(tags) > 0 {
  87. tagText = fmt.Sprintf(" { %s }", strings.Join(tags, " "))
  88. }
  89. return fmt.Sprintf("%s.%s%s", row.Name, column, tagText)
  90. }
  91. func (rp *ResponseParser) parseTimepoint(valuePair []interface{}, valuePosition int) (tsdb.TimePoint, error) {
  92. var value null.Float = rp.parseValue(valuePair[valuePosition])
  93. timestampNumber, _ := valuePair[0].(json.Number)
  94. timestamp, err := timestampNumber.Float64()
  95. if err != nil {
  96. return tsdb.TimePoint{}, err
  97. }
  98. return tsdb.NewTimePoint(value, timestamp), nil
  99. }
  100. func (rp *ResponseParser) parseValue(value interface{}) null.Float {
  101. number, ok := value.(json.Number)
  102. if !ok {
  103. return null.FloatFromPtr(nil)
  104. }
  105. fvalue, err := number.Float64()
  106. if err == nil {
  107. return null.FloatFrom(fvalue)
  108. }
  109. ivalue, err := number.Int64()
  110. if err == nil {
  111. return null.FloatFrom(float64(ivalue))
  112. }
  113. return null.FloatFromPtr(nil)
  114. }