예제 #1
0
func AppendRepeatingValuesTests(p metric.Persistence, t test.Tester) {
	m := clientmodel.Metric{
		clientmodel.MetricNameLabel: "errors_total",
		"controller":                "foo",
		"operation":                 "bar",
	}

	increments := 10
	repetitions := 500

	for i := 0; i < increments; i++ {
		for j := 0; j < repetitions; j++ {
			time := clientmodel.Timestamp(0).Add(time.Duration(i) * time.Hour).Add(time.Duration(j) * time.Second)
			testAppendSamples(p, &clientmodel.Sample{
				Value:     clientmodel.SampleValue(i),
				Timestamp: time,
				Metric:    m,
			}, t)
		}
	}

	v, ok := p.(metric.View)
	if !ok {
		// It's purely a benchmark for a Persistence that is not viewable.
		return
	}

	matchers := labelMatchersFromLabelSet(clientmodel.LabelSet{
		clientmodel.MetricNameLabel: "errors_total",
		"controller":                "foo",
		"operation":                 "bar",
	})

	for i := 0; i < increments; i++ {
		for j := 0; j < repetitions; j++ {
			fingerprints, err := p.GetFingerprintsForLabelMatchers(matchers)
			if err != nil {
				t.Fatal(err)
			}
			if len(fingerprints) != 1 {
				t.Fatalf("expected %d fingerprints, got %d", 1, len(fingerprints))
			}

			time := clientmodel.Timestamp(0).Add(time.Duration(i) * time.Hour).Add(time.Duration(j) * time.Second)
			samples := v.GetValueAtTime(fingerprints[0], time)
			if len(samples) == 0 {
				t.Fatal("expected at least one sample.")
			}

			expected := clientmodel.SampleValue(i)

			for _, sample := range samples {
				if sample.Value != expected {
					t.Fatalf("expected %v value, got %v", expected, sample.Value)
				}
			}
		}
	}
}
예제 #2
0
func newTestStorage(t test.Tester) (storage *tiered.TieredStorage, closer test.Closer) {
	storage, closer = NewTestTieredStorage(t)
	if storage == nil {
		t.Fatal("storage == nil")
	}
	storeMatrix(storage, testMatrix)
	return
}
예제 #3
0
func AppendRepeatingValuesTests(p MetricPersistence, t test.Tester) {
	metric := model.Metric{
		model.MetricNameLabel: "errors_total",
		"controller":          "foo",
		"operation":           "bar",
	}

	increments := 10
	repetitions := 500

	for i := 0; i < increments; i++ {
		for j := 0; j < repetitions; j++ {
			time := time.Time{}.Add(time.Duration(i) * time.Hour).Add(time.Duration(j) * time.Second)
			testAppendSample(p, model.Sample{
				Value:     model.SampleValue(i),
				Timestamp: time,
				Metric:    metric,
			}, t)
		}
	}

	if true {
		// XXX: Purely a benchmark.
		return
	}

	labelSet := model.LabelSet{
		model.MetricNameLabel: "errors_total",
		"controller":          "foo",
		"operation":           "bar",
	}

	for i := 0; i < increments; i++ {
		for j := 0; j < repetitions; j++ {
			fingerprints, err := p.GetFingerprintsForLabelSet(labelSet)
			if err != nil {
				t.Fatal(err)
			}
			if len(fingerprints) != 1 {
				t.Fatalf("expected %d fingerprints, got %d", 1, len(fingerprints))
			}

			time := time.Time{}.Add(time.Duration(i) * time.Hour).Add(time.Duration(j) * time.Second)
			sample, err := p.GetValueAtTime(fingerprints[0], time, StalenessPolicy{})
			if err != nil {
				t.Fatal(err)
			}
			if sample == nil {
				t.Fatal("expected non-nil sample.")
			}

			expected := model.SampleValue(i)

			if sample.Value != expected {
				t.Fatalf("expected %d value, got %d", expected, sample.Value)
			}
		}
	}
}
예제 #4
0
func GetMetricForFingerprintTests(p metric.Persistence, t test.Tester) {
	testAppendSamples(p, &clientmodel.Sample{
		Value:     0,
		Timestamp: 0,
		Metric: clientmodel.Metric{
			"request_type": "your_mom",
		},
	}, t)

	testAppendSamples(p, &clientmodel.Sample{
		Value:     0,
		Timestamp: 0,
		Metric: clientmodel.Metric{
			"request_type": "your_dad",
			"one-off":      "value",
		},
	}, t)

	result, err := p.GetFingerprintsForLabelMatchers(metric.LabelMatchers{{
		Type:  metric.Equal,
		Name:  "request_type",
		Value: "your_mom",
	}})

	if err != nil {
		t.Error(err)
	}

	if len(result) != 1 {
		t.Errorf("Expected one element.")
	}

	m, err := p.GetMetricForFingerprint(result[0])
	if err != nil {
		t.Error(err)
	}

	if m == nil {
		t.Fatal("Did not expect nil.")
	}

	if len(m) != 1 {
		t.Errorf("Expected one-dimensional metric.")
	}

	if m["request_type"] != "your_mom" {
		t.Errorf("Expected metric to match.")
	}

	result, err = p.GetFingerprintsForLabelMatchers(metric.LabelMatchers{{
		Type:  metric.Equal,
		Name:  "request_type",
		Value: "your_dad",
	}})

	if err != nil {
		t.Error(err)
	}

	if len(result) != 1 {
		t.Errorf("Expected one element.")
	}

	m, err = p.GetMetricForFingerprint(result[0])

	if m == nil {
		t.Fatal("Did not expect nil.")
	}

	if err != nil {
		t.Error(err)
	}

	if len(m) != 2 {
		t.Errorf("Expected two-dimensional metric.")
	}

	if m["request_type"] != "your_dad" {
		t.Errorf("Expected metric to match.")
	}

	if m["one-off"] != "value" {
		t.Errorf("Expected metric to match.")
	}

	// Verify that mutating a returned metric does not result in the mutated
	// metric to be returned at the next GetMetricForFingerprint() call.
	m["one-off"] = "new value"
	m, err = p.GetMetricForFingerprint(result[0])

	if m == nil {
		t.Fatal("Did not expect nil.")
	}

	if err != nil {
		t.Error(err)
	}

	if len(m) != 2 {
		t.Errorf("Expected two-dimensional metric.")
	}

	if m["request_type"] != "your_dad" {
		t.Errorf("Expected metric to match.")
	}

	if m["one-off"] != "value" {
		t.Errorf("Expected metric to match.")
	}
}
예제 #5
0
func GetMetricForFingerprintTests(p MetricPersistence, t test.Tester) {
	testAppendSample(p, model.Sample{
		Value:     0,
		Timestamp: time.Time{},
		Metric: model.Metric{
			"request_type": "your_mom",
		},
	}, t)

	testAppendSample(p, model.Sample{
		Value:     0,
		Timestamp: time.Time{},
		Metric: model.Metric{
			"request_type": "your_dad",
			"one-off":      "value",
		},
	}, t)

	result, err := p.GetFingerprintsForLabelSet(model.LabelSet{
		model.LabelName("request_type"): model.LabelValue("your_mom"),
	})

	if err != nil {
		t.Error(err)
	}

	if len(result) != 1 {
		t.Errorf("Expected one element.")
	}

	v, e := p.GetMetricForFingerprint(result[0])
	if e != nil {
		t.Error(e)
	}

	if v == nil {
		t.Fatal("Did not expect nil.")
	}

	metric := *v

	if len(metric) != 1 {
		t.Errorf("Expected one-dimensional metric.")
	}

	if metric["request_type"] != "your_mom" {
		t.Errorf("Expected metric to match.")
	}

	result, err = p.GetFingerprintsForLabelSet(model.LabelSet{
		model.LabelName("request_type"): model.LabelValue("your_dad"),
	})

	if err != nil {
		t.Error(err)
	}

	if len(result) != 1 {
		t.Errorf("Expected one element.")
	}

	v, e = p.GetMetricForFingerprint(result[0])

	if v == nil {
		t.Fatal("Did not expect nil.")
	}

	metric = *v

	if e != nil {
		t.Error(e)
	}

	if len(metric) != 2 {
		t.Errorf("Expected one-dimensional metric.")
	}

	if metric["request_type"] != "your_dad" {
		t.Errorf("Expected metric to match.")
	}

	if metric["one-off"] != "value" {
		t.Errorf("Expected metric to match.")
	}
}
예제 #6
0
func testAppendSample(p MetricPersistence, s model.Sample, t test.Tester) {
	err := p.AppendSample(s)
	if err != nil {
		t.Fatal(err)
	}
}
예제 #7
0
func StochasticTests(persistenceMaker func() (metric.Persistence, test.Closer), t test.Tester) {
	stochastic := func(x int) (success bool) {
		p, closer := persistenceMaker()
		defer closer.Close()
		defer p.Close()

		seed := rand.NewSource(int64(x))
		random := rand.New(seed)

		numberOfMetrics := random.Intn(stochasticMaximumVariance) + 1
		numberOfSharedLabels := random.Intn(stochasticMaximumVariance)
		numberOfUnsharedLabels := random.Intn(stochasticMaximumVariance)
		numberOfSamples := random.Intn(stochasticMaximumVariance) + 2
		numberOfRangeScans := random.Intn(stochasticMaximumVariance)

		metricTimestamps := map[int]map[int64]bool{}
		metricEarliestSample := map[int]int64{}
		metricNewestSample := map[int]int64{}

		for metricIndex := 0; metricIndex < numberOfMetrics; metricIndex++ {
			sample := &clientmodel.Sample{
				Metric: clientmodel.Metric{},
			}

			v := clientmodel.LabelValue(fmt.Sprintf("metric_index_%d", metricIndex))
			sample.Metric[clientmodel.MetricNameLabel] = v

			for sharedLabelIndex := 0; sharedLabelIndex < numberOfSharedLabels; sharedLabelIndex++ {
				l := clientmodel.LabelName(fmt.Sprintf("shared_label_%d", sharedLabelIndex))
				v := clientmodel.LabelValue(fmt.Sprintf("label_%d", sharedLabelIndex))

				sample.Metric[l] = v
			}

			for unsharedLabelIndex := 0; unsharedLabelIndex < numberOfUnsharedLabels; unsharedLabelIndex++ {
				l := clientmodel.LabelName(fmt.Sprintf("metric_index_%d_private_label_%d", metricIndex, unsharedLabelIndex))
				v := clientmodel.LabelValue(fmt.Sprintf("private_label_%d", unsharedLabelIndex))

				sample.Metric[l] = v
			}

			timestamps := map[int64]bool{}
			metricTimestamps[metricIndex] = timestamps
			var newestSample int64 = math.MinInt64
			var oldestSample int64 = math.MaxInt64
			var nextTimestamp func() int64

			nextTimestamp = func() int64 {
				var candidate int64
				candidate = random.Int63n(math.MaxInt32 - 1)

				if _, has := timestamps[candidate]; has {
					// WART
					candidate = nextTimestamp()
				}

				timestamps[candidate] = true

				if candidate < oldestSample {
					oldestSample = candidate
				}

				if candidate > newestSample {
					newestSample = candidate
				}

				return candidate
			}

			// BUG(matt): Invariant of the in-memory database assumes this.
			sortedTimestamps := timeslice{}
			for sampleIndex := 0; sampleIndex < numberOfSamples; sampleIndex++ {
				sortedTimestamps = append(sortedTimestamps, clientmodel.TimestampFromUnix(nextTimestamp()))
			}
			sort.Sort(sortedTimestamps)

			for sampleIndex := 0; sampleIndex < numberOfSamples; sampleIndex++ {
				sample.Timestamp = sortedTimestamps[sampleIndex]
				sample.Value = clientmodel.SampleValue(sampleIndex)

				err := p.AppendSamples(clientmodel.Samples{sample})

				if err != nil {
					t.Error(err)
					return
				}
			}

			metricEarliestSample[metricIndex] = oldestSample
			metricNewestSample[metricIndex] = newestSample

			for sharedLabelIndex := 0; sharedLabelIndex < numberOfSharedLabels; sharedLabelIndex++ {
				matchers := metric.LabelMatchers{{
					Type:  metric.Equal,
					Name:  clientmodel.LabelName(fmt.Sprintf("shared_label_%d", sharedLabelIndex)),
					Value: clientmodel.LabelValue(fmt.Sprintf("label_%d", sharedLabelIndex)),
				}}

				fingerprints, err := p.GetFingerprintsForLabelMatchers(matchers)
				if err != nil {
					t.Error(err)
					return
				}
				if len(fingerprints) == 0 {
					t.Errorf("expected fingerprint count of %d, got %d", 0, len(fingerprints))
					return
				}
			}
		}

		for metricIndex := 0; metricIndex < numberOfMetrics; metricIndex++ {
			for unsharedLabelIndex := 0; unsharedLabelIndex < numberOfUnsharedLabels; unsharedLabelIndex++ {
				labelName := clientmodel.LabelName(fmt.Sprintf("metric_index_%d_private_label_%d", metricIndex, unsharedLabelIndex))
				labelValue := clientmodel.LabelValue(fmt.Sprintf("private_label_%d", unsharedLabelIndex))
				matchers := metric.LabelMatchers{{
					Type:  metric.Equal,
					Name:  labelName,
					Value: labelValue,
				}}

				fingerprints, err := p.GetFingerprintsForLabelMatchers(matchers)
				if err != nil {
					t.Error(err)
					return
				}
				if len(fingerprints) != 1 {
					t.Errorf("expected fingerprint count of %d, got %d", 1, len(fingerprints))
					return
				}
			}

			m := clientmodel.Metric{}
			m[clientmodel.MetricNameLabel] = clientmodel.LabelValue(fmt.Sprintf("metric_index_%d", metricIndex))

			for i := 0; i < numberOfSharedLabels; i++ {
				l := clientmodel.LabelName(fmt.Sprintf("shared_label_%d", i))
				v := clientmodel.LabelValue(fmt.Sprintf("label_%d", i))

				m[l] = v
			}

			for i := 0; i < numberOfUnsharedLabels; i++ {
				l := clientmodel.LabelName(fmt.Sprintf("metric_index_%d_private_label_%d", metricIndex, i))
				v := clientmodel.LabelValue(fmt.Sprintf("private_label_%d", i))

				m[l] = v
			}

			for i := 0; i < numberOfRangeScans; i++ {
				timestamps := metricTimestamps[metricIndex]

				var first int64
				var second int64

				for {
					firstCandidate := random.Int63n(int64(len(timestamps)))
					secondCandidate := random.Int63n(int64(len(timestamps)))

					smallest := int64(-1)
					largest := int64(-1)

					if firstCandidate == secondCandidate {
						continue
					} else if firstCandidate > secondCandidate {
						largest = firstCandidate
						smallest = secondCandidate
					} else {
						largest = secondCandidate
						smallest = firstCandidate
					}

					j := int64(0)
					for i := range timestamps {
						if j == smallest {
							first = i
						} else if j == largest {
							second = i
							break
						}
						j++
					}

					break
				}

				begin := first
				end := second

				if second < first {
					begin, end = second, first
				}

				interval := metric.Interval{
					OldestInclusive: clientmodel.TimestampFromUnix(begin),
					NewestInclusive: clientmodel.TimestampFromUnix(end),
				}

				samples := metric.Values{}
				fp := &clientmodel.Fingerprint{}
				fp.LoadFromMetric(m)
				switch persistence := p.(type) {
				case metric.View:
					samples = persistence.GetRangeValues(fp, interval)
					if len(samples) < 2 {
						t.Fatalf("expected sample count greater than %d, got %d", 2, len(samples))
					}
				case *LevelDBPersistence:
					var err error
					samples, err = levelDBGetRangeValues(persistence, fp, interval)
					if err != nil {
						t.Fatal(err)
					}
					if len(samples) < 2 {
						t.Fatalf("expected sample count greater than %d, got %d", 2, len(samples))
					}
				default:
					t.Error("Unexpected type of metric.Persistence.")
				}
			}
		}

		return true
	}

	if err := quick.Check(stochastic, nil); err != nil {
		t.Error(err)
	}
}
예제 #8
0
func testAppendSamples(p metric.Persistence, s *clientmodel.Sample, t test.Tester) {
	err := p.AppendSamples(clientmodel.Samples{s})
	if err != nil {
		t.Fatal(err)
	}
}