diff --git a/models/points.go b/models/points.go index e4e8863cb8..556b96c031 100644 --- a/models/points.go +++ b/models/points.go @@ -236,13 +236,32 @@ type FieldIterator interface { type Points []Point // Len implements sort.Interface. -func (a Points) Len() int { return len(a) } +func (p Points) Len() int { return len(p) } // Less implements sort.Interface. -func (a Points) Less(i, j int) bool { return a[i].Time().Before(a[j].Time()) } +func (p Points) Less(i, j int) bool { return p[i].Time().Before(p[j].Time()) } // Swap implements sort.Interface. -func (a Points) Swap(i, j int) { a[i], a[j] = a[j], a[i] } +func (p Points) Swap(i, j int) { p[i], p[j] = p[j], p[i] } + +func (p Points) String() string { + const sep = "\n" + switch len(p) { + case 0: + return "" + case 1: + return p[0].String() + } + var b strings.Builder + b.WriteString(p[0].String()) + + for _, s := range p[1:] { + b.WriteString(sep) + b.WriteString(s.String()) + } + + return b.String() +} // point is the default implementation of Point. type point struct { diff --git a/models/points_test.go b/models/points_test.go index 3ffbd38cf6..a3fa6aaec4 100644 --- a/models/points_test.go +++ b/models/points_test.go @@ -160,7 +160,7 @@ func TestPoint_Tags(t *testing.T) { } func TestPoint_StringSize(t *testing.T) { - testPoint_cube(t, func(p models.Point) { + testPointCube(t, func(p models.Point) { l := p.StringSize() s := p.String() @@ -171,7 +171,7 @@ func TestPoint_StringSize(t *testing.T) { } func TestPoint_AppendString(t *testing.T) { - testPoint_cube(t, func(p models.Point) { + testPointCube(t, func(p models.Point) { got := p.AppendString(nil) exp := []byte(p.String()) @@ -181,7 +181,7 @@ func TestPoint_AppendString(t *testing.T) { }) } -func testPoint_cube(t *testing.T, f func(p models.Point)) { +func testPointCube(t *testing.T, f func(p models.Point)) { // heard of a table-driven test? let's make a cube-driven test... tagList := []models.Tags{nil, {models.NewTag([]byte("foo"), []byte("bar"))}, tags} fieldList := []models.Fields{{"a": 42.0}, {"a": 42, "b": "things"}, fields} @@ -1278,6 +1278,37 @@ func TestParsePointUnescape(t *testing.T) { time.Unix(0, 0))) } +func TestPoints_String(t *testing.T) { + tags := models.NewTags(map[string]string{ + "t1": "v1", + "t2": "v2", + }) + pts := make(models.Points, 5) + for i := 0; i < len(pts); i++ { + point, err := models.NewPoint( + "m1", + tags, + models.Fields{ + "f1": i, + }, + time.Unix(0, int64(i)), + ) + if err != nil { + t.Fatalf("unable to create point %v", err) + } + pts[i] = point + } + got := pts.String() + want := `m1,t1=v1,t2=v2 f1=0i 0 +m1,t1=v1,t2=v2 f1=1i 1 +m1,t1=v1,t2=v2 f1=2i 2 +m1,t1=v1,t2=v2 f1=3i 3 +m1,t1=v1,t2=v2 f1=4i 4` + if got != want { + t.Errorf("Points.String() %v| \n want \n%v", got, want) + } +} + func TestParsePointWithTags(t *testing.T) { testParsePoints(t, "cpu,host=serverA,region=us-east value=1.0 1000000000", "mm",