Skip to content

Commit 496f4bc

Browse files
committed
chore: refactor DataToPoint
1 parent 1342ca6 commit 496f4bc

File tree

2 files changed

+86
-78
lines changed

2 files changed

+86
-78
lines changed

api/data_to_point.go

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

api/write.go

Lines changed: 0 additions & 78 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,6 @@ package api
66

77
import (
88
"context"
9-
"fmt"
10-
"reflect"
119
"strings"
1210
"sync"
1311
"sync/atomic"
@@ -268,79 +266,3 @@ func (w *WriteAPIImpl) WritePoint(point *write.Point) {
268266
func buffer(lines []string) string {
269267
return strings.Join(lines, "")
270268
}
271-
272-
// DataToPoint converts custom point structures into a Point.
273-
// Each visible field of the point on input must be annotated with
274-
// 'lp' prefix and values measurement,tag, field or timestamp.
275-
// Valid point must contain measurement and at least one field.
276-
//
277-
// A field with timestamp must be of a type time.Time
278-
//
279-
// type TemperatureSensor struct {
280-
// Measurement string `lp:"measurement"`
281-
// Sensor string `lp:"tag,sensor"`
282-
// ID string `lp:"tag,device_id"`
283-
// Temp float64 `lp:"field,temperature"`
284-
// Hum int `lp:"field,humidity"`
285-
// Time time.Time `lp:"timestamp,temperature"`
286-
// Description string `lp:"-"`
287-
// }
288-
func DataToPoint(x interface{}) (*write.Point, error) {
289-
if err := checkContainerType(x, false, "point"); err != nil {
290-
return nil, err
291-
}
292-
t := reflect.TypeOf(x)
293-
v := reflect.ValueOf(x)
294-
if t.Kind() == reflect.Ptr {
295-
t = t.Elem()
296-
v = v.Elem()
297-
}
298-
fields := reflect.VisibleFields(t)
299-
300-
var measurement string = ""
301-
var lpTags = make(map[string]string)
302-
var lpFields = make(map[string]interface{})
303-
var lpTime time.Time
304-
305-
for _, f := range fields {
306-
name := f.Name
307-
if tag, ok := f.Tag.Lookup("lp"); ok {
308-
if tag == "-" {
309-
continue
310-
}
311-
parts := strings.Split(tag, ",")
312-
if len(parts) > 2 {
313-
return nil, fmt.Errorf("multiple tag attributes are not supported")
314-
}
315-
typ := parts[0]
316-
if len(parts) == 2 {
317-
name = parts[1]
318-
}
319-
switch typ {
320-
case "measurement":
321-
if measurement != "" {
322-
return nil, fmt.Errorf("multiple measurement fields")
323-
}
324-
measurement = v.FieldByIndex(f.Index).String()
325-
case "tag":
326-
lpTags[name] = v.FieldByIndex(f.Index).String()
327-
case "field":
328-
lpFields[name] = v.FieldByIndex(f.Index).Interface()
329-
case "timestamp":
330-
if f.Type != timeType {
331-
return nil, fmt.Errorf("cannot use field '%s' as a timestamp", f.Name)
332-
}
333-
lpTime = v.FieldByIndex(f.Index).Interface().(time.Time)
334-
default:
335-
return nil, fmt.Errorf("invalid tag %s", typ)
336-
}
337-
}
338-
}
339-
if measurement == "" {
340-
return nil, fmt.Errorf("no struct field with tag 'measurement'")
341-
}
342-
if len(lpFields) == 0 {
343-
return nil, fmt.Errorf("no struct field with tag 'field'")
344-
}
345-
return write.NewPoint(measurement, lpTags, lpFields, lpTime), nil
346-
}

0 commit comments

Comments
 (0)