2019-07-07 16:44:26 +00:00
|
|
|
package prometheus
|
|
|
|
|
|
|
|
import (
|
2019-08-20 19:52:49 +00:00
|
|
|
"math"
|
2021-02-01 16:04:14 +00:00
|
|
|
"net/http"
|
2019-08-20 19:52:49 +00:00
|
|
|
"reflect"
|
2019-07-07 20:34:04 +00:00
|
|
|
"testing"
|
2019-08-20 19:52:49 +00:00
|
|
|
|
|
|
|
"github.com/VictoriaMetrics/VictoriaMetrics/app/vmselect/netstorage"
|
2021-02-01 16:04:14 +00:00
|
|
|
"github.com/VictoriaMetrics/VictoriaMetrics/lib/storage"
|
2019-07-07 16:44:26 +00:00
|
|
|
)
|
|
|
|
|
2020-07-20 12:28:36 +00:00
|
|
|
func TestRemoveEmptyValuesAndTimeseries(t *testing.T) {
|
2019-08-20 19:52:49 +00:00
|
|
|
f := func(tss []netstorage.Result, tssExpected []netstorage.Result) {
|
|
|
|
t.Helper()
|
2020-07-20 12:28:36 +00:00
|
|
|
tss = removeEmptyValuesAndTimeseries(tss)
|
2019-08-20 19:52:49 +00:00
|
|
|
if !reflect.DeepEqual(tss, tssExpected) {
|
|
|
|
t.Fatalf("unexpected result; got %v; want %v", tss, tssExpected)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
f(nil, nil)
|
|
|
|
f([]netstorage.Result{
|
|
|
|
{
|
|
|
|
Timestamps: []int64{100, 200, 300},
|
|
|
|
Values: []float64{1, 2, 3},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
Timestamps: []int64{100, 200, 300, 400},
|
|
|
|
Values: []float64{nan, nan, 3, nan},
|
|
|
|
},
|
2020-07-20 12:28:36 +00:00
|
|
|
{
|
|
|
|
Timestamps: []int64{1, 2},
|
|
|
|
Values: []float64{nan, nan},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
Timestamps: nil,
|
|
|
|
Values: nil,
|
|
|
|
},
|
2019-08-20 19:52:49 +00:00
|
|
|
}, []netstorage.Result{
|
|
|
|
{
|
|
|
|
Timestamps: []int64{100, 200, 300},
|
|
|
|
Values: []float64{1, 2, 3},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
Timestamps: []int64{300},
|
|
|
|
Values: []float64{3},
|
|
|
|
},
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
2020-07-05 14:56:54 +00:00
|
|
|
func TestAdjustLastPoints(t *testing.T) {
|
2020-07-05 15:17:02 +00:00
|
|
|
f := func(tss []netstorage.Result, start, end int64, tssExpected []netstorage.Result) {
|
2020-07-05 14:56:54 +00:00
|
|
|
t.Helper()
|
2020-07-05 15:17:02 +00:00
|
|
|
tss = adjustLastPoints(tss, start, end)
|
2020-07-05 14:56:54 +00:00
|
|
|
for i, ts := range tss {
|
|
|
|
for j, value := range ts.Values {
|
|
|
|
expectedValue := tssExpected[i].Values[j]
|
|
|
|
if math.IsNaN(expectedValue) {
|
|
|
|
if !math.IsNaN(value) {
|
2020-07-14 09:45:42 +00:00
|
|
|
t.Fatalf("unexpected value for time series #%d at position %d; got %v; want nan", i, j, value)
|
2020-07-05 14:56:54 +00:00
|
|
|
}
|
|
|
|
} else if expectedValue != value {
|
2020-07-14 09:45:42 +00:00
|
|
|
t.Fatalf("unexpected value for time series #%d at position %d; got %v; want %v", i, j, value, expectedValue)
|
2020-07-05 14:56:54 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
if !reflect.DeepEqual(ts.Timestamps, tssExpected[i].Timestamps) {
|
2020-07-14 09:45:42 +00:00
|
|
|
t.Fatalf("unexpected timestamps for time series #%d; got %v; want %v", i, tss, tssExpected)
|
2020-07-05 14:56:54 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
nan := math.NaN()
|
|
|
|
|
2020-07-05 15:17:02 +00:00
|
|
|
f(nil, 300, 500, nil)
|
2020-07-05 14:56:54 +00:00
|
|
|
|
|
|
|
f([]netstorage.Result{
|
|
|
|
{
|
|
|
|
Timestamps: []int64{100, 200, 300, 400, 500},
|
|
|
|
Values: []float64{1, 2, 3, 4, nan},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
Timestamps: []int64{100, 200, 300, 400, 500},
|
|
|
|
Values: []float64{1, 2, 3, nan, nan},
|
|
|
|
},
|
2020-07-05 15:17:02 +00:00
|
|
|
}, 400, 500, []netstorage.Result{
|
2020-07-05 14:56:54 +00:00
|
|
|
{
|
|
|
|
Timestamps: []int64{100, 200, 300, 400, 500},
|
|
|
|
Values: []float64{1, 2, 3, 4, 4},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
Timestamps: []int64{100, 200, 300, 400, 500},
|
|
|
|
Values: []float64{1, 2, 3, nan, nan},
|
|
|
|
},
|
|
|
|
})
|
|
|
|
|
|
|
|
f([]netstorage.Result{
|
|
|
|
{
|
|
|
|
Timestamps: []int64{100, 200, 300, 400, 500},
|
|
|
|
Values: []float64{1, 2, 3, nan, nan},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
Timestamps: []int64{100, 200, 300, 400, 500},
|
|
|
|
Values: []float64{1, 2, nan, nan, nan},
|
|
|
|
},
|
2020-07-05 15:17:02 +00:00
|
|
|
}, 300, 500, []netstorage.Result{
|
2020-07-05 14:56:54 +00:00
|
|
|
{
|
|
|
|
Timestamps: []int64{100, 200, 300, 400, 500},
|
|
|
|
Values: []float64{1, 2, 3, 3, 3},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
Timestamps: []int64{100, 200, 300, 400, 500},
|
|
|
|
Values: []float64{1, 2, nan, nan, nan},
|
|
|
|
},
|
|
|
|
})
|
|
|
|
|
|
|
|
f([]netstorage.Result{
|
|
|
|
{
|
|
|
|
Timestamps: []int64{100, 200, 300, 400, 500},
|
|
|
|
Values: []float64{1, 2, nan, nan, nan},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
Timestamps: []int64{100, 200, 300, 400, 500},
|
|
|
|
Values: []float64{1, nan, nan, nan, nan},
|
|
|
|
},
|
|
|
|
}, 500, 300, []netstorage.Result{
|
|
|
|
{
|
|
|
|
Timestamps: []int64{100, 200, 300, 400, 500},
|
|
|
|
Values: []float64{1, 2, nan, nan, nan},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
Timestamps: []int64{100, 200, 300, 400, 500},
|
|
|
|
Values: []float64{1, nan, nan, nan, nan},
|
|
|
|
},
|
|
|
|
})
|
|
|
|
|
|
|
|
f([]netstorage.Result{
|
|
|
|
{
|
|
|
|
Timestamps: []int64{100, 200, 300, 400, 500},
|
|
|
|
Values: []float64{1, 2, 3, 4, nan},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
Timestamps: []int64{100, 200, 300, 400},
|
|
|
|
Values: []float64{1, 2, 3, 4},
|
|
|
|
},
|
2020-07-05 15:17:02 +00:00
|
|
|
}, 400, 500, []netstorage.Result{
|
2020-07-05 14:56:54 +00:00
|
|
|
{
|
|
|
|
Timestamps: []int64{100, 200, 300, 400, 500},
|
|
|
|
Values: []float64{1, 2, 3, 4, 4},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
Timestamps: []int64{100, 200, 300, 400},
|
|
|
|
Values: []float64{1, 2, 3, 4},
|
|
|
|
},
|
|
|
|
})
|
|
|
|
|
|
|
|
f([]netstorage.Result{
|
|
|
|
{
|
|
|
|
Timestamps: []int64{100, 200, 300, 400, 500},
|
|
|
|
Values: []float64{1, 2, 3, nan, nan},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
Timestamps: []int64{100, 200, 300},
|
|
|
|
Values: []float64{1, 2, nan},
|
|
|
|
},
|
2020-07-05 15:17:02 +00:00
|
|
|
}, 300, 600, []netstorage.Result{
|
2020-07-05 14:56:54 +00:00
|
|
|
{
|
|
|
|
Timestamps: []int64{100, 200, 300, 400, 500},
|
|
|
|
Values: []float64{1, 2, 3, 3, 3},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
Timestamps: []int64{100, 200, 300},
|
|
|
|
Values: []float64{1, 2, nan},
|
|
|
|
},
|
|
|
|
})
|
2020-07-14 09:45:42 +00:00
|
|
|
|
|
|
|
// Check for timestamps outside the configured time range.
|
|
|
|
// See https://github.com/VictoriaMetrics/VictoriaMetrics/issues/625
|
|
|
|
f([]netstorage.Result{
|
|
|
|
{
|
|
|
|
Timestamps: []int64{100, 200, 300, 400, 500},
|
|
|
|
Values: []float64{1, 2, 3, nan, nan},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
Timestamps: []int64{100, 200, 300},
|
|
|
|
Values: []float64{1, 2, 45},
|
|
|
|
},
|
|
|
|
}, 250, 400, []netstorage.Result{
|
|
|
|
{
|
|
|
|
Timestamps: []int64{100, 200, 300, 400, 500},
|
|
|
|
Values: []float64{1, 2, 3, nan, nan},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
Timestamps: []int64{100, 200, 300},
|
|
|
|
Values: []float64{1, 2, 2},
|
|
|
|
},
|
|
|
|
})
|
2020-07-05 14:56:54 +00:00
|
|
|
}
|
2021-02-01 16:04:14 +00:00
|
|
|
|
|
|
|
// helper for tests
|
|
|
|
func tfFromKV(k, v string) storage.TagFilter {
|
|
|
|
return storage.TagFilter{
|
|
|
|
Key: []byte(k),
|
|
|
|
Value: []byte(v),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func Test_addEnforcedFiltersToTagFilterss(t *testing.T) {
|
|
|
|
f := func(t *testing.T, dstTfss [][]storage.TagFilter, enforcedFilters []storage.TagFilter, want [][]storage.TagFilter) {
|
|
|
|
t.Helper()
|
|
|
|
got := addEnforcedFiltersToTagFilterss(dstTfss, enforcedFilters)
|
|
|
|
if !reflect.DeepEqual(got, want) {
|
|
|
|
t.Fatalf("unxpected result for addEnforcedFiltersToTagFilterss, \ngot: %v,\n want: %v", want, got)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
f(t, [][]storage.TagFilter{{tfFromKV("label", "value")}},
|
|
|
|
nil,
|
|
|
|
[][]storage.TagFilter{{tfFromKV("label", "value")}})
|
|
|
|
|
|
|
|
f(t, nil,
|
|
|
|
[]storage.TagFilter{tfFromKV("ext-label", "ext-value")},
|
|
|
|
[][]storage.TagFilter{{tfFromKV("ext-label", "ext-value")}})
|
|
|
|
|
|
|
|
f(t, [][]storage.TagFilter{
|
|
|
|
{tfFromKV("l1", "v1")},
|
|
|
|
{tfFromKV("l2", "v2")},
|
|
|
|
},
|
|
|
|
[]storage.TagFilter{tfFromKV("ext-l1", "v2")},
|
|
|
|
[][]storage.TagFilter{
|
|
|
|
{tfFromKV("l1", "v1"), tfFromKV("ext-l1", "v2")},
|
|
|
|
{tfFromKV("l2", "v2"), tfFromKV("ext-l1", "v2")},
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
|
|
|
func Test_getEnforcedTagFiltersFromRequest(t *testing.T) {
|
|
|
|
httpReqWithForm := func(tfs []string) *http.Request {
|
|
|
|
return &http.Request{
|
|
|
|
Form: map[string][]string{
|
|
|
|
"extra_label": tfs,
|
|
|
|
},
|
|
|
|
}
|
|
|
|
}
|
|
|
|
f := func(t *testing.T, r *http.Request, want []storage.TagFilter, wantErr bool) {
|
|
|
|
t.Helper()
|
|
|
|
got, err := getEnforcedTagFiltersFromRequest(r)
|
|
|
|
if (err != nil) != wantErr {
|
|
|
|
t.Fatalf("unexpected error: %v", err)
|
|
|
|
}
|
|
|
|
if !reflect.DeepEqual(got, want) {
|
|
|
|
t.Fatalf("unxpected result for getEnforcedTagFiltersFromRequest, \ngot: %v,\n want: %v", want, got)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
f(t, httpReqWithForm([]string{"label=value"}),
|
|
|
|
[]storage.TagFilter{
|
|
|
|
tfFromKV("label", "value"),
|
|
|
|
},
|
|
|
|
false)
|
|
|
|
|
|
|
|
f(t, httpReqWithForm([]string{"job=vmagent", "dc=gce"}),
|
|
|
|
[]storage.TagFilter{tfFromKV("job", "vmagent"), tfFromKV("dc", "gce")},
|
|
|
|
false,
|
|
|
|
)
|
|
|
|
f(t, httpReqWithForm([]string{"bad_filter"}),
|
|
|
|
nil,
|
|
|
|
true,
|
|
|
|
)
|
|
|
|
f(t, &http.Request{},
|
|
|
|
nil, false)
|
|
|
|
}
|