mirror of
https://github.com/hanzoai/metrics.git
synced 2026-10-30 20:03:39 +00:00
The import aliases may complicate maintenance of the code in the long term if they aren't used consistently, e.g. if one file imports the apptest under the default name while the other file imports the apptest under the "at" name. The aliases also complicate grepping the code by apptest.* or prompbmarshal.* .
273 lines
10 KiB
Go
273 lines
10 KiB
Go
package tests
|
|
|
|
import (
|
|
"fmt"
|
|
"strings"
|
|
"testing"
|
|
|
|
"github.com/google/go-cmp/cmp"
|
|
"github.com/google/go-cmp/cmp/cmpopts"
|
|
|
|
"github.com/VictoriaMetrics/VictoriaMetrics/apptest"
|
|
"github.com/VictoriaMetrics/VictoriaMetrics/lib/fs"
|
|
)
|
|
|
|
func TestSingleMetricNamesStats(t *testing.T) {
|
|
fs.MustRemoveDir(t.Name())
|
|
tc := apptest.NewTestCase(t)
|
|
defer tc.Stop()
|
|
sut := tc.MustStartVmsingle("vmsingle", []string{"-storage.trackMetricNamesStats=true", "-retentionPeriod=100y"})
|
|
|
|
const ingestDateTime = `2024-02-05T08:57:36.700Z`
|
|
const ingestTimestamp = ` 1707123456700`
|
|
const date = `2024-02-05`
|
|
dataSet := []string{
|
|
`metric_name_1{label="foo"} 10`,
|
|
`metric_name_1{label="bar"} 10`,
|
|
`metric_name_2{label="baz"} 20`,
|
|
`metric_name_1{label="baz"} 10`,
|
|
`metric_name_3{label="baz"} 30`,
|
|
}
|
|
largeMetricName := strings.Repeat("large_metric_name_", 32) + "1"
|
|
dataSet = append(dataSet, largeMetricName+`{label="bar"} 50`)
|
|
|
|
for idx := range dataSet {
|
|
dataSet[idx] += ingestTimestamp
|
|
}
|
|
tsdbMetricNameEntryCmpOpts := cmpopts.IgnoreFields(apptest.TSDBStatusResponseMetricNameEntry{}, "LastRequestTimestamp")
|
|
|
|
sut.PrometheusAPIV1ImportPrometheus(t, dataSet, apptest.QueryOpts{})
|
|
sut.ForceFlush(t)
|
|
|
|
// verify ingest request correctly registered
|
|
expected := apptest.MetricNamesStatsResponse{
|
|
Records: []apptest.MetricNamesStatsRecord{
|
|
{MetricName: largeMetricName},
|
|
{MetricName: "metric_name_1"},
|
|
{MetricName: "metric_name_2"},
|
|
{MetricName: "metric_name_3"},
|
|
},
|
|
}
|
|
got := sut.APIV1StatusMetricNamesStats(t, "", "", "", apptest.QueryOpts{})
|
|
if diff := cmp.Diff(expected, got); diff != "" {
|
|
t.Errorf("unexpected response (-want, +got):\n%s", diff)
|
|
}
|
|
|
|
// verify query request correctly registered
|
|
sut.PrometheusAPIV1Query(t, `{__name__!=""}`, apptest.QueryOpts{Time: ingestDateTime})
|
|
expected = apptest.MetricNamesStatsResponse{
|
|
Records: []apptest.MetricNamesStatsRecord{
|
|
{MetricName: largeMetricName, QueryRequestsCount: 1},
|
|
{MetricName: "metric_name_1", QueryRequestsCount: 3},
|
|
{MetricName: "metric_name_2", QueryRequestsCount: 1},
|
|
{MetricName: "metric_name_3", QueryRequestsCount: 1},
|
|
},
|
|
}
|
|
got = sut.APIV1StatusMetricNamesStats(t, "", "", "", apptest.QueryOpts{})
|
|
if diff := cmp.Diff(expected, got); diff != "" {
|
|
t.Errorf("unexpected response (-want, +got):\n%s", diff)
|
|
}
|
|
|
|
expectedStatsResponse := apptest.TSDBStatusResponse{
|
|
Data: apptest.TSDBStatusResponseData{
|
|
TotalSeries: 6,
|
|
TotalLabelValuePairs: 12,
|
|
SeriesCountByMetricName: []apptest.TSDBStatusResponseMetricNameEntry{
|
|
{Name: "metric_name_1", RequestsCount: 3},
|
|
{Name: largeMetricName, RequestsCount: 1},
|
|
{Name: "metric_name_2", RequestsCount: 1},
|
|
{Name: "metric_name_3", RequestsCount: 1},
|
|
},
|
|
SeriesCountByLabelName: []apptest.TSDBStatusResponseEntry{{Name: "__name__"}, {Name: "label"}},
|
|
SeriesCountByFocusLabelValue: []apptest.TSDBStatusResponseEntry{},
|
|
SeriesCountByLabelValuePair: []apptest.TSDBStatusResponseEntry{
|
|
{Name: "__name__=" + largeMetricName},
|
|
{Name: "__name__=metric_name_1"}, {Name: "label=baz"},
|
|
{Name: "__name__=metric_name_2"}, {Name: "__name__=metric_name_3"},
|
|
{Name: "label=bar"}, {Name: "label=foo"},
|
|
},
|
|
LabelValueCountByLabelName: []apptest.TSDBStatusResponseEntry{{Name: "__name__"}, {Name: "label"}},
|
|
},
|
|
}
|
|
expectedStatsResponse.Sort()
|
|
gotStatus := sut.APIV1StatusTSDB(t, "", date, "", apptest.QueryOpts{})
|
|
if diff := cmp.Diff(expectedStatsResponse, gotStatus, tsdbMetricNameEntryCmpOpts); diff != "" {
|
|
t.Errorf("unexpected APIV1StatusTSDB response (-want, +got):\n%s", diff)
|
|
}
|
|
|
|
// perform query request for single metric and check counter increase
|
|
sut.PrometheusAPIV1Query(t, `metric_name_2`, apptest.QueryOpts{Time: ingestDateTime})
|
|
expected = apptest.MetricNamesStatsResponse{
|
|
Records: []apptest.MetricNamesStatsRecord{
|
|
{MetricName: largeMetricName, QueryRequestsCount: 1},
|
|
{MetricName: "metric_name_1", QueryRequestsCount: 3},
|
|
{MetricName: "metric_name_2", QueryRequestsCount: 2},
|
|
{MetricName: "metric_name_3", QueryRequestsCount: 1},
|
|
},
|
|
}
|
|
got = sut.APIV1StatusMetricNamesStats(t, "", "", "", apptest.QueryOpts{})
|
|
if diff := cmp.Diff(expected, got); diff != "" {
|
|
t.Errorf("unexpected response (-want, +got):\n%s", diff)
|
|
}
|
|
|
|
// verify le filter
|
|
expected = apptest.MetricNamesStatsResponse{
|
|
Records: []apptest.MetricNamesStatsRecord{
|
|
{MetricName: largeMetricName, QueryRequestsCount: 1},
|
|
{MetricName: "metric_name_2", QueryRequestsCount: 2},
|
|
{MetricName: "metric_name_3", QueryRequestsCount: 1},
|
|
},
|
|
}
|
|
got = sut.APIV1StatusMetricNamesStats(t, "", "2", "", apptest.QueryOpts{})
|
|
if diff := cmp.Diff(expected, got); diff != "" {
|
|
t.Errorf("unexpected response (-want, +got):\n%s", diff)
|
|
}
|
|
|
|
// reset state and check empty request response
|
|
sut.APIV1AdminStatusMetricNamesStatsReset(t, apptest.QueryOpts{})
|
|
expected = apptest.MetricNamesStatsResponse{
|
|
Records: []apptest.MetricNamesStatsRecord{},
|
|
}
|
|
got = sut.APIV1StatusMetricNamesStats(t, "", "", "", apptest.QueryOpts{})
|
|
if diff := cmp.Diff(expected, got); diff != "" {
|
|
t.Errorf("unexpected response (-want, +got):\n%s", diff)
|
|
}
|
|
|
|
}
|
|
|
|
func TestClusterMetricNamesStats(t *testing.T) {
|
|
fs.MustRemoveDir(t.Name())
|
|
|
|
tc := apptest.NewTestCase(t)
|
|
defer tc.Stop()
|
|
vmstorage1 := tc.MustStartVmstorage("vmstorage-1", []string{
|
|
"-storageDataPath=" + tc.Dir() + "/vmstorage-1",
|
|
"-retentionPeriod=100y",
|
|
"-storage.trackMetricNamesStats",
|
|
})
|
|
vmstorage2 := tc.MustStartVmstorage("vmstorage-2", []string{
|
|
"-storageDataPath=" + tc.Dir() + "/vmstorage-2",
|
|
"-retentionPeriod=100y",
|
|
"-storage.trackMetricNamesStats",
|
|
})
|
|
|
|
vminsert := tc.MustStartVminsert("vminsert", []string{
|
|
fmt.Sprintf("-storageNode=%s,%s", vmstorage1.VminsertAddr(), vmstorage2.VminsertAddr()),
|
|
})
|
|
vmselect := tc.MustStartVmselect("vmselect", []string{
|
|
fmt.Sprintf("-storageNode=%s,%s", vmstorage1.VmselectAddr(), vmstorage2.VmselectAddr()),
|
|
})
|
|
// verify empty stats
|
|
resp := vmselect.MetricNamesStats(t, "", "", "", apptest.QueryOpts{Tenant: "0:0"})
|
|
if len(resp.Records) != 0 {
|
|
t.Fatalf("unexpected resp Records: %d, want: %d", len(resp.Records), 0)
|
|
}
|
|
|
|
const ingestDateTime = `2024-02-05T08:57:36.700Z`
|
|
const ingestTimestamp = ` 1707123456700`
|
|
const date = `2024-02-05`
|
|
dataSet := []string{
|
|
`metric_name_1{label="foo"} 10`,
|
|
`metric_name_1{label="bar"} 10`,
|
|
`metric_name_2{label="baz"} 20`,
|
|
`metric_name_1{label="baz"} 10`,
|
|
`metric_name_3{label="baz"} 30`,
|
|
}
|
|
largeMetricName := strings.Repeat("large_metric_name_", 32) + "1"
|
|
|
|
dataSet = append(dataSet, largeMetricName+`{label="bar"} 50`)
|
|
for idx := range dataSet {
|
|
dataSet[idx] += ingestTimestamp
|
|
}
|
|
|
|
tsdbMetricNameEntryCmpOpts := cmpopts.IgnoreFields(apptest.TSDBStatusResponseMetricNameEntry{}, "LastRequestTimestamp")
|
|
|
|
// ingest per tenant data and verify it with search
|
|
tenantIDs := []string{"1:1", "1:15", "15:15"}
|
|
for _, tenantID := range tenantIDs {
|
|
vminsert.PrometheusAPIV1ImportPrometheus(t, dataSet, apptest.QueryOpts{Tenant: tenantID})
|
|
vmstorage1.ForceFlush(t)
|
|
vmstorage2.ForceFlush(t)
|
|
|
|
// verify ingest request correctly registered
|
|
expected := apptest.MetricNamesStatsResponse{
|
|
Records: []apptest.MetricNamesStatsRecord{
|
|
{MetricName: largeMetricName},
|
|
{MetricName: "metric_name_1"},
|
|
{MetricName: "metric_name_2"},
|
|
{MetricName: "metric_name_3"},
|
|
},
|
|
}
|
|
gotStats := vmselect.MetricNamesStats(t, "", "", "", apptest.QueryOpts{Tenant: tenantID})
|
|
if diff := cmp.Diff(expected, gotStats); diff != "" {
|
|
t.Errorf("unexpected response (-want, +got):\n%s", diff)
|
|
}
|
|
|
|
// verify query request registered correctly
|
|
vmselect.PrometheusAPIV1Query(t, `{__name__!=""}`, apptest.QueryOpts{
|
|
Tenant: tenantID, Time: ingestDateTime,
|
|
})
|
|
|
|
expected = apptest.MetricNamesStatsResponse{
|
|
Records: []apptest.MetricNamesStatsRecord{
|
|
{MetricName: largeMetricName, QueryRequestsCount: 1},
|
|
{MetricName: "metric_name_2", QueryRequestsCount: 1},
|
|
{MetricName: "metric_name_3", QueryRequestsCount: 1},
|
|
{MetricName: "metric_name_1", QueryRequestsCount: 3},
|
|
},
|
|
}
|
|
gotStats = vmselect.MetricNamesStats(t, "", "", "", apptest.QueryOpts{Tenant: tenantID})
|
|
if diff := cmp.Diff(expected, gotStats); diff != "" {
|
|
t.Errorf("unexpected response tenant: %s (-want, +got):\n%s", tenantID, diff)
|
|
}
|
|
|
|
expectedStatsResponse := apptest.TSDBStatusResponse{
|
|
Data: apptest.TSDBStatusResponseData{
|
|
TotalSeries: 6,
|
|
TotalLabelValuePairs: 12,
|
|
SeriesCountByMetricName: []apptest.TSDBStatusResponseMetricNameEntry{
|
|
{Name: "metric_name_1", RequestsCount: 3},
|
|
{Name: largeMetricName, RequestsCount: 1},
|
|
{Name: "metric_name_2", RequestsCount: 1},
|
|
{Name: "metric_name_3", RequestsCount: 1},
|
|
},
|
|
SeriesCountByLabelName: []apptest.TSDBStatusResponseEntry{{Name: "__name__"}, {Name: "label"}},
|
|
SeriesCountByFocusLabelValue: []apptest.TSDBStatusResponseEntry{},
|
|
SeriesCountByLabelValuePair: []apptest.TSDBStatusResponseEntry{
|
|
{Name: "__name__=" + largeMetricName},
|
|
{Name: "__name__=metric_name_1"}, {Name: "label=baz"},
|
|
{Name: "__name__=metric_name_2"}, {Name: "__name__=metric_name_3"},
|
|
{Name: "label=bar"}, {Name: "label=foo"},
|
|
},
|
|
LabelValueCountByLabelName: []apptest.TSDBStatusResponseEntry{{Name: "__name__"}, {Name: "label"}},
|
|
},
|
|
}
|
|
expectedStatsResponse.Sort()
|
|
gotStatus := vmselect.APIV1StatusTSDB(t, "", date, "", apptest.QueryOpts{Tenant: tenantID})
|
|
if diff := cmp.Diff(expectedStatsResponse, gotStatus, tsdbMetricNameEntryCmpOpts); diff != "" {
|
|
t.Errorf("unexpected APIV1StatusTSDB response tenant: %s (-want, +got):\n%s", tenantID, diff)
|
|
}
|
|
}
|
|
|
|
// verify multitenant stats
|
|
expected := apptest.MetricNamesStatsResponse{
|
|
Records: []apptest.MetricNamesStatsRecord{
|
|
{MetricName: largeMetricName, QueryRequestsCount: 3},
|
|
{MetricName: "metric_name_2", QueryRequestsCount: 3},
|
|
{MetricName: "metric_name_3", QueryRequestsCount: 3},
|
|
{MetricName: "metric_name_1", QueryRequestsCount: 9},
|
|
},
|
|
}
|
|
gotStats := vmselect.MetricNamesStats(t, "", "", "", apptest.QueryOpts{Tenant: "multitenant"})
|
|
if diff := cmp.Diff(expected, gotStats); diff != "" {
|
|
t.Errorf("unexpected response (-want, +got):\n%s", diff)
|
|
}
|
|
|
|
// reset cache and check empty state
|
|
vmselect.MetricNamesStatsReset(t, apptest.QueryOpts{})
|
|
resp = vmselect.MetricNamesStats(t, "", "", "", apptest.QueryOpts{Tenant: "multitenant"})
|
|
if len(resp.Records) != 0 {
|
|
t.Fatalf("want 0 records, got: %d", len(resp.Records))
|
|
}
|
|
}
|