github.com/go-graphite/carbonapi@v0.17.0/expr/functions/aliasByNode/function_test.go (about) 1 package aliasByNode 2 3 import ( 4 "context" 5 "math" 6 "testing" 7 "time" 8 9 "github.com/go-graphite/carbonapi/expr/interfaces" 10 "github.com/go-graphite/carbonapi/expr/metadata" 11 "github.com/go-graphite/carbonapi/expr/types" 12 "github.com/go-graphite/carbonapi/pkg/parser" 13 th "github.com/go-graphite/carbonapi/tests" 14 15 "github.com/go-graphite/carbonapi/expr/functions/aggregate" 16 "github.com/go-graphite/carbonapi/expr/functions/aliasSub" 17 "github.com/go-graphite/carbonapi/expr/functions/perSecond" 18 "github.com/go-graphite/carbonapi/expr/functions/transformNull" 19 ) 20 21 var ( 22 md []interfaces.FunctionMetadata = New("") 23 ) 24 25 func init() { 26 for _, m := range md { 27 metadata.RegisterFunction(m.Name, m.F) 28 } 29 asFunc := aliasSub.New("") 30 for _, m := range asFunc { 31 metadata.RegisterFunction(m.Name, m.F) 32 } 33 tnFunc := transformNull.New("") 34 for _, m := range tnFunc { 35 metadata.RegisterFunction(m.Name, m.F) 36 } 37 psFunc := perSecond.New("") 38 for _, m := range psFunc { 39 metadata.RegisterFunction(m.Name, m.F) 40 } 41 aggFunc := aggregate.New("") 42 for _, m := range aggFunc { 43 metadata.RegisterFunction(m.Name, m.F) 44 } 45 } 46 47 func TestAliasByNode(t *testing.T) { 48 now32 := int64(time.Now().Unix()) 49 50 tests := []th.EvalTestItem{ 51 // issue 517 52 { 53 "aliasByNode(aliasSub(a.b.c.d.e, '(.*)', '0.1.2.@.4'), 2)", 54 map[parser.MetricRequest][]*types.MetricData{ 55 {Metric: "a.b.c.d.e", From: 0, Until: 1}: { 56 types.MakeMetricData("a.b.c.d.e", []float64{8, 2, 4}, 1, now32), 57 }, 58 }, 59 []*types.MetricData{types.MakeMetricData("2", []float64{8, 2, 4}, 1, now32).SetNameTag("a.b.c.d.e")}, 60 }, 61 { 62 Target: "aliasByNode(aliasSub(a.b.c.d.e, '(.*)', '0.1.2.@.4'), 2)", 63 M: map[parser.MetricRequest][]*types.MetricData{ 64 {Metric: "a.b.c.d.e", From: 0, Until: 1}: {types.MakeMetricData("a.b.c.d.e", []float64{1, 2, 3, 4, 5}, 1, now32)}, 65 }, 66 Want: []*types.MetricData{types.MakeMetricData("2", []float64{1, 2, 3, 4, 5}, 1, now32).SetNameTag("a.b.c.d.e")}, 67 }, 68 { 69 Target: "aliasByNode(aliasSub(transformNull(metric1.foo.bar.ba*, 0), 'baz', 'word'), 2, 3)", 70 M: map[parser.MetricRequest][]*types.MetricData{ 71 {Metric: "metric1.foo.bar.ba*", From: 0, Until: 1}: {types.MakeMetricData("metric1.foo.bar.baz", []float64{1, 2, 3, 4, 5}, 1, now32)}, 72 }, 73 Want: []*types.MetricData{types.MakeMetricData("bar.word", []float64{1, 2, 3, 4, 5}, 1, now32).SetTag("transformNull", "0").SetNameTag("metric1.foo.bar.baz")}, 74 }, 75 { 76 Target: "aliasByNode(metric1.foo.bar.baz,1)", 77 M: map[parser.MetricRequest][]*types.MetricData{ 78 {Metric: "metric1.foo.bar.baz", From: 0, Until: 1}: {types.MakeMetricData("metric1.foo.bar.baz", []float64{1, 2, 3, 4, 5}, 1, now32)}, 79 }, 80 Want: []*types.MetricData{types.MakeMetricData("foo", []float64{1, 2, 3, 4, 5}, 1, now32).SetNameTag("metric1.foo.bar.baz")}, 81 }, 82 { 83 Target: "aliasByNode(metric1.foo.bar.baz,1,3)", 84 M: map[parser.MetricRequest][]*types.MetricData{ 85 {Metric: "metric1.foo.bar.baz", From: 0, Until: 1}: {types.MakeMetricData("metric1.foo.bar.baz", []float64{1, 2, 3, 4, 5}, 1, now32)}, 86 }, 87 Want: []*types.MetricData{types.MakeMetricData("foo.baz", 88 []float64{1, 2, 3, 4, 5}, 1, now32).SetNameTag("metric1.foo.bar.baz")}, 89 }, 90 { 91 Target: "aliasByNode(metric1.foo.bar.baz,1,-2)", 92 M: map[parser.MetricRequest][]*types.MetricData{ 93 {Metric: "metric1.foo.bar.baz", From: 0, Until: 1}: {types.MakeMetricData("metric1.foo.bar.baz", []float64{1, 2, 3, 4, 5}, 1, now32)}, 94 }, 95 Want: []*types.MetricData{types.MakeMetricData("foo.bar", 96 []float64{1, 2, 3, 4, 5}, 1, now32).SetNameTag("metric1.foo.bar.baz")}, 97 }, 98 { 99 Target: `aliasByTags(*, "foo")`, 100 M: map[parser.MetricRequest][]*types.MetricData{ 101 {Metric: "*", From: 0, Until: 1}: {types.MakeMetricData("metric1.foo.bar.baz;foo=bar;baz=bam", []float64{1, 2, 3, 4, 5}, 1, now32)}, 102 }, 103 Want: []*types.MetricData{types.MakeMetricData("bar", []float64{1, 2, 3, 4, 5}, 1, now32).SetTag("foo", "bar").SetTag("baz", "bam").SetNameTag("metric1.foo.bar.baz")}, 104 }, 105 { 106 Target: `aliasByTags(*, "foo", "name")`, 107 M: map[parser.MetricRequest][]*types.MetricData{ 108 {Metric: "*", From: 0, Until: 1}: {types.MakeMetricData("metric1;foo=bar", []float64{1, 2, 3, 4, 5}, 1, now32)}, 109 }, 110 Want: []*types.MetricData{types.MakeMetricData("bar.metric1", []float64{1, 2, 3, 4, 5}, 1, now32).SetTag("foo", "bar").SetNameTag("metric1")}, 111 }, 112 { 113 Target: `aliasByTags(*, 2, "blah", "foo", 1)`, 114 M: map[parser.MetricRequest][]*types.MetricData{ 115 {Metric: "*", From: 0, Until: 1}: {types.MakeMetricData("base.metric1;foo=bar;baz=bam", []float64{1, 2, 3, 4, 5}, 1, now32)}, 116 }, 117 Want: []*types.MetricData{types.MakeMetricData(".bar.metric1", []float64{1, 2, 3, 4, 5}, 1, now32).SetTag("foo", "bar").SetTag("baz", "bam").SetNameTag("base.metric1")}, 118 }, 119 { 120 Target: `aliasByTags(*, 2, "baz", "foo", 1)`, 121 M: map[parser.MetricRequest][]*types.MetricData{ 122 {Metric: "*", From: 0, Until: 1}: {types.MakeMetricData("base.metric1;foo=bar;baz=bam", []float64{1, 2, 3, 4, 5}, 1, now32)}, 123 }, 124 Want: []*types.MetricData{types.MakeMetricData("bam.bar.metric1", []float64{1, 2, 3, 4, 5}, 1, now32).SetTag("foo", "bar").SetTag("baz", "bam").SetNameTag("base.metric1")}, 125 }, 126 { 127 Target: `aliasByTags(perSecond(*), 'name')`, 128 M: map[parser.MetricRequest][]*types.MetricData{ 129 {Metric: "*", From: 0, Until: 1}: {types.MakeMetricData("base.metric1;foo=bar;baz=bam", []float64{1, 2, 3, 4, 5}, 1, now32)}, 130 }, 131 Want: []*types.MetricData{types.MakeMetricData("base.metric1", []float64{math.NaN(), 1, 1, 1, 1}, 1, now32).SetTag("foo", "bar").SetTag("baz", "bam").SetTag("perSecond", "1").SetNameTag("base.metric1")}, 132 }, 133 { 134 Target: "aliasByNode(metric1.fo*.bar.baz,1,3)", 135 M: map[parser.MetricRequest][]*types.MetricData{ 136 {Metric: "metric1.fo*.bar.baz", From: 0, Until: 1}: {types.MakeMetricData("metric1.foo==.bar.baz", []float64{1, 2, 3, 4, 5}, 1, now32)}, 137 }, 138 Want: []*types.MetricData{types.MakeMetricData("foo==.baz", 139 []float64{1, 2, 3, 4, 5}, 1, now32).SetNameTag("metric1.foo==.bar.baz")}, 140 }, 141 { 142 Target: `aliasByTags(*, 2, "baz", "foo", 1)`, 143 M: map[parser.MetricRequest][]*types.MetricData{ 144 {Metric: "*", From: 0, Until: 1}: {types.MakeMetricData("base.metric1;foo=bar=;baz=bam==", []float64{1, 2, 3, 4, 5}, 1, now32)}, 145 }, 146 Want: []*types.MetricData{types.MakeMetricData("bam==.bar=.metric1", []float64{1, 2, 3, 4, 5}, 1, now32).SetTag("foo", "bar=").SetTag("baz", "bam==").SetNameTag("base.metric1")}, 147 }, 148 // extract nodes with sumSeries 149 { 150 Target: `aliasByNode(sumSeries(metric.{a,b}*.b), 1, 2)`, 151 M: map[parser.MetricRequest][]*types.MetricData{ 152 {Metric: "metric.{a,b}*.b", From: 0, Until: 1}: { 153 types.MakeMetricData("metric.a1.b", []float64{1, math.NaN(), 2, 3, 4, 5}, 1, now32), 154 types.MakeMetricData("metric.b2.b", []float64{2, math.NaN(), 3, math.NaN(), 5, 6}, 1, now32), 155 types.MakeMetricData("metric.c2.b", []float64{3, math.NaN(), 4, 5, 6, math.NaN()}, 1, now32), 156 }, 157 }, 158 Want: []*types.MetricData{types.MakeMetricData("{a,b}*.b", []float64{6, math.NaN(), 9, 8, 15, 11}, 1, now32).SetTag("aggregatedBy", "sum").SetNameTag("metric.{a,b}*.b")}, 159 }, 160 // extract tags from seriesByTag 161 { 162 Target: `aliasByTags(sumSeries(seriesByTag('tag2=value*', 'name=metric')), 'tag2', 'name')`, 163 M: map[parser.MetricRequest][]*types.MetricData{ 164 {Metric: "seriesByTag('tag2=value*', 'name=metric')", From: 0, Until: 1}: { 165 types.MakeMetricData("metric;tag1=value1;tag2=value21", []float64{1, math.NaN(), 2, 3, 4, 5}, 1, now32), 166 types.MakeMetricData("metric;tag2=value21;tag3=value3", []float64{2, math.NaN(), 3, math.NaN(), 5, 6}, 1, now32), 167 types.MakeMetricData("metric;tag2=value21;tag3=value3", []float64{3, math.NaN(), 4, 5, 6, math.NaN()}, 1, now32), 168 }, 169 {Metric: "metric", From: 0, Until: 1}: {types.MakeMetricData("metric", []float64{2, math.NaN(), 3, math.NaN(), 5, 11}, 1, now32)}, 170 }, 171 // Want: []*types.MetricData{types.MakeMetricData("value____.metric", []float64{6, math.NaN(), 9, 8, 15, 11}, 1, now32)}, 172 Want: []*types.MetricData{ 173 types.MakeMetricData("value21.metric", []float64{6, math.NaN(), 9, 8, 15, 11}, 1, now32).SetTag("aggregatedBy", "sum").SetTag("tag2", "value21").SetNameTag("metric")}, 174 }, 175 // TODO msaf1980: tests with extractTagsFromArgs = true 176 } 177 178 for _, tt := range tests { 179 testName := tt.Target 180 t.Run(testName, func(t *testing.T) { 181 eval := th.EvaluatorFromFuncWithMetadata(metadata.FunctionMD.Functions) 182 th.TestEvalExpr(t, eval, &tt) 183 }) 184 } 185 186 } 187 188 func BenchmarkAliasByNode(b *testing.B) { 189 target := "aliasByNode(metric1.foo.bar.baz,1,3)" 190 metrics := map[parser.MetricRequest][]*types.MetricData{ 191 {Metric: "metric1.foo.bar.baz", From: 0, Until: 1}: { 192 types.MakeMetricData("metric1.foo.bar.baz", []float64{1, 2, 3, 4, 5}, 1, 1), 193 }, 194 } 195 196 eval := th.EvaluatorFromFuncWithMetadata(metadata.FunctionMD.Functions) 197 exp, _, err := parser.ParseExpr(target) 198 if err != nil { 199 b.Fatalf("failed to parse %s: %+v", target, err) 200 } 201 202 b.ResetTimer() 203 for n := 0; n < b.N; n++ { 204 g, err := eval.Eval(context.Background(), exp, 0, 1, metrics) 205 if err != nil { 206 b.Fatalf("failed to eval %s: %+v", target, err) 207 } 208 _ = g 209 } 210 }