github.com/m3db/m3@v1.5.1-0.20231129193456-75a402aa583b/src/dbnode/integration/generate/generate.go (about) 1 // Copyright (c) 2018 Uber Technologies, Inc. 2 // 3 // Permission is hereby granted, free of charge, to any person obtaining a copy 4 // of this software and associated documentation files (the "Software"), to deal 5 // in the Software without restriction, including without limitation the rights 6 // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 // copies of the Software, and to permit persons to whom the Software is 8 // furnished to do so, subject to the following conditions: 9 // 10 // The above copyright notice and this permission notice shall be included in 11 // all copies or substantial portions of the Software. 12 // 13 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 // THE SOFTWARE. 20 21 package generate 22 23 import ( 24 "bytes" 25 "math/rand" 26 "sort" 27 "time" 28 29 "github.com/m3db/m3/src/dbnode/encoding/testgen" 30 "github.com/m3db/m3/src/dbnode/ts" 31 "github.com/m3db/m3/src/m3ninx/doc" 32 "github.com/m3db/m3/src/x/ident" 33 xtime "github.com/m3db/m3/src/x/time" 34 ) 35 36 // Making SeriesBlock sortable 37 func (l SeriesBlock) Len() int { return len(l) } 38 func (l SeriesBlock) Swap(i, j int) { l[i], l[j] = l[j], l[i] } 39 func (l SeriesBlock) Less(i, j int) bool { 40 return bytes.Compare(l[i].ID.Bytes(), l[j].ID.Bytes()) < 0 41 } 42 43 // Block generates a SeriesBlock based on provided config 44 func Block(conf BlockConfig) SeriesBlock { 45 if conf.NumPoints <= 0 { 46 return nil 47 } 48 r := rand.New(rand.NewSource(time.Now().UnixNano())) 49 testData := make(SeriesBlock, len(conf.IDs)) 50 51 for i, name := range conf.IDs { 52 datapoints := make([]TestValue, 0, conf.NumPoints) 53 for j := 0; j < conf.NumPoints; j++ { 54 timestamp := conf.Start.Add(time.Duration(j) * time.Second) 55 if conf.AnnGen == nil { 56 datapoints = append(datapoints, TestValue{ 57 Datapoint: ts.Datapoint{ 58 TimestampNanos: timestamp, 59 Value: testgen.GenerateFloatVal(r, 3, 1), 60 }, 61 }) 62 } else { 63 datapoints = append(datapoints, TestValue{ 64 Datapoint: ts.Datapoint{ 65 TimestampNanos: timestamp, 66 Value: 0, 67 }, 68 Annotation: conf.AnnGen.Next(), 69 }) 70 } 71 } 72 testData[i] = Series{ 73 ID: ident.StringID(name), 74 Tags: conf.Tags, 75 Data: datapoints, 76 } 77 } 78 return testData 79 } 80 81 // BlocksByStart generates a map of SeriesBlocks keyed by Start time 82 // for the provided configs 83 func BlocksByStart(confs []BlockConfig) SeriesBlocksByStart { 84 seriesMaps := make(map[xtime.UnixNano]SeriesBlock) 85 for _, conf := range confs { 86 key := conf.Start 87 seriesMaps[key] = append(seriesMaps[key], Block(conf)...) 88 } 89 return seriesMaps 90 } 91 92 // ToPointsByTime converts a SeriesBlocksByStart to SeriesDataPointsByTime 93 func ToPointsByTime(seriesMaps SeriesBlocksByStart) SeriesDataPointsByTime { 94 var pointsByTime SeriesDataPointsByTime 95 for _, blks := range seriesMaps { 96 for _, blk := range blks { 97 for _, dp := range blk.Data { 98 pointsByTime = append(pointsByTime, SeriesDataPoint{ 99 ID: blk.ID, 100 Value: dp, 101 }) 102 } 103 } 104 } 105 sort.Sort(pointsByTime) 106 return pointsByTime 107 } 108 109 // ToDocMetadata converts a SeriesBlock to []doc.Metadata 110 func ToDocMetadata(seriesBlock SeriesBlock) []doc.Metadata { 111 docs := make([]doc.Metadata, 0) 112 for _, series := range seriesBlock { 113 fields := make([]doc.Field, 0) 114 for _, t := range series.Tags.Values() { 115 fields = append(fields, doc.Field{ 116 Name: t.Name.Bytes(), 117 Value: t.Value.Bytes(), 118 }) 119 } 120 docs = append(docs, doc.Metadata{ 121 ID: series.ID.Bytes(), 122 Fields: fields, 123 }) 124 } 125 return docs 126 } 127 128 // Dearrange de-arranges the list by the defined percent. 129 func (l SeriesDataPointsByTime) Dearrange(percent float64) SeriesDataPointsByTime { 130 numDis := percent * float64(len(l)) 131 disEvery := int(float64(len(l)) / numDis) 132 133 newArr := make(SeriesDataPointsByTime, 0, len(l)) 134 for i := 0; i < len(l); i += disEvery { 135 ti := i + disEvery 136 if ti >= len(l) { 137 newArr = append(newArr, l[i:]...) 138 break 139 } 140 141 newArr = append(newArr, l[ti]) 142 newArr = append(newArr, l[i:ti]...) 143 } 144 145 return newArr 146 } 147 148 // Making SeriesDataPointsByTimes sortable 149 150 func (l SeriesDataPointsByTime) Len() int { return len(l) } 151 func (l SeriesDataPointsByTime) Swap(i, j int) { l[i], l[j] = l[j], l[i] } 152 func (l SeriesDataPointsByTime) Less(i, j int) bool { 153 if l[i].Value.TimestampNanos != l[j].Value.TimestampNanos { 154 return l[i].Value.TimestampNanos.Before(l[j].Value.TimestampNanos) 155 } 156 return bytes.Compare(l[i].ID.Bytes(), l[j].ID.Bytes()) < 0 157 }