mirror of
https://github.com/VictoriaMetrics/VictoriaMetrics.git
synced 2026-08-14 11:44:32 +03:00
Compare commits
7 Commits
dashboards
...
remove-id-
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
331389f4e1 | ||
|
|
1b242a8c71 | ||
|
|
c1f3589248 | ||
|
|
389ad7933e | ||
|
|
1a1c61083d | ||
|
|
8b59f970f3 | ||
|
|
15a21d9791 |
@@ -290,6 +290,8 @@ func (g *Group) updateWith(newGroup *Group) error {
|
||||
g.Headers = newGroup.Headers
|
||||
g.NotifierHeaders = newGroup.NotifierHeaders
|
||||
g.Labels = newGroup.Labels
|
||||
g.EvalDelay = newGroup.EvalDelay
|
||||
g.evalAlignment = newGroup.evalAlignment
|
||||
g.Limit = newGroup.Limit
|
||||
g.checksum = newGroup.checksum
|
||||
g.Rules = newRules
|
||||
@@ -337,7 +339,7 @@ func (g *Group) Init() {
|
||||
i := g.Interval.Seconds()
|
||||
return i
|
||||
})
|
||||
g.metrics.iterationLimit = g.metrics.set.NewGauge(fmt.Sprintf(`vmalert_rule_group_results_limit{%s}`, labels), func() float64 {
|
||||
g.metrics.iterationLimit = g.metrics.set.NewGauge(fmt.Sprintf(`vmalert_group_rule_results_limit{%s}`, labels), func() float64 {
|
||||
g.mu.RLock()
|
||||
limit := g.Limit
|
||||
g.mu.RUnlock()
|
||||
|
||||
@@ -78,6 +78,12 @@ func TestUpdateWith(t *testing.T) {
|
||||
if g.Debug != expect.Debug {
|
||||
t.Fatalf("expected to have debug %v; got %v", expect.Debug, g.Debug)
|
||||
}
|
||||
if !durationPtrEqual(g.EvalDelay, expect.EvalDelay) {
|
||||
t.Fatalf("expected to have eval_delay %v; got %v", expect.EvalDelay, g.EvalDelay)
|
||||
}
|
||||
if !boolPtrEqual(g.evalAlignment, expect.evalAlignment) {
|
||||
t.Fatalf("expected to have eval_alignment %v; got %v", expect.evalAlignment, g.evalAlignment)
|
||||
}
|
||||
}
|
||||
|
||||
// new rule
|
||||
@@ -237,6 +243,37 @@ func TestUpdateWith(t *testing.T) {
|
||||
{Alert: "foo1", Debug: &debug},
|
||||
},
|
||||
})
|
||||
|
||||
// update group evaluation settings
|
||||
evalDelay := promutil.NewDuration(time.Minute)
|
||||
evalAlignment := false
|
||||
f(config.Group{
|
||||
Rules: []config.Rule{{
|
||||
Record: "foo",
|
||||
Expr: "max(up)",
|
||||
}},
|
||||
}, config.Group{
|
||||
EvalDelay: evalDelay,
|
||||
EvalAlignment: &evalAlignment,
|
||||
Rules: []config.Rule{{
|
||||
Record: "foo",
|
||||
Expr: "min(up)",
|
||||
}},
|
||||
})
|
||||
}
|
||||
|
||||
func durationPtrEqual(a, b *time.Duration) bool {
|
||||
if a == nil || b == nil {
|
||||
return a == b
|
||||
}
|
||||
return *a == *b
|
||||
}
|
||||
|
||||
func boolPtrEqual(a, b *bool) bool {
|
||||
if a == nil || b == nil {
|
||||
return a == b
|
||||
}
|
||||
return *a == *b
|
||||
}
|
||||
|
||||
func TestUpdateDuringRandSleep(t *testing.T) {
|
||||
|
||||
@@ -25,7 +25,6 @@
|
||||
"editable": true,
|
||||
"fiscalYearStartMonth": 0,
|
||||
"graphTooltip": 1,
|
||||
"id": 3,
|
||||
"links": [
|
||||
{
|
||||
"icon": "doc",
|
||||
|
||||
@@ -62,7 +62,6 @@
|
||||
"editable": true,
|
||||
"fiscalYearStartMonth": 0,
|
||||
"graphTooltip": 1,
|
||||
"id": 13,
|
||||
"links": [
|
||||
{
|
||||
"icon": "doc",
|
||||
|
||||
@@ -50,7 +50,6 @@
|
||||
"editable": true,
|
||||
"fiscalYearStartMonth": 0,
|
||||
"graphTooltip": 1,
|
||||
"id": 3,
|
||||
"links": [
|
||||
{
|
||||
"icon": "doc",
|
||||
|
||||
@@ -50,7 +50,6 @@
|
||||
"editable": true,
|
||||
"fiscalYearStartMonth": 0,
|
||||
"graphTooltip": 1,
|
||||
"id": 3,
|
||||
"links": [
|
||||
{
|
||||
"icon": "doc",
|
||||
|
||||
@@ -38,6 +38,9 @@ See also [LTS releases](https://docs.victoriametrics.com/victoriametrics/lts-rel
|
||||
* BUGFIX: [vmsingle](https://docs.victoriametrics.com/victoriametrics/single-server-victoriametrics/) and `vmselect` in [VictoriaMetrics cluster](https://docs.victoriametrics.com/victoriametrics/cluster-victoriametrics/): change the HTTP response code for [Prometheus querying API](https://docs.victoriametrics.com/victoriametrics/single-server-victoriametrics/#prometheus-querying-api-usage) requests from `422 Unprocessable Entity` to `400 Bad Request` when request parameters are missing or incorrect. See [#11330](https://github.com/VictoriaMetrics/VictoriaMetrics/issues/11330).
|
||||
* BUGFIX: [vmui](https://docs.victoriametrics.com/victoriametrics/single-server-victoriametrics/#vmui): respect the custom query step specified via `g0.step_input` when opening a URL. Previously, it could be reset to the automatically calculated step and potentially cause dashboards to freeze. See [#11137](https://github.com/VictoriaMetrics/VictoriaMetrics/issues/11137).
|
||||
* BUGFIX: [vmagent](https://docs.victoriametrics.com/victoriametrics/vmagent/) and [vmsingle](https://docs.victoriametrics.com/victoriametrics/single-server-victoriametrics/): properly assign scrape target IP address at IPv6-only networks for [docker_sd_configs](https://docs.victoriametrics.com/victoriametrics/sd_configs/#docker_sd_configs). See [#10965](https://github.com/VictoriaMetrics/VictoriaMetrics/issues/10965).
|
||||
* BUGFIX: [vmalert](https://docs.victoriametrics.com/victoriametrics/vmalert/): rename `vmalert_rule_group_results_limit` back to `vmalert_group_rule_results_limit`. The metric was introduced in [v1.147.0](https://docs.victoriametrics.com/victoriametrics/changelog/#v11470) but was accidentally given the wrong name. See [#11179](https://github.com/VictoriaMetrics/VictoriaMetrics/issues/11179).
|
||||
* BUGFIX: [vmalert](https://docs.victoriametrics.com/victoriametrics/vmalert/): properly update group-level `eval_delay` and `eval_alignment` for existing groups during runtime when config reload is triggered periodically or manually via `/-/reload`. Previously, these settings weren't updated after config reload during runtime. See [#11374](https://github.com/VictoriaMetrics/VictoriaMetrics/issues/11374).
|
||||
* BUGFIX: `vmselect` in [VictoriaMetrics cluster](https://docs.victoriametrics.com/victoriametrics/cluster-victoriametrics/): scale the default `-search.maxConcurrentRequests` with the number of available CPU cores instead of capping it at 16. See [#11191](https://github.com/VictoriaMetrics/VictoriaMetrics/issues/11191). Thanks to @Dhru1Tanna for contribution.
|
||||
|
||||
## [v1.149.0](https://github.com/VictoriaMetrics/VictoriaMetrics/releases/tag/v1.149.0)
|
||||
|
||||
|
||||
@@ -99,7 +99,7 @@ type indexDB struct {
|
||||
// legacy indexDBs, since these indexDBs are readonly.
|
||||
// This field cannot be used for the partition indexDBs, since they may receive data
|
||||
// with bigger timestamps at any time.
|
||||
legacyMinMissingTimestampByKey map[string]int64
|
||||
legacyMinMissingTimestampByKey map[TenantToken]int64
|
||||
// protects legacyMinMissingTimestampByKey
|
||||
legacyMinMissingTimestampByKeyLock sync.Mutex
|
||||
|
||||
@@ -174,7 +174,7 @@ func mustOpenIndexDB(id uint64, tr TimeRange, name, path string, s *Storage, isR
|
||||
tfssCache := lrucache.NewCache(getTagFiltersCacheSize)
|
||||
tb := mergeset.MustOpenTable(path, dataFlushInterval, tfssCache.Reset, 0, mergeTagToMetricIDsRows, isReadOnly)
|
||||
db := &indexDB{
|
||||
legacyMinMissingTimestampByKey: make(map[string]int64),
|
||||
legacyMinMissingTimestampByKey: make(map[TenantToken]int64),
|
||||
id: id,
|
||||
tr: tr,
|
||||
name: name,
|
||||
@@ -508,6 +508,11 @@ func (db *indexDB) SearchLabelNames(qt *querytracer.Tracer, tfss []*TagFilters,
|
||||
qt = qt.NewChild("search label names: filters=%s, timeRange=%s, maxLabelNames=%d, maxMetrics=%d", tfss, &tr, maxLabelNames, maxMetrics)
|
||||
defer qt.Done()
|
||||
|
||||
if !db.legacyContainsTimeRange(tr) {
|
||||
qt.Printf("indexDB doesn't contain data for the given time range: %v", &tr)
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
is := db.getIndexSearch(deadline)
|
||||
lns, err := is.searchLabelNamesWithFiltersOnTimeRange(qt, tfss, tr, maxLabelNames, maxMetrics)
|
||||
db.putIndexSearch(is)
|
||||
@@ -710,6 +715,11 @@ func (db *indexDB) SearchLabelValues(qt *querytracer.Tracer, labelName string, t
|
||||
qt = qt.NewChild("search label values: labelName=%q, filters=%s, timeRange=%s, maxLabelValues=%d, maxMetrics=%d", labelName, tfss, &tr, maxLabelValues, maxMetrics)
|
||||
defer qt.Done()
|
||||
|
||||
if !db.legacyContainsTimeRange(tr) {
|
||||
qt.Printf("indexDB doesn't contain data for the given time range: %v", &tr)
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
key := labelName
|
||||
if key == "__name__" {
|
||||
key = ""
|
||||
@@ -958,6 +968,11 @@ func (db *indexDB) SearchTagValueSuffixes(qt *querytracer.Tracer, tr TimeRange,
|
||||
&tr, tagKey, tagValuePrefix, delimiter, maxTagValueSuffixes)
|
||||
defer qt.Done()
|
||||
|
||||
if !db.legacyContainsTimeRange(tr) {
|
||||
qt.Printf("indexDB doesn't contain data for the given time range: %v", &tr)
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
// TODO: cache results?
|
||||
|
||||
is := db.getIndexSearch(deadline)
|
||||
@@ -1092,6 +1107,11 @@ func (db *indexDB) SearchGraphitePaths(qt *querytracer.Tracer, tr TimeRange, qHe
|
||||
qt = qt.NewChild("search graphite paths: timeRange=%s, qHead=%q, qTail=%q, maxPaths=%d", &tr, bytesutil.ToUnsafeString(qHead), bytesutil.ToUnsafeString(qTail), maxPaths)
|
||||
defer qt.Done()
|
||||
|
||||
if !db.legacyContainsTimeRange(tr) {
|
||||
qt.Printf("indexDB doesn't contain data for the given time range: %v", &tr)
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
n := bytes.IndexAny(qTail, "*[{")
|
||||
if n < 0 {
|
||||
// Verify that qHead matches a metric name.
|
||||
@@ -1273,6 +1293,11 @@ func (db *indexDB) GetTSDBStatus(qt *querytracer.Tracer, tfss []*TagFilters, dat
|
||||
qt = qt.NewChild("collect TSDB status: filters=%s, date=%s, focusLabel=%q, topN=%d, maxMetrics=%d", tfss, dateToString(date), focusLabel, topN, maxMetrics)
|
||||
defer qt.Done()
|
||||
|
||||
if !db.legacyContainsDate(date) {
|
||||
qt.Printf("indexDB doesn't contain data for the given date: %s", dateToString(date))
|
||||
return &TSDBStatus{}, nil
|
||||
}
|
||||
|
||||
is := db.getIndexSearch(deadline)
|
||||
defer db.putIndexSearch(is)
|
||||
status, err := is.getTSDBStatus(qt, tfss, date, focusLabel, topN, maxMetrics)
|
||||
@@ -1720,6 +1745,11 @@ func (db *indexDB) SearchTSIDs(qt *querytracer.Tracer, tfss []*TagFilters, tr Ti
|
||||
qt = qt.NewChild("search TSIDs: filters=%s, timeRange=%s, maxMetrics=%d", tfss, &tr, maxMetrics)
|
||||
defer qt.Done()
|
||||
|
||||
if !db.legacyContainsTimeRange(tr) {
|
||||
qt.Printf("indexDB doesn't contain data for the given time range: %v", &tr)
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
metricIDs, err := db.searchMetricIDs(qt, tfss, tr, maxMetrics, deadline)
|
||||
if err != nil {
|
||||
return nil, db.wrapError("search TSIDs", err)
|
||||
@@ -1803,6 +1833,11 @@ func (db *indexDB) SearchMetricNames(qt *querytracer.Tracer, tfss []*TagFilters,
|
||||
qt = qt.NewChild("search metric names: filters=%s, timeRange=%s, maxMetrics=%d", tfss, &tr, maxMetrics)
|
||||
defer qt.Done()
|
||||
|
||||
if !db.legacyContainsTimeRange(tr) {
|
||||
qt.Printf("indexDB doesn't contain data for the given time range: %v", &tr)
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
metricIDs, err := db.searchMetricIDs(qt, tfss, tr, maxMetrics, deadline)
|
||||
if err != nil {
|
||||
return nil, db.wrapError("search metric names", err)
|
||||
@@ -2219,18 +2254,12 @@ func (is *indexSearch) searchMetricIDsInternal(qt *querytracer.Tracer, tfss []*T
|
||||
qt = qt.NewChild("search for metric ids: filters=%s, timeRange=%s, maxMetrics=%d", tfss, &tr, maxMetrics)
|
||||
defer qt.Done()
|
||||
|
||||
metricIDs := &uint64set.Set{}
|
||||
|
||||
if !is.legacyContainsTimeRange(tr) {
|
||||
qt.Printf("indexdb doesn't contain data for the given timeRange=%s", &tr)
|
||||
return metricIDs, nil
|
||||
}
|
||||
|
||||
if tr.MinTimestamp >= is.db.s.minTimestampForCompositeIndex {
|
||||
tfss = convertToCompositeTagFilterss(tfss)
|
||||
qt.Printf("composite filters=%s", tfss)
|
||||
}
|
||||
|
||||
metricIDs := &uint64set.Set{}
|
||||
for _, tfs := range tfss {
|
||||
if len(tfs.tfs) == 0 {
|
||||
// An empty filters must be equivalent to `{__name__!=""}`
|
||||
|
||||
@@ -7,7 +7,6 @@ import (
|
||||
"strconv"
|
||||
"sync/atomic"
|
||||
|
||||
"github.com/VictoriaMetrics/VictoriaMetrics/lib/bytesutil"
|
||||
"github.com/VictoriaMetrics/VictoriaMetrics/lib/encoding"
|
||||
"github.com/VictoriaMetrics/VictoriaMetrics/lib/fs"
|
||||
"github.com/VictoriaMetrics/VictoriaMetrics/lib/logger"
|
||||
@@ -87,48 +86,61 @@ func mustOpenLegacyIndexDB(path string, s *Storage) *legacyIndexDB {
|
||||
return legacyIDB
|
||||
}
|
||||
|
||||
func (is *indexSearch) legacyContainsTimeRange(tr TimeRange) bool {
|
||||
func (db *indexDB) legacyContainsDate(date uint64) bool {
|
||||
var tr TimeRange
|
||||
if date == globalIndexDate {
|
||||
tr = globalIndexTimeRange
|
||||
} else {
|
||||
tr.MinTimestamp = int64(date) * msecPerDay
|
||||
tr.MaxTimestamp = int64(date+1)*msecPerDay - 1
|
||||
}
|
||||
return db.legacyContainsTimeRange(tr)
|
||||
}
|
||||
|
||||
func (db *indexDB) legacyContainsTimeRange(tr TimeRange) bool {
|
||||
if tr == globalIndexTimeRange {
|
||||
return true
|
||||
}
|
||||
|
||||
db := is.db
|
||||
if !db.noRegisterNewSeries.Load() {
|
||||
// indexDB could register new time series - it is not safe to cache minMissingTimestamp
|
||||
return true
|
||||
}
|
||||
|
||||
// use common prefix as a key for minMissingTimestamp
|
||||
// it's needed to properly track timestamps for cluster version
|
||||
// which uses tenant labels for the index search
|
||||
kb := &is.kb
|
||||
kb.B = is.marshalCommonPrefix(kb.B[:0], nsPrefixDateToMetricID)
|
||||
key := kb.B
|
||||
|
||||
// vmsingle does not have tenants and therefore has just one key.
|
||||
// While vmstorage can potentially have many tenants and the actual
|
||||
// accountID and projectID will be set from the request.
|
||||
key := TenantToken{
|
||||
AccountID: 0,
|
||||
ProjectID: 0,
|
||||
}
|
||||
db.legacyMinMissingTimestampByKeyLock.Lock()
|
||||
minMissingTimestamp, ok := db.legacyMinMissingTimestampByKey[string(key)]
|
||||
minMissingTimestamp, ok := db.legacyMinMissingTimestampByKey[key]
|
||||
db.legacyMinMissingTimestampByKeyLock.Unlock()
|
||||
|
||||
if ok && tr.MinTimestamp >= minMissingTimestamp {
|
||||
// Fast path.
|
||||
return false
|
||||
}
|
||||
if is.legacyContainsTimeRangeSlow(kb, tr) {
|
||||
|
||||
// Slow path.
|
||||
is := db.getIndexSearch(noDeadline)
|
||||
defer db.putIndexSearch(is)
|
||||
if is.legacyContainsTimeRange(tr) {
|
||||
return true
|
||||
}
|
||||
|
||||
db.legacyMinMissingTimestampByKeyLock.Lock()
|
||||
minMissingTimestamp, ok = db.legacyMinMissingTimestampByKey[string(key)]
|
||||
minMissingTimestamp, ok = db.legacyMinMissingTimestampByKey[key]
|
||||
if !ok || tr.MinTimestamp < minMissingTimestamp {
|
||||
db.legacyMinMissingTimestampByKey[string(key)] = tr.MinTimestamp
|
||||
db.legacyMinMissingTimestampByKey[key] = tr.MinTimestamp
|
||||
}
|
||||
db.legacyMinMissingTimestampByKeyLock.Unlock()
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
func (is *indexSearch) legacyContainsTimeRangeSlow(prefixBuf *bytesutil.ByteBuffer, tr TimeRange) bool {
|
||||
ts := &is.ts
|
||||
|
||||
func (is *indexSearch) legacyContainsTimeRange(tr TimeRange) bool {
|
||||
// Verify whether the tr.MinTimestamp is included into `ts` or is smaller than the minimum date stored in `ts`.
|
||||
// Do not check whether tr.MaxTimestamp is included into `ts` or is bigger than the max date stored in `ts` for performance reasons.
|
||||
// This means that this func can return true if `tr` is located below the min date stored in `ts`.
|
||||
@@ -136,12 +148,17 @@ func (is *indexSearch) legacyContainsTimeRangeSlow(prefixBuf *bytesutil.ByteBuff
|
||||
// The main practical case allows skipping searching in prev indexdb (`ts`) when `tr`
|
||||
// is located above the max date stored there.
|
||||
minDate := uint64(tr.MinTimestamp) / msecPerDay
|
||||
prefix := prefixBuf.B
|
||||
prefixBuf.B = encoding.MarshalUint64(prefixBuf.B, minDate)
|
||||
ts.Seek(prefixBuf.B)
|
||||
|
||||
kb := &is.kb
|
||||
kb.B = is.marshalCommonPrefix(kb.B[:0], nsPrefixDateToMetricID)
|
||||
prefix := kb.B
|
||||
kb.B = encoding.MarshalUint64(kb.B, minDate)
|
||||
|
||||
ts := &is.ts
|
||||
ts.Seek(kb.B)
|
||||
if !ts.NextItem() {
|
||||
if err := ts.Error(); err != nil {
|
||||
logger.Panicf("FATAL: error when searching for minDate=%d, prefix %q: %s", minDate, prefixBuf.B, err)
|
||||
logger.Panicf("FATAL: error when searching for minDate=%d, prefix %q: %s", minDate, kb.B, err)
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
@@ -29,11 +29,7 @@ func TestLegacyContainsTimeRange(t *testing.T) {
|
||||
|
||||
f := func(idb *indexDB, tr TimeRange, want bool) {
|
||||
t.Helper()
|
||||
is := idb.getIndexSearch(noDeadline)
|
||||
defer idb.putIndexSearch(is)
|
||||
|
||||
got := is.legacyContainsTimeRange(tr)
|
||||
|
||||
got := idb.legacyContainsTimeRange(tr)
|
||||
if got != want {
|
||||
t.Fatalf("legacyContainsTimeRange(%s) for index db %s returns unexpected result: got %t, want %t", tr.String(), idb.name, got, want)
|
||||
}
|
||||
@@ -97,8 +93,8 @@ func TestLegacyContainsTimeRange(t *testing.T) {
|
||||
f(legacyIDBs.getIDBCurr(), tr, true)
|
||||
f(idb, tr, true)
|
||||
|
||||
// Fully inside trPt, overlaps with trPrev on the right side and trCurr on
|
||||
// the left side.
|
||||
// Fully inside trPt, overlaps with trPrev on the right side and with trCurr
|
||||
// on the left side.
|
||||
tr = TimeRange{
|
||||
MinTimestamp: time.Date(2025, 1, 7, 0, 0, 0, 0, time.UTC).UnixMilli(),
|
||||
MaxTimestamp: time.Date(2025, 1, 21, 23, 59, 59, 999_999_999, time.UTC).UnixMilli(),
|
||||
|
||||
@@ -2241,15 +2241,16 @@ func TestIndexSearchLegacyContainsTimeRange_Concurrent(t *testing.T) {
|
||||
for i := range concurrency {
|
||||
ts := minTimestamp + msecPerDay*i
|
||||
wg.Go(func() {
|
||||
is := idb.getIndexSearch(noDeadline)
|
||||
_ = is.legacyContainsTimeRange(TimeRange{ts, ts})
|
||||
idb.putIndexSearch(is)
|
||||
_ = idb.legacyContainsTimeRange(TimeRange{ts, ts})
|
||||
})
|
||||
}
|
||||
wg.Wait()
|
||||
|
||||
key := marshalCommonPrefix(nil, nsPrefixDateToMetricID)
|
||||
if got, want := idb.legacyMinMissingTimestampByKey[string(key)], minTimestamp; got != want {
|
||||
key := TenantToken{
|
||||
AccountID: 0,
|
||||
ProjectID: 0,
|
||||
}
|
||||
if got, want := idb.legacyMinMissingTimestampByKey[key], minTimestamp; got != want {
|
||||
t.Fatalf("unexpected min timestamp: got %v, want %v", time.UnixMilli(got).UTC(), time.UnixMilli(want).UTC())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -33,16 +33,22 @@ func TestLegacyStorage_SearchMetricNames(t *testing.T) {
|
||||
return mrs, want
|
||||
}
|
||||
const numMetrics = 1000
|
||||
tr := TimeRange{
|
||||
tr1 := TimeRange{
|
||||
MinTimestamp: time.Date(2023, 6, 1, 0, 0, 0, 0, time.UTC).UnixMilli(),
|
||||
MaxTimestamp: time.Date(2024, 5, 31, 23, 59, 59, 999_999_999, time.UTC).UnixMilli(),
|
||||
}
|
||||
legacyData, wantLegacy := genData(numMetrics, "legacy", tr)
|
||||
newData, wantNew := genData(numMetrics, "new", tr)
|
||||
wantNew = append(wantNew, wantLegacy...)
|
||||
slices.Sort(wantNew)
|
||||
tr2 := TimeRange{
|
||||
MinTimestamp: time.Date(2024, 6, 1, 0, 0, 0, 0, time.UTC).UnixMilli(),
|
||||
MaxTimestamp: time.Date(2024, 6, 30, 23, 59, 59, 999_999_999, time.UTC).UnixMilli(),
|
||||
}
|
||||
legacyData, wantLegacy := genData(numMetrics, "legacy", tr1)
|
||||
new1Data, wantNew1 := genData(numMetrics, "new1", tr1)
|
||||
new2Data, wantNew2 := genData(numMetrics, "new2", tr2)
|
||||
newData := slices.Concat(new1Data, new2Data)
|
||||
wantLegacyAndNew1 := slices.Concat(wantLegacy, wantNew1)
|
||||
slices.Sort(wantLegacyAndNew1)
|
||||
|
||||
assertSearchResults := func(s *Storage, want []string) {
|
||||
assertSearchResults := func(s *Storage, tr TimeRange, want []string) {
|
||||
t.Helper()
|
||||
tfsAll := NewTagFilters()
|
||||
if err := tfsAll.Add([]byte("__name__"), []byte(".*"), false, true); err != nil {
|
||||
@@ -67,10 +73,11 @@ func TestLegacyStorage_SearchMetricNames(t *testing.T) {
|
||||
}
|
||||
|
||||
assertLegacyData := func(s *Storage) {
|
||||
assertSearchResults(s, wantLegacy)
|
||||
assertSearchResults(s, tr1, wantLegacy)
|
||||
}
|
||||
assertNewData := func(s *Storage) {
|
||||
assertSearchResults(s, wantNew)
|
||||
assertSearchResults(s, tr1, wantLegacyAndNew1)
|
||||
assertSearchResults(s, tr2, wantNew2)
|
||||
}
|
||||
testSearchOpWithLegacyIndexDBs(t, legacyData, newData, assertLegacyData, assertNewData)
|
||||
}
|
||||
@@ -95,15 +102,22 @@ func TestLegacyStorage_SearchLabelNames(t *testing.T) {
|
||||
return mrs, want
|
||||
}
|
||||
const numMetrics = 1000
|
||||
tr := TimeRange{
|
||||
tr1 := TimeRange{
|
||||
MinTimestamp: time.Date(2023, 6, 1, 0, 0, 0, 0, time.UTC).UnixMilli(),
|
||||
MaxTimestamp: time.Date(2024, 5, 31, 23, 59, 59, 999_999_999, time.UTC).UnixMilli(),
|
||||
}
|
||||
legacyData, wantLegacy := genData(numMetrics, "legacy", tr)
|
||||
newData, wantNew := genData(numMetrics, "new", tr)
|
||||
wantNew = append(wantNew, wantLegacy...)
|
||||
tr2 := TimeRange{
|
||||
MinTimestamp: time.Date(2024, 6, 1, 0, 0, 0, 0, time.UTC).UnixMilli(),
|
||||
MaxTimestamp: time.Date(2024, 6, 30, 23, 59, 59, 999_999_999, time.UTC).UnixMilli(),
|
||||
}
|
||||
legacyData, wantLegacy := genData(numMetrics, "legacy", tr1)
|
||||
new1Data, wantNew1 := genData(numMetrics, "new1", tr1)
|
||||
new2Data, wantNew2 := genData(numMetrics, "new2", tr2)
|
||||
newData := slices.Concat(new1Data, new2Data)
|
||||
wantLegacyAndNew1 := slices.Concat(wantLegacy, wantNew1)
|
||||
slices.Sort(wantLegacyAndNew1)
|
||||
|
||||
assertSearchResults := func(s *Storage, want []string) {
|
||||
assertSearchResults := func(s *Storage, tr TimeRange, want []string) {
|
||||
t.Helper()
|
||||
got, err := s.SearchLabelNames(nil, nil, tr, 1e9, 1e9, noDeadline)
|
||||
if err != nil {
|
||||
@@ -118,12 +132,16 @@ func TestLegacyStorage_SearchLabelNames(t *testing.T) {
|
||||
assertLegacyData := func(s *Storage) {
|
||||
want := append(wantLegacy, "__name__")
|
||||
slices.Sort(want)
|
||||
assertSearchResults(s, want)
|
||||
assertSearchResults(s, tr1, want)
|
||||
}
|
||||
assertNewData := func(s *Storage) {
|
||||
want := append(wantNew, "__name__")
|
||||
want := append(wantLegacyAndNew1, "__name__")
|
||||
slices.Sort(want)
|
||||
assertSearchResults(s, want)
|
||||
assertSearchResults(s, tr1, want)
|
||||
|
||||
want = append(wantNew2, "__name__")
|
||||
slices.Sort(want)
|
||||
assertSearchResults(s, tr2, want)
|
||||
}
|
||||
testSearchOpWithLegacyIndexDBs(t, legacyData, newData, assertLegacyData, assertNewData)
|
||||
}
|
||||
@@ -148,16 +166,22 @@ func TestLegacyStorage_SearchLabelValues(t *testing.T) {
|
||||
return mrs, want
|
||||
}
|
||||
const numMetrics = 1000
|
||||
tr := TimeRange{
|
||||
tr1 := TimeRange{
|
||||
MinTimestamp: time.Date(2023, 6, 1, 0, 0, 0, 0, time.UTC).UnixMilli(),
|
||||
MaxTimestamp: time.Date(2024, 5, 31, 23, 59, 59, 999_999_999, time.UTC).UnixMilli(),
|
||||
}
|
||||
legacyData, wantLegacy := genData(numMetrics, "legacy", tr)
|
||||
newData, wantNew := genData(numMetrics, "new", tr)
|
||||
wantNew = append(wantNew, wantLegacy...)
|
||||
slices.Sort(wantNew)
|
||||
tr2 := TimeRange{
|
||||
MinTimestamp: time.Date(2024, 6, 1, 0, 0, 0, 0, time.UTC).UnixMilli(),
|
||||
MaxTimestamp: time.Date(2024, 6, 30, 23, 59, 59, 999_999_999, time.UTC).UnixMilli(),
|
||||
}
|
||||
legacyData, wantLegacy := genData(numMetrics, "legacy", tr1)
|
||||
new1Data, wantNew1 := genData(numMetrics, "new1", tr1)
|
||||
new2Data, wantNew2 := genData(numMetrics, "new2", tr2)
|
||||
newData := slices.Concat(new1Data, new2Data)
|
||||
wantLegacyAndNew1 := slices.Concat(wantLegacy, wantNew1)
|
||||
slices.Sort(wantLegacyAndNew1)
|
||||
|
||||
assertSearchResults := func(s *Storage, want []string) {
|
||||
assertSearchResults := func(s *Storage, tr TimeRange, want []string) {
|
||||
t.Helper()
|
||||
got, err := s.SearchLabelValues(nil, "label", nil, tr, 1e9, 1e9, noDeadline)
|
||||
if err != nil {
|
||||
@@ -171,11 +195,12 @@ func TestLegacyStorage_SearchLabelValues(t *testing.T) {
|
||||
|
||||
assertLegacyData := func(s *Storage) {
|
||||
t.Helper()
|
||||
assertSearchResults(s, wantLegacy)
|
||||
assertSearchResults(s, tr1, wantLegacy)
|
||||
}
|
||||
assertNewData := func(s *Storage) {
|
||||
t.Helper()
|
||||
assertSearchResults(s, wantNew)
|
||||
assertSearchResults(s, tr1, wantLegacyAndNew1)
|
||||
assertSearchResults(s, tr2, wantNew2)
|
||||
}
|
||||
testSearchOpWithLegacyIndexDBs(t, legacyData, newData, assertLegacyData, assertNewData)
|
||||
}
|
||||
@@ -197,16 +222,22 @@ func TestLegacyStorage_SearchTagValueSuffixes(t *testing.T) {
|
||||
return mrs, want
|
||||
}
|
||||
const numMetrics = 1000
|
||||
tr := TimeRange{
|
||||
tr1 := TimeRange{
|
||||
MinTimestamp: time.Date(2023, 6, 1, 0, 0, 0, 0, time.UTC).UnixMilli(),
|
||||
MaxTimestamp: time.Date(2024, 5, 31, 23, 59, 59, 999_999_999, time.UTC).UnixMilli(),
|
||||
}
|
||||
legacyData, wantLegacy := genData(numMetrics, "legacy", tr)
|
||||
newData, wantNew := genData(numMetrics, "new", tr)
|
||||
wantNew = append(wantNew, wantLegacy...)
|
||||
slices.Sort(wantNew)
|
||||
tr2 := TimeRange{
|
||||
MinTimestamp: time.Date(2024, 6, 1, 0, 0, 0, 0, time.UTC).UnixMilli(),
|
||||
MaxTimestamp: time.Date(2024, 6, 30, 23, 59, 59, 999_999_999, time.UTC).UnixMilli(),
|
||||
}
|
||||
legacyData, wantLegacy := genData(numMetrics, "legacy", tr1)
|
||||
new1Data, wantNew1 := genData(numMetrics, "new1", tr1)
|
||||
new2Data, wantNew2 := genData(numMetrics, "new2", tr2)
|
||||
newData := slices.Concat(new1Data, new2Data)
|
||||
wantLegacyAndNew1 := slices.Concat(wantLegacy, wantNew1)
|
||||
slices.Sort(wantLegacyAndNew1)
|
||||
|
||||
assertSearchResults := func(s *Storage, want []string) {
|
||||
assertSearchResults := func(s *Storage, tr TimeRange, want []string) {
|
||||
t.Helper()
|
||||
got, err := s.SearchTagValueSuffixes(nil, tr, "", "prefix.", '.', 1e9, noDeadline)
|
||||
if err != nil {
|
||||
@@ -221,11 +252,12 @@ func TestLegacyStorage_SearchTagValueSuffixes(t *testing.T) {
|
||||
|
||||
assertLegacyData := func(s *Storage) {
|
||||
t.Helper()
|
||||
assertSearchResults(s, wantLegacy)
|
||||
assertSearchResults(s, tr1, wantLegacy)
|
||||
}
|
||||
assertNewData := func(s *Storage) {
|
||||
t.Helper()
|
||||
assertSearchResults(s, wantNew)
|
||||
assertSearchResults(s, tr1, wantLegacyAndNew1)
|
||||
assertSearchResults(s, tr2, wantNew2)
|
||||
}
|
||||
testSearchOpWithLegacyIndexDBs(t, legacyData, newData, assertLegacyData, assertNewData)
|
||||
}
|
||||
@@ -247,16 +279,22 @@ func TestLegacyStorage_SearchGraphitePaths(t *testing.T) {
|
||||
return mrs, want
|
||||
}
|
||||
const numMetrics = 1000
|
||||
tr := TimeRange{
|
||||
tr1 := TimeRange{
|
||||
MinTimestamp: time.Date(2023, 6, 1, 0, 0, 0, 0, time.UTC).UnixMilli(),
|
||||
MaxTimestamp: time.Date(2024, 5, 31, 23, 59, 59, 999_999_999, time.UTC).UnixMilli(),
|
||||
}
|
||||
legacyData, wantLegacy := genData(numMetrics, "legacy", tr)
|
||||
newData, wantNew := genData(numMetrics, "new", tr)
|
||||
wantNew = append(wantNew, wantLegacy...)
|
||||
slices.Sort(wantNew)
|
||||
tr2 := TimeRange{
|
||||
MinTimestamp: time.Date(2024, 6, 1, 0, 0, 0, 0, time.UTC).UnixMilli(),
|
||||
MaxTimestamp: time.Date(2024, 6, 30, 23, 59, 59, 999_999_999, time.UTC).UnixMilli(),
|
||||
}
|
||||
legacyData, wantLegacy := genData(numMetrics, "legacy", tr1)
|
||||
new1Data, wantNew1 := genData(numMetrics, "new1", tr1)
|
||||
new2Data, wantNew2 := genData(numMetrics, "new2", tr2)
|
||||
newData := slices.Concat(new1Data, new2Data)
|
||||
wantLegacyAndNew1 := slices.Concat(wantLegacy, wantNew1)
|
||||
slices.Sort(wantLegacyAndNew1)
|
||||
|
||||
assertSearchResults := func(s *Storage, want []string) {
|
||||
assertSearchResults := func(s *Storage, tr TimeRange, want []string) {
|
||||
t.Helper()
|
||||
got, err := s.SearchGraphitePaths(nil, tr, []byte("*.*"), 1e9, noDeadline)
|
||||
if err != nil {
|
||||
@@ -271,16 +309,17 @@ func TestLegacyStorage_SearchGraphitePaths(t *testing.T) {
|
||||
|
||||
assertLegacyData := func(s *Storage) {
|
||||
t.Helper()
|
||||
assertSearchResults(s, wantLegacy)
|
||||
assertSearchResults(s, tr1, wantLegacy)
|
||||
}
|
||||
assertNewData := func(s *Storage) {
|
||||
t.Helper()
|
||||
assertSearchResults(s, wantNew)
|
||||
assertSearchResults(s, tr1, wantLegacyAndNew1)
|
||||
assertSearchResults(s, tr2, wantNew2)
|
||||
}
|
||||
testSearchOpWithLegacyIndexDBs(t, legacyData, newData, assertLegacyData, assertNewData)
|
||||
}
|
||||
|
||||
func TestLegacyStorage_Search(t *testing.T) {
|
||||
func TestLegacyStorage_SearchData(t *testing.T) {
|
||||
genData := func(numMetrics int, prefix string, tr TimeRange) []MetricRow {
|
||||
mrs := make([]MetricRow, numMetrics)
|
||||
for i := range numMetrics {
|
||||
@@ -295,14 +334,20 @@ func TestLegacyStorage_Search(t *testing.T) {
|
||||
return mrs
|
||||
}
|
||||
const numMetrics = 1000
|
||||
tr := TimeRange{
|
||||
tr1 := TimeRange{
|
||||
MinTimestamp: time.Date(2023, 6, 1, 0, 0, 0, 0, time.UTC).UnixMilli(),
|
||||
MaxTimestamp: time.Date(2024, 5, 31, 23, 59, 59, 999_999_999, time.UTC).UnixMilli(),
|
||||
}
|
||||
legacyData := genData(numMetrics, "legacy", tr)
|
||||
newData := genData(numMetrics, "new", tr)
|
||||
tr2 := TimeRange{
|
||||
MinTimestamp: time.Date(2024, 6, 1, 0, 0, 0, 0, time.UTC).UnixMilli(),
|
||||
MaxTimestamp: time.Date(2024, 6, 30, 23, 59, 59, 999_999_999, time.UTC).UnixMilli(),
|
||||
}
|
||||
legacyData := genData(numMetrics, "legacy", tr1)
|
||||
new1Data := genData(numMetrics, "new1", tr1)
|
||||
new2Data := genData(numMetrics, "new2", tr2)
|
||||
newData := slices.Concat(new1Data, new2Data)
|
||||
|
||||
assertSearchResults := func(s *Storage, want []MetricRow) {
|
||||
assertSearchResults := func(s *Storage, tr TimeRange, want []MetricRow) {
|
||||
tfsAll := NewTagFilters()
|
||||
if err := tfsAll.Add([]byte("__name__"), []byte(".*"), false, true); err != nil {
|
||||
t.Fatalf("unexpected error in TagFilters.Add: %v", err)
|
||||
@@ -314,13 +359,13 @@ func TestLegacyStorage_Search(t *testing.T) {
|
||||
|
||||
assertLegacyData := func(s *Storage) {
|
||||
t.Helper()
|
||||
want := legacyData
|
||||
assertSearchResults(s, want)
|
||||
assertSearchResults(s, tr1, legacyData)
|
||||
}
|
||||
assertNewData := func(s *Storage) {
|
||||
t.Helper()
|
||||
want := slices.Concat(legacyData, newData)
|
||||
assertSearchResults(s, want)
|
||||
want := slices.Concat(legacyData, new1Data)
|
||||
assertSearchResults(s, tr1, want)
|
||||
assertSearchResults(s, tr2, new2Data)
|
||||
}
|
||||
testSearchOpWithLegacyIndexDBs(t, legacyData, newData, assertLegacyData, assertNewData)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user