func AppendSampleAsPureSparseAppendTests(p metric.Persistence, t test.Tester) { appendSample := func(x int) (success bool) { v := clientmodel.SampleValue(x) ts := clientmodel.TimestampFromUnix(int64(x)) labelName := clientmodel.LabelName(x) labelValue := clientmodel.LabelValue(x) l := clientmodel.Metric{labelName: labelValue} sample := &clientmodel.Sample{ Value: v, Timestamp: ts, Metric: l, } err := p.AppendSamples(clientmodel.Samples{sample}) success = err == nil if !success { t.Error(err) } return } if err := quick.Check(appendSample, nil); err != nil { t.Error(err) } }
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) } } } } }
func storeMatrix(storage metric.Persistence, matrix ast.Matrix) (err error) { pendingSamples := clientmodel.Samples{} for _, sampleSet := range matrix { for _, sample := range sampleSet.Values { pendingSamples = append(pendingSamples, &clientmodel.Sample{ Metric: sampleSet.Metric, Value: sample.Value, Timestamp: sample.Timestamp, }) } } err = storage.AppendSamples(pendingSamples) return }
func ReadEmptyTests(p metric.Persistence, t test.Tester) { hasLabelPair := func(x int) (success bool) { fingerprints, err := p.GetFingerprintsForLabelMatchers(metric.LabelMatchers{{ Type: metric.Equal, Name: clientmodel.LabelName(string(x)), Value: clientmodel.LabelValue(string(x)), }}) if err != nil { t.Error(err) return } success = len(fingerprints) == 0 if !success { t.Errorf("unexpected fingerprint length %d, got %d", 0, len(fingerprints)) } return } err := quick.Check(hasLabelPair, nil) if err != nil { t.Error(err) return } hasLabelName := func(x int) (success bool) { labelName := clientmodel.LabelName(string(x)) values, err := p.GetLabelValuesForLabelName(labelName) if err != nil { t.Error(err) return } success = len(values) == 0 if !success { t.Errorf("unexpected values length %d, got %d", 0, len(values)) } return } err = quick.Check(hasLabelName, nil) if err != nil { t.Error(err) return } }
func AppendSampleAsPureSingleEntityAppendTests(p metric.Persistence, t test.Tester) { appendSample := func(x int) bool { sample := &clientmodel.Sample{ Value: clientmodel.SampleValue(x), Timestamp: clientmodel.TimestampFromUnix(int64(x)), Metric: clientmodel.Metric{clientmodel.MetricNameLabel: "my_metric"}, } err := p.AppendSamples(clientmodel.Samples{sample}) return err == nil } if err := quick.Check(appendSample, nil); err != nil { t.Error(err) } }
func GetLabelValuesForLabelNameTests(p metric.Persistence, t test.Tester) { testAppendSamples(p, &clientmodel.Sample{ Value: 0, Timestamp: 0, Metric: clientmodel.Metric{ clientmodel.MetricNameLabel: "my_metric", "request_type": "create", "result": "success", }, }, t) testAppendSamples(p, &clientmodel.Sample{ Value: 0, Timestamp: 0, Metric: clientmodel.Metric{ clientmodel.MetricNameLabel: "my_metric", "request_type": "delete", "outcome": "failure", }, }, t) expectedIndex := map[clientmodel.LabelName]clientmodel.LabelValues{ clientmodel.MetricNameLabel: {"my_metric"}, "request_type": {"create", "delete"}, "result": {"success"}, "outcome": {"failure"}, } for name, expected := range expectedIndex { actual, err := p.GetLabelValuesForLabelName(name) if err != nil { t.Fatalf("Error getting values for label %s: %v", name, err) } if len(actual) != len(expected) { t.Fatalf("Number of values don't match for label %s: got %d; want %d", name, len(actual), len(expected)) } for i := range expected { if actual[i] != expected[i] { t.Fatalf("%d. Got %s; want %s", i, actual[i], expected[i]) } } } }
func GetFingerprintsForLabelSetUsesAndForLabelMatchingTests(p metric.Persistence, t test.Tester) { metrics := []clientmodel.LabelSet{ {clientmodel.MetricNameLabel: "request_metrics_latency_equal_tallying_microseconds", "instance": "http://localhost:9090/metrics.json", "percentile": "0.010000"}, {clientmodel.MetricNameLabel: "requests_metrics_latency_equal_accumulating_microseconds", "instance": "http://localhost:9090/metrics.json", "percentile": "0.010000"}, {clientmodel.MetricNameLabel: "requests_metrics_latency_logarithmic_accumulating_microseconds", "instance": "http://localhost:9090/metrics.json", "percentile": "0.010000"}, {clientmodel.MetricNameLabel: "requests_metrics_latency_logarithmic_tallying_microseconds", "instance": "http://localhost:9090/metrics.json", "percentile": "0.010000"}, {clientmodel.MetricNameLabel: "targets_healthy_scrape_latency_ms", "instance": "http://localhost:9090/metrics.json", "percentile": "0.010000"}, } for _, metric := range metrics { m := clientmodel.Metric{} for k, v := range metric { m[clientmodel.LabelName(k)] = clientmodel.LabelValue(v) } testAppendSamples(p, &clientmodel.Sample{ Value: clientmodel.SampleValue(0.0), Timestamp: clientmodel.Now(), Metric: m, }, t) } labelSet := clientmodel.LabelSet{ clientmodel.MetricNameLabel: "targets_healthy_scrape_latency_ms", "percentile": "0.010000", } fingerprints, err := p.GetFingerprintsForLabelMatchers(labelMatchersFromLabelSet(labelSet)) if err != nil { t.Errorf("could not get labels: %s", err) } if len(fingerprints) != 1 { t.Errorf("did not get a single metric as is expected, got %s", fingerprints) } }
func AppendSampleAsSparseAppendWithReadsTests(p metric.Persistence, t test.Tester) { appendSample := func(x int) (success bool) { v := clientmodel.SampleValue(x) ts := clientmodel.TimestampFromUnix(int64(x)) labelName := clientmodel.LabelName(x) labelValue := clientmodel.LabelValue(x) l := clientmodel.Metric{labelName: labelValue} sample := &clientmodel.Sample{ Value: v, Timestamp: ts, Metric: l, } err := p.AppendSamples(clientmodel.Samples{sample}) if err != nil { t.Error(err) return } values, err := p.GetLabelValuesForLabelName(labelName) if err != nil { t.Error(err) return } if len(values) != 1 { t.Errorf("expected label values count of %d, got %d", 1, len(values)) return } fingerprints, err := p.GetFingerprintsForLabelMatchers(metric.LabelMatchers{{ Type: metric.Equal, Name: labelName, Value: labelValue, }}) if err != nil { t.Error(err) return } if len(fingerprints) != 1 { t.Errorf("expected fingerprint count of %d, got %d", 1, len(fingerprints)) return } return true } if err := quick.Check(appendSample, nil); err != nil { t.Error(err) } }
func GetFingerprintsForLabelSetTests(p metric.Persistence, t test.Tester) { metrics := []clientmodel.Metric{ { clientmodel.MetricNameLabel: "test_metric", "method": "get", "result": "success", }, { clientmodel.MetricNameLabel: "test_metric", "method": "get", "result": "failure", }, { clientmodel.MetricNameLabel: "test_metric", "method": "post", "result": "success", }, { clientmodel.MetricNameLabel: "test_metric", "method": "post", "result": "failure", }, } newTestLabelMatcher := func(matchType metric.MatchType, name clientmodel.LabelName, value clientmodel.LabelValue) *metric.LabelMatcher { m, err := metric.NewLabelMatcher(matchType, name, value) if err != nil { t.Fatalf("Couldn't create label matcher: %v", err) } return m } scenarios := []struct { in metric.LabelMatchers outIndexes []int }{ { in: metric.LabelMatchers{ newTestLabelMatcher(metric.Equal, clientmodel.MetricNameLabel, "test_metric"), }, outIndexes: []int{0, 1, 2, 3}, }, { in: metric.LabelMatchers{ newTestLabelMatcher(metric.Equal, clientmodel.MetricNameLabel, "non_existent_metric"), }, outIndexes: []int{}, }, { in: metric.LabelMatchers{ newTestLabelMatcher(metric.Equal, clientmodel.MetricNameLabel, "non_existent_metric"), newTestLabelMatcher(metric.Equal, "result", "success"), }, outIndexes: []int{}, }, { in: metric.LabelMatchers{ newTestLabelMatcher(metric.Equal, clientmodel.MetricNameLabel, "test_metric"), newTestLabelMatcher(metric.Equal, "result", "success"), }, outIndexes: []int{0, 2}, }, { in: metric.LabelMatchers{ newTestLabelMatcher(metric.Equal, clientmodel.MetricNameLabel, "test_metric"), newTestLabelMatcher(metric.NotEqual, "result", "success"), }, outIndexes: []int{1, 3}, }, { in: metric.LabelMatchers{ newTestLabelMatcher(metric.Equal, clientmodel.MetricNameLabel, "test_metric"), newTestLabelMatcher(metric.RegexMatch, "result", "foo|success|bar"), }, outIndexes: []int{0, 2}, }, { in: metric.LabelMatchers{ newTestLabelMatcher(metric.Equal, clientmodel.MetricNameLabel, "test_metric"), newTestLabelMatcher(metric.RegexNoMatch, "result", "foo|success|bar"), }, outIndexes: []int{1, 3}, }, { in: metric.LabelMatchers{ newTestLabelMatcher(metric.Equal, clientmodel.MetricNameLabel, "test_metric"), newTestLabelMatcher(metric.RegexNoMatch, "result", "foo|success|bar"), newTestLabelMatcher(metric.RegexMatch, "method", "os"), }, outIndexes: []int{3}, }, } for _, m := range metrics { testAppendSamples(p, &clientmodel.Sample{ Value: 0, Timestamp: 0, Metric: m, }, t) } for i, s := range scenarios { actualFps, err := p.GetFingerprintsForLabelMatchers(s.in) if err != nil { t.Fatalf("%d. Couldn't get fingerprints for label matchers: %v", i, err) } expectedFps := clientmodel.Fingerprints{} for _, i := range s.outIndexes { fp := &clientmodel.Fingerprint{} fp.LoadFromMetric(metrics[i]) expectedFps = append(expectedFps, fp) } sort.Sort(actualFps) sort.Sort(expectedFps) if len(actualFps) != len(expectedFps) { t.Fatalf("%d. Got %d fingerprints; want %d", i, len(actualFps), len(expectedFps)) } for j, actualFp := range actualFps { if !actualFp.Equal(expectedFps[j]) { t.Fatalf("%d.%d. Got fingerprint %v; want %v", i, j, actualFp, expectedFps[j]) } } } }
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.") } }
func testAppendSamples(p metric.Persistence, s *clientmodel.Sample, t test.Tester) { err := p.AppendSamples(clientmodel.Samples{s}) if err != nil { t.Fatal(err) } }