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))
}
Example #5
0
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
}