func GetFingerprintsForLabelSetTests(p MetricPersistence, t test.Tester) { testAppendSample(p, model.Sample{ Value: 0, Timestamp: time.Time{}, Metric: model.Metric{ model.MetricNameLabel: "my_metric", "request_type": "your_mom", }, }, t) testAppendSample(p, model.Sample{ Value: 0, Timestamp: time.Time{}, Metric: model.Metric{ model.MetricNameLabel: "my_metric", "request_type": "your_dad", }, }, t) result, err := p.GetFingerprintsForLabelSet(model.LabelSet{ model.MetricNameLabel: model.LabelValue("my_metric"), }) if err != nil { t.Error(err) } if len(result) != 2 { t.Errorf("Expected two elements.") } 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.") } 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.") } }
func ReadEmptyTests(p MetricPersistence, t test.Tester) { hasLabelPair := func(x int) (success bool) { name := model.LabelName(string(x)) value := model.LabelValue(string(x)) labelSet := model.LabelSet{ name: value, } fingerprints, err := p.GetFingerprintsForLabelSet(labelSet) 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 := model.LabelName(string(x)) fingerprints, err := p.GetFingerprintsForLabelName(labelName) 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(hasLabelName, nil) if err != nil { t.Error(err) return } }
func (l *LevelDBMetricPersistence) GetMetricForFingerprint(f model.Fingerprint) (m *model.Metric, err error) { begin := time.Now() defer func() { duration := time.Since(begin) recordOutcome(duration, err, map[string]string{operation: getMetricForFingerprint, result: success}, map[string]string{operation: getMetricForFingerprint, result: failure}) }() raw, err := l.fingerprintToMetrics.Get(coding.NewProtocolBuffer(model.FingerprintToDTO(f))) if err != nil { return } unmarshaled := &dto.Metric{} err = proto.Unmarshal(raw, unmarshaled) if err != nil { return } metric := model.Metric{} for _, v := range unmarshaled.LabelPair { metric[model.LabelName(*v.Name)] = model.LabelValue(*v.Value) } // Explicit address passing here shaves immense amounts of time off of the // code flow due to less tight-loop dereferencing. m = &metric return }
func AppendSampleAsPureSparseAppendTests(p MetricPersistence, t test.Tester) { appendSample := func(x int) (success bool) { v := model.SampleValue(x) ts := time.Unix(int64(x), int64(x)) labelName := model.LabelName(x) labelValue := model.LabelValue(x) l := model.Metric{labelName: labelValue} sample := model.Sample{ Value: v, Timestamp: ts, Metric: l, } err := p.AppendSample(sample) success = err == nil if !success { t.Error(err) } return } if err := quick.Check(appendSample, nil); err != nil { t.Error(err) } }
func (d *MetricKeyDecoder) DecodeKey(in interface{}) (out interface{}, err error) { unmarshaled := dto.LabelPair{} err = proto.Unmarshal(in.([]byte), &unmarshaled) if err != nil { return } out = model.LabelPair{ Name: model.LabelName(*unmarshaled.Name), Value: model.LabelValue(*unmarshaled.Value), } return }
func AppendSampleAsSparseAppendWithReadsTests(p MetricPersistence, t test.Tester) { appendSample := func(x int) (success bool) { v := model.SampleValue(x) ts := time.Unix(int64(x), int64(x)) labelName := model.LabelName(x) labelValue := model.LabelValue(x) l := model.Metric{labelName: labelValue} sample := model.Sample{ Value: v, Timestamp: ts, Metric: l, } err := p.AppendSample(sample) if err != nil { t.Error(err) return } fingerprints, err := p.GetFingerprintsForLabelName(labelName) if err != nil { t.Error(err) return } if len(fingerprints) != 1 { t.Errorf("expected fingerprint count of %d, got %d", 1, len(fingerprints)) return } fingerprints, err = p.GetFingerprintsForLabelSet(model.LabelSet{ labelName: 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 (m *targetManager) AddTargetsFromConfig(config *config.Config) { for _, job := range config.Jobs { for _, configTargets := range job.Targets { baseLabels := model.LabelSet{ model.LabelName("job"): model.LabelValue(job.Name), } for label, value := range configTargets.Labels { baseLabels[label] = value } for _, endpoint := range configTargets.Endpoints { target := NewTarget(endpoint, time.Second*5, baseLabels) m.AddTarget(&job, target, config.Global.ScrapeInterval) } } } }
func (serv MetricsService) SetTargets(targetGroups []TargetGroup, jobName string) { if job := serv.appState.Config.GetJobByName(jobName); job == nil { rb := serv.ResponseBuilder() rb.SetResponseCode(http.StatusNotFound) } else { newTargets := []retrieval.Target{} for _, targetGroup := range targetGroups { // Do mandatory map type conversion due to Go shortcomings. baseLabels := model.LabelSet{} for label, value := range targetGroup.BaseLabels { baseLabels[model.LabelName(label)] = model.LabelValue(value) } for _, endpoint := range targetGroup.Endpoints { newTarget := retrieval.NewTarget(endpoint, time.Second*5, baseLabels) newTargets = append(newTargets, newTarget) } } serv.appState.TargetManager.ReplaceTargets(job, newTargets, serv.appState.Config.Global.ScrapeInterval) } }
func GetFingerprintsForLabelSetUsesAndForLabelMatchingTests(p MetricPersistence, t test.Tester) { metrics := []model.LabelSet{ {model.MetricNameLabel: "request_metrics_latency_equal_tallying_microseconds", "instance": "http://localhost:9090/metrics.json", "percentile": "0.010000"}, {model.MetricNameLabel: "requests_metrics_latency_equal_accumulating_microseconds", "instance": "http://localhost:9090/metrics.json", "percentile": "0.010000"}, {model.MetricNameLabel: "requests_metrics_latency_logarithmic_accumulating_microseconds", "instance": "http://localhost:9090/metrics.json", "percentile": "0.010000"}, {model.MetricNameLabel: "requests_metrics_latency_logarithmic_tallying_microseconds", "instance": "http://localhost:9090/metrics.json", "percentile": "0.010000"}, {model.MetricNameLabel: "targets_healthy_scrape_latency_ms", "instance": "http://localhost:9090/metrics.json", "percentile": "0.010000"}, } for _, metric := range metrics { m := model.Metric{} for k, v := range metric { m[model.LabelName(k)] = model.LabelValue(v) } testAppendSample(p, model.Sample{ Value: model.SampleValue(0.0), Timestamp: time.Now(), Metric: m, }, t) } labelSet := model.LabelSet{ model.MetricNameLabel: "targets_healthy_scrape_latency_ms", "percentile": "0.010000", } fingerprints, err := p.GetFingerprintsForLabelSet(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 (p *processor001) Process(stream io.ReadCloser, baseLabels model.LabelSet, results chan Result) (err error) { // TODO(matt): Replace with plain-jane JSON unmarshalling. defer stream.Close() buffer, err := ioutil.ReadAll(stream) if err != nil { return } entities := entity001{} err = json.Unmarshal(buffer, &entities) if err != nil { return } now := p.time.Now() // TODO(matt): This outer loop is a great basis for parallelization. for _, entity := range entities { for _, value := range entity.Metric.Value { metric := model.Metric{} for label, labelValue := range baseLabels { metric[label] = labelValue } for label, labelValue := range entity.BaseLabels { metric[model.LabelName(label)] = model.LabelValue(labelValue) } for label, labelValue := range value.Labels { metric[model.LabelName(label)] = model.LabelValue(labelValue) } switch entity.Metric.MetricType { case gauge001, counter001: sampleValue, ok := value.Value.(float64) if !ok { err = fmt.Errorf("Could not convert value from %s %s to float64.", entity, value) continue } sample := model.Sample{ Metric: metric, Timestamp: now, Value: model.SampleValue(sampleValue), } results <- Result{ Err: err, Sample: sample, } break case histogram001: sampleValue, ok := value.Value.(map[string]interface{}) if !ok { err = fmt.Errorf("Could not convert value from %q to a map[string]interface{}.", value.Value) continue } for percentile, percentileValue := range sampleValue { individualValue, ok := percentileValue.(float64) if !ok { err = fmt.Errorf("Could not convert value from %q to a float64.", percentileValue) continue } childMetric := make(map[model.LabelName]model.LabelValue, len(metric)+1) for k, v := range metric { childMetric[k] = v } childMetric[model.LabelName(percentile001)] = model.LabelValue(percentile) sample := model.Sample{ Metric: childMetric, Timestamp: now, Value: model.SampleValue(individualValue), } results <- Result{ Err: err, Sample: sample, } } break default: } } } return }
func yyParse(yylex yyLexer) int { var yyn int var yylval yySymType var yyVAL yySymType yyS := make([]yySymType, yyMaxDepth) Nerrs := 0 /* number of errors */ Errflag := 0 /* error recovery flag */ yystate := 0 yychar := -1 yyp := -1 goto yystack ret0: return 0 ret1: return 1 yystack: /* put a state and value onto the stack */ if yyDebug >= 4 { fmt.Printf("char %v in %v\n", yyTokname(yychar), yyStatname(yystate)) } yyp++ if yyp >= len(yyS) { nyys := make([]yySymType, len(yyS)*2) copy(nyys, yyS) yyS = nyys } yyS[yyp] = yyVAL yyS[yyp].yys = yystate yynewstate: yyn = yyPact[yystate] if yyn <= yyFlag { goto yydefault /* simple state */ } if yychar < 0 { yychar = yylex1(yylex, &yylval) } yyn += yychar if yyn < 0 || yyn >= yyLast { goto yydefault } yyn = yyAct[yyn] if yyChk[yyn] == yychar { /* valid shift */ yychar = -1 yyVAL = yylval yystate = yyn if Errflag > 0 { Errflag-- } goto yystack } yydefault: /* default state action */ yyn = yyDef[yystate] if yyn == -2 { if yychar < 0 { yychar = yylex1(yylex, &yylval) } /* look through exception table */ xi := 0 for { if yyExca[xi+0] == -1 && yyExca[xi+1] == yystate { break } xi += 2 } for xi += 2; ; xi += 2 { yyn = yyExca[xi+0] if yyn < 0 || yyn == yychar { break } } yyn = yyExca[xi+1] if yyn < 0 { goto ret0 } } if yyn == 0 { /* error ... attempt to resume parsing */ switch Errflag { case 0: /* brand new error */ yylex.Error("syntax error") Nerrs++ if yyDebug >= 1 { fmt.Printf("%s", yyStatname(yystate)) fmt.Printf("saw %s\n", yyTokname(yychar)) } fallthrough case 1, 2: /* incompletely recovered error ... try again */ Errflag = 3 /* find a state where "error" is a legal shift action */ for yyp >= 0 { yyn = yyPact[yyS[yyp].yys] + yyErrCode if yyn >= 0 && yyn < yyLast { yystate = yyAct[yyn] /* simulate a shift of "error" */ if yyChk[yystate] == yyErrCode { goto yystack } } /* the current p has no shift on "error", pop stack */ if yyDebug >= 2 { fmt.Printf("error recovery pops state %d\n", yyS[yyp].yys) } yyp-- } /* there is no state on the stack with an error shift ... abort */ goto ret1 case 3: /* no shift yet; clobber input char */ if yyDebug >= 2 { fmt.Printf("error recovery discards %s\n", yyTokname(yychar)) } if yychar == yyEofCode { goto ret1 } yychar = -1 goto yynewstate /* try again in the same state */ } } /* reduction by production yyn */ if yyDebug >= 2 { fmt.Printf("reduce %v in:\n\t%v\n", yyn, yyStatname(yystate)) } yynt := yyn yypt := yyp _ = yypt // guard against "declared and not used" yyp -= yyR2[yyn] yyVAL = yyS[yyp+1] /* consult goto table to find next state */ yyn = yyR1[yyn] yyg := yyPgo[yyn] yyj := yyg + yyS[yyp].yys + 1 if yyj >= yyLast { yystate = yyAct[yyg] } else { yystate = yyAct[yyj] if yyChk[yystate] != -yyn { yystate = yyAct[yyg] } } // dummy call; replaced with literal code switch yynt { case 4: //line parser.y:45 { PopJob() } case 7: //line parser.y:53 { parsedConfig.Global.SetOption(yyS[yypt-2].str, yyS[yypt-0].str) } case 8: //line parser.y:55 { parsedConfig.Global.SetLabels(yyS[yypt-0].labelSet) } case 9: //line parser.y:57 { parsedConfig.Global.AddRuleFiles(yyS[yypt-0].stringSlice) } case 10: //line parser.y:61 { yyVAL.labelSet = yyS[yypt-1].labelSet } case 11: //line parser.y:63 { yyVAL.labelSet = model.LabelSet{} } case 12: //line parser.y:67 { yyVAL.labelSet = yyS[yypt-0].labelSet } case 13: //line parser.y:69 { for k, v := range yyS[yypt-0].labelSet { yyVAL.labelSet[k] = v } } case 14: //line parser.y:73 { yyVAL.labelSet = model.LabelSet{model.LabelName(yyS[yypt-2].str): model.LabelValue(yyS[yypt-0].str)} } case 15: //line parser.y:77 { yyVAL.stringSlice = yyS[yypt-0].stringSlice } case 18: //line parser.y:85 { PushJobOption(yyS[yypt-2].str, yyS[yypt-0].str) } case 19: //line parser.y:87 { PushJobTargets() } case 22: //line parser.y:95 { PushTargetEndpoints(yyS[yypt-0].stringSlice) } case 23: //line parser.y:97 { PushTargetLabels(yyS[yypt-0].labelSet) } case 24: //line parser.y:101 { yyVAL.stringSlice = yyS[yypt-0].stringSlice } case 25: //line parser.y:105 { yyVAL.stringSlice = yyS[yypt-1].stringSlice } case 26: //line parser.y:107 { yyVAL.stringSlice = []string{} } case 27: //line parser.y:111 { yyVAL.stringSlice = []string{yyS[yypt-0].str} } case 28: //line parser.y:113 { yyVAL.stringSlice = append(yyVAL.stringSlice, yyS[yypt-0].str) } } goto yystack /* stack new state and value */ }
func yyParse(yylex yyLexer) int { var yyn int var yylval yySymType var yyVAL yySymType yyS := make([]yySymType, yyMaxDepth) Nerrs := 0 /* number of errors */ Errflag := 0 /* error recovery flag */ yystate := 0 yychar := -1 yyp := -1 goto yystack ret0: return 0 ret1: return 1 yystack: /* put a state and value onto the stack */ if yyDebug >= 4 { fmt.Printf("char %v in %v\n", yyTokname(yychar), yyStatname(yystate)) } yyp++ if yyp >= len(yyS) { nyys := make([]yySymType, len(yyS)*2) copy(nyys, yyS) yyS = nyys } yyS[yyp] = yyVAL yyS[yyp].yys = yystate yynewstate: yyn = yyPact[yystate] if yyn <= yyFlag { goto yydefault /* simple state */ } if yychar < 0 { yychar = yylex1(yylex, &yylval) } yyn += yychar if yyn < 0 || yyn >= yyLast { goto yydefault } yyn = yyAct[yyn] if yyChk[yyn] == yychar { /* valid shift */ yychar = -1 yyVAL = yylval yystate = yyn if Errflag > 0 { Errflag-- } goto yystack } yydefault: /* default state action */ yyn = yyDef[yystate] if yyn == -2 { if yychar < 0 { yychar = yylex1(yylex, &yylval) } /* look through exception table */ xi := 0 for { if yyExca[xi+0] == -1 && yyExca[xi+1] == yystate { break } xi += 2 } for xi += 2; ; xi += 2 { yyn = yyExca[xi+0] if yyn < 0 || yyn == yychar { break } } yyn = yyExca[xi+1] if yyn < 0 { goto ret0 } } if yyn == 0 { /* error ... attempt to resume parsing */ switch Errflag { case 0: /* brand new error */ yylex.Error("syntax error") Nerrs++ if yyDebug >= 1 { fmt.Printf("%s", yyStatname(yystate)) fmt.Printf("saw %s\n", yyTokname(yychar)) } fallthrough case 1, 2: /* incompletely recovered error ... try again */ Errflag = 3 /* find a state where "error" is a legal shift action */ for yyp >= 0 { yyn = yyPact[yyS[yyp].yys] + yyErrCode if yyn >= 0 && yyn < yyLast { yystate = yyAct[yyn] /* simulate a shift of "error" */ if yyChk[yystate] == yyErrCode { goto yystack } } /* the current p has no shift on "error", pop stack */ if yyDebug >= 2 { fmt.Printf("error recovery pops state %d\n", yyS[yyp].yys) } yyp-- } /* there is no state on the stack with an error shift ... abort */ goto ret1 case 3: /* no shift yet; clobber input char */ if yyDebug >= 2 { fmt.Printf("error recovery discards %s\n", yyTokname(yychar)) } if yychar == yyEofCode { goto ret1 } yychar = -1 goto yynewstate /* try again in the same state */ } } /* reduction by production yyn */ if yyDebug >= 2 { fmt.Printf("reduce %v in:\n\t%v\n", yyn, yyStatname(yystate)) } yynt := yyn yypt := yyp _ = yypt // guard against "declared and not used" yyp -= yyR2[yyn] yyVAL = yyS[yyp+1] /* consult goto table to find next state */ yyn = yyR1[yyn] yyg := yyPgo[yyn] yyj := yyg + yyS[yyp].yys + 1 if yyj >= yyLast { yystate = yyAct[yyg] } else { yystate = yyAct[yyj] if yyChk[yystate] != -yyn { yystate = yyAct[yyg] } } // dummy call; replaced with literal code switch yynt { case 5: //line parser.y:65 { yylex.(*RulesLexer).parsedExpr = yyS[yypt-0].ruleNode } case 6: //line parser.y:69 { rule, err := CreateRule(yyS[yypt-3].str, yyS[yypt-2].labelSet, yyS[yypt-0].ruleNode, yyS[yypt-4].boolean) if err != nil { yylex.Error(err.Error()) return 1 } yylex.(*RulesLexer).parsedRules = append(yylex.(*RulesLexer).parsedRules, rule) } case 7: //line parser.y:77 { yyVAL.boolean = false } case 8: //line parser.y:79 { yyVAL.boolean = true } case 9: //line parser.y:83 { yyVAL.labelSet = model.LabelSet{} } case 10: //line parser.y:85 { yyVAL.labelSet = yyS[yypt-1].labelSet } case 11: //line parser.y:87 { yyVAL.labelSet = model.LabelSet{} } case 12: //line parser.y:90 { yyVAL.labelSet = yyS[yypt-0].labelSet } case 13: //line parser.y:92 { for k, v := range yyS[yypt-0].labelSet { yyVAL.labelSet[k] = v } } case 14: //line parser.y:96 { yyVAL.labelSet = model.LabelSet{model.LabelName(yyS[yypt-2].str): model.LabelValue(yyS[yypt-0].str)} } case 15: //line parser.y:101 { yyVAL.ruleNode = yyS[yypt-1].ruleNode } case 16: //line parser.y:103 { yyS[yypt-0].labelSet[model.MetricNameLabel] = model.LabelValue(yyS[yypt-1].str) yyVAL.ruleNode = ast.NewVectorLiteral(yyS[yypt-0].labelSet) } case 17: //line parser.y:105 { var err error yyVAL.ruleNode, err = NewFunctionCall(yyS[yypt-3].str, yyS[yypt-1].ruleNodeSlice) if err != nil { yylex.Error(err.Error()) return 1 } } case 18: //line parser.y:111 { var err error yyVAL.ruleNode, err = NewFunctionCall(yyS[yypt-2].str, []ast.Node{}) if err != nil { yylex.Error(err.Error()) return 1 } } case 19: //line parser.y:117 { var err error yyVAL.ruleNode, err = NewMatrix(yyS[yypt-3].ruleNode, yyS[yypt-1].str) if err != nil { yylex.Error(err.Error()) return 1 } } case 20: //line parser.y:123 { var err error yyVAL.ruleNode, err = NewVectorAggregation(yyS[yypt-4].str, yyS[yypt-2].ruleNode, yyS[yypt-0].labelNameSlice) if err != nil { yylex.Error(err.Error()) return 1 } } case 21: //line parser.y:131 { var err error yyVAL.ruleNode, err = NewArithExpr(yyS[yypt-1].str, yyS[yypt-2].ruleNode, yyS[yypt-0].ruleNode) if err != nil { yylex.Error(err.Error()) return 1 } } case 22: //line parser.y:137 { var err error yyVAL.ruleNode, err = NewArithExpr(yyS[yypt-1].str, yyS[yypt-2].ruleNode, yyS[yypt-0].ruleNode) if err != nil { yylex.Error(err.Error()) return 1 } } case 23: //line parser.y:143 { var err error yyVAL.ruleNode, err = NewArithExpr(yyS[yypt-1].str, yyS[yypt-2].ruleNode, yyS[yypt-0].ruleNode) if err != nil { yylex.Error(err.Error()) return 1 } } case 24: //line parser.y:149 { yyVAL.ruleNode = ast.NewScalarLiteral(yyS[yypt-0].num) } case 25: //line parser.y:153 { yyVAL.labelNameSlice = []model.LabelName{} } case 26: //line parser.y:155 { yyVAL.labelNameSlice = yyS[yypt-1].labelNameSlice } case 27: //line parser.y:159 { yyVAL.labelNameSlice = []model.LabelName{model.LabelName(yyS[yypt-0].str)} } case 28: //line parser.y:161 { yyVAL.labelNameSlice = append(yyVAL.labelNameSlice, model.LabelName(yyS[yypt-0].str)) } case 29: //line parser.y:165 { yyVAL.ruleNodeSlice = []ast.Node{yyS[yypt-0].ruleNode} } case 30: //line parser.y:167 { yyVAL.ruleNodeSlice = append(yyVAL.ruleNodeSlice, yyS[yypt-0].ruleNode) } case 31: //line parser.y:171 { yyVAL.ruleNode = yyS[yypt-0].ruleNode } case 32: //line parser.y:173 { yyVAL.ruleNode = ast.NewStringLiteral(yyS[yypt-0].str) } } goto yystack /* stack new state and value */ }
func GetFingerprintsForLabelNameTests(p MetricPersistence, t test.Tester) { testAppendSample(p, model.Sample{ Value: 0, Timestamp: time.Time{}, Metric: model.Metric{ model.MetricNameLabel: "my_metric", "request_type": "your_mom", "language": "english", }, }, t) testAppendSample(p, model.Sample{ Value: 0, Timestamp: time.Time{}, Metric: model.Metric{ model.MetricNameLabel: "my_metric", "request_type": "your_dad", "sprache": "deutsch", }, }, t) b := model.MetricNameLabel result, err := p.GetFingerprintsForLabelName(b) if err != nil { t.Error(err) } if len(result) != 2 { t.Errorf("Expected two elements.") } b = model.LabelName("request_type") result, err = p.GetFingerprintsForLabelName(b) if err != nil { t.Error(err) } if len(result) != 2 { t.Errorf("Expected two elements.") } b = model.LabelName("language") result, err = p.GetFingerprintsForLabelName(b) if err != nil { t.Error(err) } if len(result) != 1 { t.Errorf("Expected one element.") } b = model.LabelName("sprache") result, err = p.GetFingerprintsForLabelName(b) if err != nil { t.Error(err) } if len(result) != 1 { t.Errorf("Expected one element.") } }
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.") } }
func StochasticTests(persistenceMaker func() (MetricPersistence, 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 := model.Sample{ Metric: model.Metric{}, } v := model.LabelValue(fmt.Sprintf("metric_index_%d", metricIndex)) sample.Metric[model.MetricNameLabel] = v for sharedLabelIndex := 0; sharedLabelIndex < numberOfSharedLabels; sharedLabelIndex++ { l := model.LabelName(fmt.Sprintf("shared_label_%d", sharedLabelIndex)) v := model.LabelValue(fmt.Sprintf("label_%d", sharedLabelIndex)) sample.Metric[l] = v } for unsharedLabelIndex := 0; unsharedLabelIndex < numberOfUnsharedLabels; unsharedLabelIndex++ { l := model.LabelName(fmt.Sprintf("metric_index_%d_private_label_%d", metricIndex, unsharedLabelIndex)) v := model.LabelValue(fmt.Sprintf("private_label_%d", unsharedLabelIndex)) sample.Metric[l] = v } timestamps := map[int64]bool{} metricTimestamps[metricIndex] = timestamps var ( newestSample int64 = math.MinInt64 oldestSample int64 = math.MaxInt64 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 } for sampleIndex := 0; sampleIndex < numberOfSamples; sampleIndex++ { sample.Timestamp = time.Unix(nextTimestamp(), 0) sample.Value = model.SampleValue(sampleIndex) err := p.AppendSample(sample) if err != nil { t.Error(err) return } } metricEarliestSample[metricIndex] = oldestSample metricNewestSample[metricIndex] = newestSample for sharedLabelIndex := 0; sharedLabelIndex < numberOfSharedLabels; sharedLabelIndex++ { labelPair := model.LabelSet{ model.LabelName(fmt.Sprintf("shared_label_%d", sharedLabelIndex)): model.LabelValue(fmt.Sprintf("label_%d", sharedLabelIndex)), } fingerprints, err := p.GetFingerprintsForLabelSet(labelPair) if err != nil { t.Error(err) return } if len(fingerprints) == 0 { t.Errorf("expected fingerprint count of %d, got %d", 0, len(fingerprints)) return } labelName := model.LabelName(fmt.Sprintf("shared_label_%d", sharedLabelIndex)) fingerprints, err = p.GetFingerprintsForLabelName(labelName) 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 sharedIndex := 0; sharedIndex < numberOfSharedLabels; sharedIndex++ { labelName := model.LabelName(fmt.Sprintf("shared_label_%d", sharedIndex)) fingerprints, err := p.GetFingerprintsForLabelName(labelName) if err != nil { t.Error(err) return } if len(fingerprints) != numberOfMetrics { t.Errorf("expected fingerprint count of %d, got %d", numberOfMetrics, len(fingerprints)) return } } for metricIndex := 0; metricIndex < numberOfMetrics; metricIndex++ { for unsharedLabelIndex := 0; unsharedLabelIndex < numberOfUnsharedLabels; unsharedLabelIndex++ { labelName := model.LabelName(fmt.Sprintf("metric_index_%d_private_label_%d", metricIndex, unsharedLabelIndex)) labelValue := model.LabelValue(fmt.Sprintf("private_label_%d", unsharedLabelIndex)) labelSet := model.LabelSet{ labelName: labelValue, } fingerprints, err := p.GetFingerprintsForLabelSet(labelSet) if err != nil { t.Error(err) return } if len(fingerprints) != 1 { t.Errorf("expected fingerprint count of %d, got %d", 1, len(fingerprints)) return } fingerprints, err = p.GetFingerprintsForLabelName(labelName) if err != nil { t.Error(err) return } if len(fingerprints) != 1 { t.Errorf("expected fingerprint count of %d, got %d", 1, len(fingerprints)) return } } metric := model.Metric{} metric[model.MetricNameLabel] = model.LabelValue(fmt.Sprintf("metric_index_%d", metricIndex)) for i := 0; i < numberOfSharedLabels; i++ { l := model.LabelName(fmt.Sprintf("shared_label_%d", i)) v := model.LabelValue(fmt.Sprintf("label_%d", i)) metric[l] = v } for i := 0; i < numberOfUnsharedLabels; i++ { l := model.LabelName(fmt.Sprintf("metric_index_%d_private_label_%d", metricIndex, i)) v := model.LabelValue(fmt.Sprintf("private_label_%d", i)) metric[l] = v } for i := 0; i < numberOfRangeScans; i++ { timestamps := metricTimestamps[metricIndex] var first int64 = 0 var second int64 = 0 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 := model.Interval{ OldestInclusive: time.Unix(begin, 0), NewestInclusive: time.Unix(end, 0), } samples, err := p.GetRangeValues(model.NewFingerprintFromMetric(metric), interval) if err != nil { t.Error(err) return } if len(samples.Values) < 2 { t.Errorf("expected sample count less than %d, got %d", 2, len(samples.Values)) return } } } return true } if err := quick.Check(stochastic, nil); err != nil { t.Error(err) } }