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  }