2024-10-30 14:22:06 +00:00
|
|
|
package tests
|
|
|
|
|
|
|
|
import (
|
|
|
|
"fmt"
|
|
|
|
"math/rand/v2"
|
|
|
|
"testing"
|
|
|
|
"time"
|
|
|
|
|
|
|
|
"github.com/VictoriaMetrics/VictoriaMetrics/apptest"
|
|
|
|
)
|
|
|
|
|
2024-11-07 11:58:37 +00:00
|
|
|
func TestClusterMultilevelSelect(t *testing.T) {
|
2024-10-30 14:22:06 +00:00
|
|
|
tc := apptest.NewTestCase(t)
|
|
|
|
defer tc.Close()
|
|
|
|
|
|
|
|
// Set up the following multi-level cluster configuration:
|
|
|
|
//
|
|
|
|
// vmselect (L2) -> vmselect (L1) -> vmstorage <- vminsert
|
|
|
|
//
|
|
|
|
// vmisert writes data into vmstorage.
|
|
|
|
// vmselect (L2) reads that data via vmselect (L1).
|
|
|
|
|
|
|
|
cli := tc.Client()
|
|
|
|
|
|
|
|
vmstorage := apptest.MustStartVmstorage(t, "vmstorage", []string{
|
|
|
|
"-storageDataPath=" + tc.Dir() + "/vmstorage",
|
|
|
|
}, cli)
|
|
|
|
defer vmstorage.Stop()
|
|
|
|
vminsert := apptest.MustStartVminsert(t, "vminsert", []string{
|
|
|
|
"-storageNode=" + vmstorage.VminsertAddr(),
|
|
|
|
}, cli)
|
|
|
|
defer vminsert.Stop()
|
|
|
|
vmselectL1 := apptest.MustStartVmselect(t, "vmselect-level1", []string{
|
|
|
|
"-storageNode=" + vmstorage.VmselectAddr(),
|
|
|
|
}, cli)
|
|
|
|
defer vmselectL1.Stop()
|
|
|
|
vmselectL2 := apptest.MustStartVmselect(t, "vmselect-level2", []string{
|
|
|
|
"-storageNode=" + vmselectL1.ClusternativeListenAddr(),
|
|
|
|
}, cli)
|
|
|
|
defer vmselectL2.Stop()
|
|
|
|
|
|
|
|
// Insert 1000 unique time series.Wait for 2 seconds to let vmstorage
|
|
|
|
// flush pending items so they become searchable.
|
|
|
|
|
|
|
|
const numMetrics = 1000
|
|
|
|
records := make([]string, numMetrics)
|
|
|
|
for i := range numMetrics {
|
|
|
|
records[i] = fmt.Sprintf("metric_%d %d", i, rand.IntN(1000))
|
|
|
|
}
|
2024-11-07 11:58:37 +00:00
|
|
|
vminsert.PrometheusAPIV1ImportPrometheus(t, records, apptest.QueryOpts{Tenant: "0"})
|
2024-10-30 14:22:06 +00:00
|
|
|
time.Sleep(2 * time.Second)
|
|
|
|
|
|
|
|
// Retrieve all time series and verify that vmselect (L1) serves the complete
|
|
|
|
// set of time series.
|
|
|
|
|
2024-11-07 11:58:37 +00:00
|
|
|
seriesL1 := vmselectL1.PrometheusAPIV1Series(t, `{__name__=~".*"}`, apptest.QueryOpts{Tenant: "0"})
|
2024-10-30 14:22:06 +00:00
|
|
|
if got, want := len(seriesL1.Data), numMetrics; got != want {
|
|
|
|
t.Fatalf("unexpected level-1 series count: got %d, want %d", got, want)
|
|
|
|
}
|
|
|
|
|
|
|
|
// Retrieve all time series and verify that vmselect (L2) serves the complete
|
|
|
|
// set of time series.
|
|
|
|
|
2024-11-07 11:58:37 +00:00
|
|
|
seriesL2 := vmselectL2.PrometheusAPIV1Series(t, `{__name__=~".*"}`, apptest.QueryOpts{Tenant: "0"})
|
2024-10-30 14:22:06 +00:00
|
|
|
if got, want := len(seriesL2.Data), numMetrics; got != want {
|
|
|
|
t.Fatalf("unexpected level-2 series count: got %d, want %d", got, want)
|
|
|
|
}
|
|
|
|
}
|