mirror of
https://github.com/VictoriaMetrics/VictoriaMetrics.git
synced 2026-05-17 00:26:36 +03:00
lib/storage: include last sample when query at the last millisecond of the day
One millisecond shouldn't be subtracted from the `tr.MaxTimestamp`, and related test cases will be added Fixes https://github.com/VictoriaMetrics/VictoriaMetrics/issues/9804
This commit is contained in:
@@ -53,6 +53,7 @@ func testSpecialQueryRegression(tc *apptest.TestCase, sut apptest.PrometheusWrit
|
||||
testMatchSeries(tc, sut)
|
||||
testNegativeIncrease(tc, sut)
|
||||
testInstantQueryWithOffsetUsingCache(tc, sut)
|
||||
testQueryRangeEndAtFirstMillisecondOfDate(tc, sut)
|
||||
|
||||
// graphite
|
||||
testComparisonNotInfNotNan(tc, sut)
|
||||
@@ -334,6 +335,48 @@ func testInstantQueryWithOffsetUsingCache(tc *apptest.TestCase, sut apptest.Prom
|
||||
})
|
||||
}
|
||||
|
||||
func testQueryRangeEndAtFirstMillisecondOfDate(tc *apptest.TestCase, sut apptest.PrometheusWriteQuerier) {
|
||||
t := tc.T()
|
||||
|
||||
// unexpected /api/v1/query_range response
|
||||
// when the sample is at the last millisecond of a day, e.g. `2025-12-12 00:00:00`
|
||||
// query_range with `End` at the last millisecond of that day may cause the time point to be missed.
|
||||
// see https://github.com/VictoriaMetrics/VictoriaMetrics/issues/9804
|
||||
|
||||
// `End` should be inclusive according to https://prometheus.io/docs/prometheus/latest/querying/api/#range-queries
|
||||
|
||||
sut.PrometheusAPIV1ImportPrometheus(t, []string{
|
||||
`foo_bar 7 1765497600000`, // 2025-12-12 00:00:00
|
||||
}, apptest.QueryOpts{})
|
||||
sut.ForceFlush(t)
|
||||
|
||||
tc.Assert(&apptest.AssertOptions{
|
||||
Msg: "unexpected /api/v1/query response",
|
||||
DoNotRetry: true,
|
||||
Got: func() any {
|
||||
return sut.PrometheusAPIV1QueryRange(t, `foo_bar`, apptest.QueryOpts{
|
||||
Start: "2025-12-11T20:00:00.000Z",
|
||||
End: "2025-12-12T00:00:00.000Z",
|
||||
Step: "1h",
|
||||
})
|
||||
},
|
||||
Want: &apptest.PrometheusAPIV1QueryResponse{
|
||||
Status: "success",
|
||||
Data: &apptest.QueryData{
|
||||
ResultType: "matrix",
|
||||
Result: []*apptest.QueryResult{
|
||||
{
|
||||
Metric: map[string]string{"__name__": "foo_bar"},
|
||||
Samples: []*apptest.Sample{
|
||||
{Timestamp: 1765497600000, Value: 7},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
func testComparisonNotInfNotNan(tc *apptest.TestCase, sut apptest.PrometheusWriteQuerier) {
|
||||
t := tc.T()
|
||||
|
||||
|
||||
@@ -50,6 +50,7 @@ See also [LTS releases](https://docs.victoriametrics.com/victoriametrics/lts-rel
|
||||
* BUGFIX: [vmsingle](https://docs.victoriametrics.com/victoriametrics/single-server-victoriametrics/) and `vmstorage` in [VictoriaMetrics cluster](https://docs.victoriametrics.com/victoriametrics/cluster-victoriametrics/): `dateMetricIDCache` metrics were renamed to follow the naming pattern used for other caches. `vm_date_metric_id_cache_resets_total` becomes `vm_cache_resets_total{type="indexdb/date_metricID"}` and `vm_date_metric_id_cache_syncs_total` became `vm_cache_syncs_total{type="indexdb/date_metricID"}`. See PR [#10152](https://github.com/VictoriaMetrics/VictoriaMetrics/pull/10152) for details.
|
||||
* BUGFIX: [vmsingle](https://docs.victoriametrics.com/victoriametrics/single-server-victoriametrics/) and `vmstorage` in [VictoriaMetrics cluster](https://docs.victoriametrics.com/victoriametrics/cluster-victoriametrics/): fix performance degradation caused by redundant indexdb lookups at the start of each hour. See this issue [#10114](https://github.com/VictoriaMetrics/VictoriaMetrics/issues/10114) for details.
|
||||
* BUGFIX: [vmauth](https://docs.victoriametrics.com/victoriametrics/vmauth/): verify backend network reachability with a TCP dial before marking it healthy. Previously, backends were auto-restored after `-failTimeout` even if the network was still unreachable, causing requests to hang repeatedly. `vmauth` now performs a 1s TCP dial check before returning a backend to the healthy pool. See [#9997](https://github.com/VictoriaMetrics/VictoriaMetrics/issues/9997).
|
||||
* BUGFIX: [vmsingle](https://docs.victoriametrics.com/victoriametrics/single-server-victoriametrics/) and `vmstorage` in [VictoriaMetrics cluster](https://docs.victoriametrics.com/victoriametrics/cluster-victoriametrics/): fix potential datapoint lost in response when query at the last millisecond of the day. See issue [#9804](https://github.com/VictoriaMetrics/VictoriaMetrics/issues/9804) for details.
|
||||
|
||||
## [v1.131.0](https://github.com/VictoriaMetrics/VictoriaMetrics/releases/tag/v1.131.0)
|
||||
|
||||
|
||||
@@ -3183,7 +3183,7 @@ func TestStorageAdjustTimeRange(t *testing.T) {
|
||||
// Time range is smaller than 40 days. When the -disablePerDayIndex flag is
|
||||
// unset, the time range will not be adjusted. When the flag is set, the
|
||||
// adjusted time range will be globalIndexTimeRange.
|
||||
tr = TimeRange{10 * msecPerDay, 50 * msecPerDay}
|
||||
tr = TimeRange{10 * msecPerDay, 50*msecPerDay - 1}
|
||||
f(false, tr, tr)
|
||||
f(true, tr, globalIndexTimeRange)
|
||||
|
||||
@@ -3202,7 +3202,7 @@ func TestStorageAdjustTimeRange(t *testing.T) {
|
||||
// When the -disablePerDayIndex flag is unset, the time range will not be
|
||||
// adjusted. When the flag is set, the adjusted time range will be
|
||||
// globalIndexTimeRange.
|
||||
tr = TimeRange{10 * msecPerDay, 51 * msecPerDay}
|
||||
tr = TimeRange{10 * msecPerDay, 50 * msecPerDay}
|
||||
f(false, tr, tr)
|
||||
f(true, tr, globalIndexTimeRange)
|
||||
|
||||
|
||||
@@ -43,10 +43,9 @@ var (
|
||||
// DateRange returns the date range for the given time range.
|
||||
func (tr *TimeRange) DateRange() (uint64, uint64) {
|
||||
minDate := uint64(tr.MinTimestamp) / msecPerDay
|
||||
// Max timestamp may point to the first millisecond of the next day. As the
|
||||
// result, the returned date range will cover one more day than needed.
|
||||
// Decrementing by 1 removes this extra day.
|
||||
maxDate := uint64(tr.MaxTimestamp-1) / msecPerDay
|
||||
// Sample at Max timestamp should be included because `End` is inclusive.
|
||||
// According to https://prometheus.io/docs/prometheus/latest/querying/api/#range-queries
|
||||
maxDate := uint64(tr.MaxTimestamp) / msecPerDay
|
||||
|
||||
// However, if both timestamps are the same and point to the beginning of
|
||||
// the day, then maxDate will be smaller that the minDate. In this case
|
||||
|
||||
@@ -138,6 +138,16 @@ func TestTimeRangeDateRange(t *testing.T) {
|
||||
// the same as min date.
|
||||
tr = TimeRange{2*msecPerDay + 654, 1*msecPerDay + 321}
|
||||
f(tr, 2, 2)
|
||||
|
||||
// MaxTimestamp is the last millisecond of the day.
|
||||
// Max date should be the next date
|
||||
tr = TimeRange{1*msecPerDay + 123, 2 * msecPerDay}
|
||||
f(tr, 1, 2)
|
||||
|
||||
// MaxTimestamp is the first millisecond of the day.
|
||||
// Max date should be the next date
|
||||
tr = TimeRange{1*msecPerDay + 123, 2*msecPerDay + 1}
|
||||
f(tr, 1, 2)
|
||||
}
|
||||
|
||||
func TestDateToString(t *testing.T) {
|
||||
|
||||
Reference in New Issue
Block a user