func (s *MySuite) TestMeanByTwoLabels(c *C) { input := []*oproto.ValueStream{ <-s.store.Reader(context.Background(), variable.NewFromString("/test{host=a,job=foo,other=w}")), <-s.store.Reader(context.Background(), variable.NewFromString("/test{host=a,job=bar,other=x}")), <-s.store.Reader(context.Background(), variable.NewFromString("/test{host=b,job=foo,other=y}")), <-s.store.Reader(context.Background(), variable.NewFromString("/test{host=b,job=bar,other=z}")), } output := aggregations.Mean([]string{"host", "job"}, input) c.Assert(output, Not(IsNil)) c.Assert(len(output), Equals, 4) // Check that there are 4 output streams with the correct number of output labels checkHostsAndJobs(c, output, 2, 2, 2, 2) }
func (s *MySuite) TestMeanBy(c *C) { input := []*oproto.ValueStream{ <-s.store.Reader(context.Background(), variable.NewFromString("/test{host=a,job=foo,other=w}")), <-s.store.Reader(context.Background(), variable.NewFromString("/test{host=a,job=bar,other=x}")), <-s.store.Reader(context.Background(), variable.NewFromString("/test{host=b,job=foo,other=y}")), <-s.store.Reader(context.Background(), variable.NewFromString("/test{host=b,job=bar,other=z}")), } output := aggregations.Mean([]string{"host"}, input) c.Assert(output, Not(IsNil)) c.Assert(len(output), Equals, 2) // Check that there are two output streams, as there are two distinct hosts checkHostsAndJobs(c, output, 1, 1, 0, 0) for _, stream := range output { c.Assert(len(stream.Value), Equals, 11) if stream.Variable.Label["host"] == "a" { checkValue(c, stream.Value[0], 60*0, float64((20*1+20*1)/2)) checkValue(c, stream.Value[1], 60*1, float64((20*2+20*2)/2)) checkValue(c, stream.Value[2], 60*2, float64((20*3+20*3)/2)) checkValue(c, stream.Value[3], 60*3, float64((20*4+20*4)/2)) checkValue(c, stream.Value[4], 60*4, float64((20*5+20*5)/2)) checkValue(c, stream.Value[5], 60*5, float64((20*6+20*6)/2)) checkValue(c, stream.Value[6], 60*6, float64((20*7+20*7)/2)) checkValue(c, stream.Value[7], 60*7, float64((20*8+20*8)/2)) checkValue(c, stream.Value[8], 60*8, float64((20*9+20*9)/2)) checkValue(c, stream.Value[9], 60*9, float64((20*10+20*10)/2)) checkValue(c, stream.Value[10], 60*10, float64((20*11+20*11)/2)) } else if stream.Variable.Label["host"] == "b" { checkValue(c, stream.Value[0], 60*0, float64((40*1+40*1)/2)) checkValue(c, stream.Value[1], 60*1, float64((40*2+40*2)/2)) checkValue(c, stream.Value[2], 60*2, float64((40*3+40*3)/2)) checkValue(c, stream.Value[3], 60*3, float64((40*4+40*4)/2)) checkValue(c, stream.Value[4], 60*4, float64((40*5+40*5)/2)) checkValue(c, stream.Value[5], 60*5, float64((40*6+40*6)/2)) checkValue(c, stream.Value[6], 60*6, float64((40*7+40*7)/2)) checkValue(c, stream.Value[7], 60*7, float64((40*8+40*8)/2)) checkValue(c, stream.Value[8], 60*8, float64((40*9+40*9)/2)) checkValue(c, stream.Value[9], 60*9, float64((40*10+40*10)/2)) checkValue(c, stream.Value[10], 60*10, float64((40*11+40*11)/2)) } else { c.Fail() } } }
func (s *MySuite) TestMeanByJob(c *C) { input := []*oproto.ValueStream{ <-s.store.Reader(context.Background(), variable.NewFromString("/test{host=a,job=foo,other=w}")), <-s.store.Reader(context.Background(), variable.NewFromString("/test{host=a,job=bar,other=x}")), <-s.store.Reader(context.Background(), variable.NewFromString("/test{host=b,job=foo,other=y}")), <-s.store.Reader(context.Background(), variable.NewFromString("/test{host=b,job=bar,other=z}")), } output := aggregations.Mean([]string{"job"}, input) c.Assert(output, Not(IsNil)) c.Assert(len(output), Equals, 2) // Check that there are two output streams, as there are two distinct hosts checkHostsAndJobs(c, output, 0, 0, 1, 1) // First stream is job=foo stream := output[0] c.Assert(len(stream.Value), Equals, 11) checkValue(c, stream.Value[0], 60*0, float64((20*1+40*1)/2)) checkValue(c, stream.Value[1], 60*1, float64((20*2+40*2)/2)) checkValue(c, stream.Value[2], 60*2, float64((20*3+40*3)/2)) checkValue(c, stream.Value[3], 60*3, float64((20*4+40*4)/2)) checkValue(c, stream.Value[4], 60*4, float64((20*5+40*5)/2)) checkValue(c, stream.Value[5], 60*5, float64((20*6+40*6)/2)) checkValue(c, stream.Value[6], 60*6, float64((20*7+40*7)/2)) checkValue(c, stream.Value[7], 60*7, float64((20*8+40*8)/2)) checkValue(c, stream.Value[8], 60*8, float64((20*9+40*9)/2)) checkValue(c, stream.Value[9], 60*9, float64((20*10+40*10)/2)) checkValue(c, stream.Value[10], 60*10, float64((20*11+40*11)/2)) // Second stream is job=bar stream = output[1] c.Assert(len(stream.Value), Equals, 11) checkValue(c, stream.Value[0], 60*0, float64((20*1+40*1)/2)) checkValue(c, stream.Value[1], 60*1, float64((20*2+40*2)/2)) checkValue(c, stream.Value[2], 60*2, float64((20*3+40*3)/2)) checkValue(c, stream.Value[3], 60*3, float64((20*4+40*4)/2)) checkValue(c, stream.Value[4], 60*4, float64((20*5+40*5)/2)) checkValue(c, stream.Value[5], 60*5, float64((20*6+40*6)/2)) checkValue(c, stream.Value[6], 60*6, float64((20*7+40*7)/2)) checkValue(c, stream.Value[7], 60*7, float64((20*8+40*8)/2)) checkValue(c, stream.Value[8], 60*8, float64((20*9+40*9)/2)) checkValue(c, stream.Value[9], 60*9, float64((20*10+40*10)/2)) checkValue(c, stream.Value[10], 60*10, float64((20*11+40*11)/2)) }
func (s *MySuite) TestMean(c *C) { input := []*oproto.ValueStream{ <-s.store.Reader(context.Background(), variable.NewFromString("/test{host=a}")), <-s.store.Reader(context.Background(), variable.NewFromString("/test{host=b}")), } output := aggregations.Mean(nil, input) c.Assert(output, Not(IsNil)) c.Assert(len(output), Equals, 1) stream := output[0] c.Assert(len(stream.Value), Equals, 11) checkValue(c, stream.Value[0], 60*0, float64((20*1+40*1)/2)) checkValue(c, stream.Value[1], 60*1, float64((20*2+40*2)/2)) checkValue(c, stream.Value[2], 60*2, float64((20*3+40*3)/2)) checkValue(c, stream.Value[3], 60*3, float64((20*4+40*4)/2)) checkValue(c, stream.Value[4], 60*4, float64((20*5+40*5)/2)) checkValue(c, stream.Value[5], 60*5, float64((20*6+40*6)/2)) checkValue(c, stream.Value[6], 60*6, float64((20*7+40*7)/2)) checkValue(c, stream.Value[7], 60*7, float64((20*8+40*8)/2)) checkValue(c, stream.Value[8], 60*8, float64((20*9+40*9)/2)) checkValue(c, stream.Value[9], 60*9, float64((20*10+40*10)/2)) checkValue(c, stream.Value[10], 60*10, float64((20*11+40*11)/2)) }
func RunQuery(ctx context.Context, query *oproto.Query, store datastore.ReadableStore) (chan *oproto.ValueStream, error) { log.Printf("Running query %v", query) output := make(chan *oproto.ValueStream, 100) go func() { defer close(output) for _, v := range query.Variable { log.Printf("Returning variable %s", variable.ProtoToString(v)) for stream := range store.Reader(ctx, variable.NewFromProto(v)) { if stream != nil { outputStream := &oproto.ValueStream{Variable: stream.Variable} stv := variable.NewFromProto(stream.Variable) for _, v := range stream.Value { if stv.TimestampInsideRange(v.Timestamp) { outputStream.Value = append(outputStream.Value, v) } } output <- outputStream } } } for _, child := range query.Aggregation { log.Printf("Running child aggregation") input := []*oproto.ValueStream{} for _, q := range child.Query { o, err := RunQuery(ctx, q, store) if err != nil { return } for stream := range o { input = append(input, stream) } } log.Printf("Child aggregation returned output") o := []*oproto.ValueStream{} switch child.Type { case oproto.StreamAggregation_NONE: o = input case oproto.StreamAggregation_MEAN: o = aggregations.Mean(child.Label, input) case oproto.StreamAggregation_MAX: o = aggregations.Max(child.Label, input) case oproto.StreamAggregation_MIN: o = aggregations.Min(child.Label, input) case oproto.StreamAggregation_MEDIAN: o = aggregations.Median(child.Label, input) case oproto.StreamAggregation_SUM: o = aggregations.Sum(child.Label, input) case oproto.StreamAggregation_STDDEV: o = aggregations.StdDev(child.Label, input) case oproto.StreamAggregation_PERCENTILE: o = aggregations.Percentile(child.Label, child.Param, input) } for _, stream := range o { //log.Println(openinstrument.ProtoText(stream)) output <- stream } } for _, child := range query.Mutation { log.Printf("Running child mutation") input, err := RunQuery(ctx, child.Query, store) if err != nil { log.Printf("Error in child mutation: %s", err) return } for stream := range input { var outStream *oproto.ValueStream switch child.Type { case oproto.StreamMutation_MEAN: outStream = mutations.Mean(stream) case oproto.StreamMutation_INTERPOLATE: outStream = mutations.Interpolate(uint64(child.Param), stream) case oproto.StreamMutation_MIN: outStream = mutations.Min(uint64(child.Param), stream) case oproto.StreamMutation_MAX: outStream = mutations.Max(uint64(child.Param), stream) case oproto.StreamMutation_FIRST: outStream = mutations.First(uint64(child.Param), stream) case oproto.StreamMutation_LAST: outStream = mutations.Last(uint64(child.Param), stream) case oproto.StreamMutation_RATE: outStream = mutations.Rate(stream) case oproto.StreamMutation_ROOT: outStream = mutations.Root(child.Param, stream) case oproto.StreamMutation_POWER: outStream = mutations.Power(child.Param, stream) case oproto.StreamMutation_ADD: outStream = mutations.Add(child.Param, stream) case oproto.StreamMutation_MULTIPLY: outStream = mutations.Multiply(child.Param, stream) case oproto.StreamMutation_RATE_SIGNED: outStream = mutations.SignedRate(stream) case oproto.StreamMutation_MOVING_AVERAGE: outStream = mutations.MovingAverage(uint64(child.Param), stream) } if outStream == nil { log.Printf("No stream returned from mutation") continue } outStream.Variable = stream.Variable output <- outStream } } }() return output, nil }