point.go 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162
  1. // Copyright 2020-2021 InfluxData, Inc. All rights reserved.
  2. // Use of this source code is governed by MIT
  3. // license that can be found in the LICENSE file.
  4. // Package write provides the Point struct
  5. package write
  6. import (
  7. "fmt"
  8. "sort"
  9. "time"
  10. lp "github.com/influxdata/line-protocol"
  11. )
  12. // Point is represents InfluxDB time series point, holding tags and fields
  13. type Point struct {
  14. measurement string
  15. tags []*lp.Tag
  16. fields []*lp.Field
  17. timestamp time.Time
  18. }
  19. // TagList returns a slice containing tags of a Point.
  20. func (m *Point) TagList() []*lp.Tag {
  21. return m.tags
  22. }
  23. // FieldList returns a slice containing the fields of a Point.
  24. func (m *Point) FieldList() []*lp.Field {
  25. return m.fields
  26. }
  27. // SetTime set timestamp for a Point.
  28. func (m *Point) SetTime(timestamp time.Time) *Point {
  29. m.timestamp = timestamp
  30. return m
  31. }
  32. // Time is the timestamp of a Point.
  33. func (m *Point) Time() time.Time {
  34. return m.timestamp
  35. }
  36. // SortTags orders the tags of a point alphanumerically by key.
  37. // This is just here as a helper, to make it easy to keep tags sorted if you are creating a Point manually.
  38. func (m *Point) SortTags() *Point {
  39. sort.Slice(m.tags, func(i, j int) bool { return m.tags[i].Key < m.tags[j].Key })
  40. return m
  41. }
  42. // SortFields orders the fields of a point alphanumerically by key.
  43. func (m *Point) SortFields() *Point {
  44. sort.Slice(m.fields, func(i, j int) bool { return m.fields[i].Key < m.fields[j].Key })
  45. return m
  46. }
  47. // AddTag adds a tag to a point.
  48. func (m *Point) AddTag(k, v string) *Point {
  49. for i, tag := range m.tags {
  50. if k == tag.Key {
  51. m.tags[i].Value = v
  52. return m
  53. }
  54. }
  55. m.tags = append(m.tags, &lp.Tag{Key: k, Value: v})
  56. return m
  57. }
  58. // AddField adds a field to a point.
  59. func (m *Point) AddField(k string, v interface{}) *Point {
  60. for i, field := range m.fields {
  61. if k == field.Key {
  62. m.fields[i].Value = v
  63. return m
  64. }
  65. }
  66. m.fields = append(m.fields, &lp.Field{Key: k, Value: convertField(v)})
  67. return m
  68. }
  69. // Name returns the name of measurement of a point.
  70. func (m *Point) Name() string {
  71. return m.measurement
  72. }
  73. // NewPointWithMeasurement creates a empty Point
  74. // Use AddTag and AddField to fill point with data
  75. func NewPointWithMeasurement(measurement string) *Point {
  76. return &Point{measurement: measurement}
  77. }
  78. // NewPoint creates a Point from measurement name, tags, fields and a timestamp.
  79. func NewPoint(
  80. measurement string,
  81. tags map[string]string,
  82. fields map[string]interface{},
  83. ts time.Time,
  84. ) *Point {
  85. m := &Point{
  86. measurement: measurement,
  87. tags: nil,
  88. fields: nil,
  89. timestamp: ts,
  90. }
  91. if len(tags) > 0 {
  92. m.tags = make([]*lp.Tag, 0, len(tags))
  93. for k, v := range tags {
  94. m.tags = append(m.tags,
  95. &lp.Tag{Key: k, Value: v})
  96. }
  97. }
  98. m.fields = make([]*lp.Field, 0, len(fields))
  99. for k, v := range fields {
  100. v := convertField(v)
  101. if v == nil {
  102. continue
  103. }
  104. m.fields = append(m.fields, &lp.Field{Key: k, Value: v})
  105. }
  106. m.SortFields()
  107. m.SortTags()
  108. return m
  109. }
  110. // convertField converts any primitive type to types supported by line protocol
  111. func convertField(v interface{}) interface{} {
  112. switch v := v.(type) {
  113. case bool, int64, string, float64:
  114. return v
  115. case int:
  116. return int64(v)
  117. case uint:
  118. return uint64(v)
  119. case uint64:
  120. return v
  121. case []byte:
  122. return string(v)
  123. case int32:
  124. return int64(v)
  125. case int16:
  126. return int64(v)
  127. case int8:
  128. return int64(v)
  129. case uint32:
  130. return uint64(v)
  131. case uint16:
  132. return uint64(v)
  133. case uint8:
  134. return uint64(v)
  135. case float32:
  136. return float64(v)
  137. case time.Time:
  138. return v.Format(time.RFC3339Nano)
  139. case time.Duration:
  140. return v.String()
  141. default:
  142. return fmt.Sprintf("%v", v)
  143. }
  144. }