-
Notifications
You must be signed in to change notification settings - Fork 116
/
Copy pathdata_to_point.go
96 lines (91 loc) · 2.69 KB
/
data_to_point.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
package api
import (
"fmt"
"reflect"
"strings"
"time"
"github.com/influxdata/influxdb-client-go/v2/api/write"
)
// DataToPoint converts custom point structures into a Point.
// Each visible field of the point on input must be annotated with
// 'lp' prefix and values measurement,tag, field or timestamp.
// Valid point must contain measurement and at least one field.
//
// A field with timestamp must be of a type time.Time
//
// type TemperatureSensor struct {
// Measurement string `lp:"measurement"`
// Sensor string `lp:"tag,sensor"`
// ID string `lp:"tag,device_id"`
// Temp float64 `lp:"field,temperature"`
// Hum int `lp:"field,humidity"`
// Time time.Time `lp:"timestamp,temperature"`
// Description string `lp:"-"`
// }
func DataToPoint(x interface{}) (*write.Point, error) {
t := reflect.TypeOf(x)
v := reflect.ValueOf(x)
if t.Kind() == reflect.Ptr {
t = t.Elem()
v = v.Elem()
}
if t.Kind() != reflect.Struct {
return nil, fmt.Errorf("cannot use %v as point", t)
}
fields := reflect.VisibleFields(t)
var measurement = ""
var lpTags = make(map[string]string)
var lpFields = make(map[string]interface{})
var lpTime time.Time
for _, f := range fields {
name := f.Name
if tag, ok := f.Tag.Lookup("lp"); ok {
if tag == "-" {
continue
}
parts := strings.Split(tag, ",")
if len(parts) > 2 {
return nil, fmt.Errorf("multiple tag attributes are not supported")
}
typ := parts[0]
if len(parts) == 2 {
name = parts[1]
}
t := getFieldType(v.FieldByIndex(f.Index))
if !validFieldType(t) {
return nil, fmt.Errorf("cannot use field '%s' of type '%v' as to create a point", f.Name, t)
}
switch typ {
case "measurement":
if measurement != "" {
return nil, fmt.Errorf("multiple measurement fields")
}
measurement = v.FieldByIndex(f.Index).String()
case "tag":
if name == "" {
return nil, fmt.Errorf("cannot use field '%s': invalid lp tag name \"\"", f.Name)
}
lpTags[name] = v.FieldByIndex(f.Index).String()
case "field":
if name == "" {
return nil, fmt.Errorf("cannot use field '%s': invalid lp field name \"\"", f.Name)
}
lpFields[name] = v.FieldByIndex(f.Index).Interface()
case "timestamp":
if f.Type != timeType {
return nil, fmt.Errorf("cannot use field '%s' as a timestamp", f.Name)
}
lpTime = v.FieldByIndex(f.Index).Interface().(time.Time)
default:
return nil, fmt.Errorf("invalid tag %s", typ)
}
}
}
if measurement == "" {
return nil, fmt.Errorf("no struct field with tag 'measurement'")
}
if len(lpFields) == 0 {
return nil, fmt.Errorf("no struct field with tag 'field'")
}
return write.NewPoint(measurement, lpTags, lpFields, lpTime), nil
}