- Fix copy-paste bug: smoothed branch in bare MatrixSelector eval now
says "smoothed modifier is not supported with histograms" instead of
"anchored".
- Change annosFromInterpolationError to take *annotations.Annotations,
consistent with all other histogram helper functions.
- Rename delta to result in interpolateHistograms to avoid the misleading
name (the variable holds the interpolated result, not a delta).
- Fix extendedRate doc comment: interpolates at boundaries, not
extrapolates.
- Fix stale comment in correctForCounterResetsHistogram that referenced
the nonexistent variable leftInterpolationHandledReset.
- Add comment explaining why right.Copy() is not redundant in
extendedHistogramRate.
- Hoist s.Labels().Get(labels.MetricName) out of the per-step loop in
smoothSeries; was called up to three times per step.
- Reset CounterResetHint to UnknownCounterReset on carry-forward
histograms in smoothSeries; a Reset hint at a new timestamp is
semantically misleading.
- Add TestInterpolateHistograms unit test covering exact-match, midpoint,
counter, reset, and quarter-point cases.
- Add rate(hist_counter[1m] anchored) test.
- Add delta(hist_counter[1m] anchored/smoothed) tests with
NativeHistogramNotGaugeWarning assertions.
- Add carry-forward test for smoothed vector selector.
- Add range eval test for rate(hist_counter[1m] smoothed).
- Add right-boundary reset interpolation test (right_boundary_reset).
- Fix stale test comment about "prev initialPrev path".
Signed-off-by: Julien Pivotto <291750+roidelapluie@users.noreply.github.com>
Implement least(a, b) and greatest(a, b) as scalar-returning PromQL
functions backed by math.Min and math.Max respectively.
Signed-off-by: Julien Pivotto <291750+roidelapluie@users.noreply.github.com>
The previous split required callers to compute the inner slice before
calling correctForCounterResetsHistogram, which led to a bug where
h[lastSampleIndex] could be double-counted when it carries a reset hint
that equals the right boundary value.
Merge the boundary logic into correctForCounterResetsHistogram so the
function owns its own loop range, always excludes lastSampleIndex from
the inner loop, and initialises prev to h[firstSampleIndex+1] when the
left-boundary interpolation already spanned the first reset.
Add regression tests covering: reset at the last sample, two-sample
anchored windows, double-reset in smoothed mode, and the two-sample
smoothed window where both boundaries are interpolated from the same
reset segment.
Signed-off-by: Julien Pivotto <291750+roidelapluie@users.noreply.github.com>
start(), end(), range(), and step() are folded into NumberLiteral nodes
by foldQueryContextFunctions during preprocessing and never reach the
evaluator. Use nil with a comment pointing to foldQueryContextFunctions,
consistent with the pattern used for label_join and label_replace.
Signed-off-by: Julien Pivotto <291750+roidelapluie@users.noreply.github.com>
Rename the `min()` and `max()` duration expression functions to
`least()` and `greatest()` to avoid conflicts with the existing
PromQL aggregate functions `min` and `max`.
Update documentation and tests accordingly.
Signed-off-by: Julien Pivotto <291750+roidelapluie@users.noreply.github.com>
min(), max(), step(), and range() in duration expression context were
not guarded by the ExperimentalDurationExpr feature flag, unlike the
binary operators (+, -, *, /, %, ^). Add the missing
experimentalDurationExpr() calls in both offset_duration_expr and
duration_expr grammar rules.
Signed-off-by: Julien Pivotto <291750+roidelapluie@users.noreply.github.com>
Add native histogram support for the smoothed and anchored rate
modifiers (rate, increase, delta). Previously these modifiers only
worked with float samples and errored on native histograms.
The implementation adds histogram interpolation helpers that mirror
the float versions, and a dedicated extendedHistogramRate() function
parallel to extendedRate(). The smoothSeries() function for smoothed
vector selectors now also handles histogram interpolation.
Signed-off-by: Julien Pivotto <291750+roidelapluie@users.noreply.github.com>
Without Schema being propagated in HistogramStatsIterator, histograms
served through the stats-only path (e.g. histogram_count(rate(...)))
all appear as Schema=0, causing the exponential/custom-bucket mismatch
detection to be silently skipped.
Add a test that exercises histogram_count(rate()) over a series with
mixed exponential and custom bucket schemas to verify the warning is
emitted.
Signed-off-by: Julien Pivotto <291750+roidelapluie@users.noreply.github.com>
calculateDuration converts a float64 seconds value into a time.Duration
nanoseconds value via "time.Duration(duration*1000) * time.Millisecond".
Two related issues let invalid input slip through:
1. The bounds check used "duration > 1<<63-1 || duration < -1<<63",
comparing a value-in-seconds against the int64 nanosecond range. The
safe input range is +/- math.MaxInt64 / 1e9 seconds (about 292 years),
roughly 1e9 times tighter. Arithmetic on legal duration literals
(e.g. constructed via MUL/POW operators in DurationExpr) could
produce a finite value that passed the check but overflowed during
the final time.Duration conversion, yielding an
implementation-defined int64 silently flowing into selector Range,
OriginalOffset, and Step.
2. NaN compares false against everything, so a NaN duration produced
by math.Pow(-1, 0.5) (and similar) bypassed both the negative-value
check and the magnitude check, again producing an
implementation-defined int64 in the conversion.
Reject NaN and +/-Inf up front, and align the magnitude bound with the
parser's offset_duration_expr rule (1<<63 / 1e9), which already had the
correct unit. Add regression tests covering each new failure mode and
a happy-path case just below the new bound.
```release-notes
[BUGFIX] PromQL: Reject NaN, infinite, and out-of-range duration expressions instead of silently producing an out-of-range time.Duration.
```
Signed-off-by: alexmchughdev <alexanderedwardmchugh@gmail.com>
Fixed a bug in the `PositionRange` method where a panic occurred when `e.RHS` was nil.
Previously, the code checked `if e.RHS == nil` but then immediately
accessed `e.RHS.PositionRange().End`, causing a runtime error.
This commit updates the logic to correctly use `e.LHS.PositionRange().End`
when the RHS is missing.
Fixes: ee7d5158a ("Add step(), min(a,b) and max(a,b) in promql duration expressions")
Found by PostgresPro with the Svace static analyzer.
Signed-off-by: Maksim Korotkov <m.korotkov@postgrespro.ru>
Replace the hardcoded switch over start characters and keyword names with
a map-driven approach. durationKeywordTokens maps lowercase keyword strings
to their token types, and isDurationKeywordStartChar derives the valid start
characters from that map, so adding a new duration keyword only requires one
change instead of three.
Signed-off-by: Julien Pivotto <291750+roidelapluie@users.noreply.github.com>
smoothSeries() was stamping output points at offset-adjusted timestamps
instead of evaluator timestamps. When the @ modifier is used, this
causes gatherVector() to miss the points because it matches by exact
timestamp equality against evaluator step timestamps.
Fix by iterating over evaluator timestamps and deriving data timestamps
by subtracting the offset, so output points align with what
gatherVector() expects.
Signed-off-by: Julien Pivotto <291750+roidelapluie@users.noreply.github.com>
For smoothed rate/increase, a result should only be returned
when there is data available to interpolate across the range. If the
range has a single data point only on one side, the result is
meaningless and should be empty.
The "data only before" case was already handled: if the last fetched
sample is at or before rangeStart, extendedRate returns nothing.
Add the symmetric guard for the "data only after" case: if the first
fetched sample is strictly after rangeEnd, return nothing as well.
This mirrors the behaviour described in prometheus/prometheus#18295,
where a smoothed rate that has no data before the range should not
return zero.
Signed-off-by: Julien Pivotto <291750+roidelapluie@users.noreply.github.com>
* promql: add test for info() with non-matching labels and empty-string data matcher
This adds a test case for info() where identifying labels don't match
any info series, but the data label matcher accepts empty strings
({data=~".*"}). In this case, the base series should be returned
unchanged, since the matcher doesn't require info series data to be
present.
This complements the existing test with {non_existent=~".+"}, which
drops the series because .+ doesn't match the empty string.
Signed-off-by: Arve Knudsen <arve.knudsen@gmail.com>
* promql: remove stale XXX comment and add info() empty-matcher test
Remove the outdated XXX comment about vector selectors requiring at
least one non-empty matcher, since the info function's second argument
now bypasses this check via BypassEmptyMatcherCheck.
Add a test case for info(metric, {non_existent=~".*"}) to verify that
a data matcher accepting empty labels on its own returns the metric
unchanged when the requested label doesn't exist on the info series.
Signed-off-by: Arve Knudsen <arve.knudsen@gmail.com>
* promql: add test for info() with non-matching identifying labels and non-empty data matcher
Add a test case for info(metric_not_matching_target_info, {data=~".+"})
to verify that the series is dropped when identifying labels don't match
any info series and the data matcher doesn't accept empty strings.
Signed-off-by: Arve Knudsen <arve.knudsen@gmail.com>
---------
Signed-off-by: Arve Knudsen <arve.knudsen@gmail.com>
Export parser.Keywords() and add GetDictForFuzzParseExpr() so that
the corpus generator can produce a stable fuzzParseExpr.dict file
derived directly from the PromQL grammar rather than maintained by hand.
Signed-off-by: Julien Pivotto <291750+roidelapluie@users.noreply.github.com>
* promqltest: use AppenderV2 in load command
Switch the PromQL test framework's load command from storage.Appender
to storage.AppenderV2 in appendSample, appendCustomHistogram and
appendTill. ST is set to 0 (unknown) for now; a follow-up will add
per-sample ST specification in load statements.
Signed-off-by: György Krajcsovits <gyorgy.krajcsovits@grafana.com>
Coded with Claude Sonnet 4.6.
Signed-off-by: György Krajcsovits <gyorgy.krajcsovits@grafana.com>
* promqltest: fix unchecked Rollback error
Signed-off-by: György Krajcsovits <gyorgy.krajcsovits@grafana.com>
Coded with Claude Sonnet 4.6.
Signed-off-by: György Krajcsovits <gyorgy.krajcsovits@grafana.com>
* promqltest: support start timestamp (ST) per sample in load command
Add @st annotation lines in the load section of PromQL test files to
specify a start timestamp offset for each sample. The @st line must
immediately precede the corresponding sample line. The metric selector
is the same as the sample line, followed by @st and a space, then an
ST sequence.
ST offset items use Prometheus duration syntax (e.g. -1m, 30s) and
support the same repetition shorthand as value sequences:
_ – omit ST for this position (ST=0 in AppenderV2)
_xN – N omitted positions
<dur> – one position with the given offset
<dur>xN – N+1 positions all with the same offset
<dur>+<dur>xN – N+1 positions, offset increasing by step each position
<dur>-<dur>xN – N+1 positions, offset decreasing by step each position
The absolute ST stored in each sample is:
sample_timestamp_ms + offset_ms
The count of ST values must exactly match the count of sample values.
No @st line means ST=0 for all samples (backward compatible).
Coded with Claude Sonnet 4.6.
Signed-off-by: György Krajcsovits <gyorgy.krajcsovits@grafana.com>
* promqltest: use labels.Equal for @st metric match check
Using hash comparison risks false positives on hash collisions.
Compare metrics directly with labels.Equal instead.
Coded with Claude Sonnet 4.6.
Signed-off-by: György Krajcsovits <gyorgy.krajcsovits@grafana.com>
* promqltest: add storage roundtrip test for @st lines
Verify that start timestamps written via the @st load syntax are
actually persisted in TSDB and can be read back through the chunkenc
Iterator.AtST method. Requires both EnableSTStorage (WAL encoding) and
EnableXOR2Encoding (XOR2 chunk format) to be enabled.
Coded with Claude Sonnet 4.6.
Signed-off-by: György Krajcsovits <gyorgy.krajcsovits@grafana.com>
* promqltest: enable ST storage and XOR2 encoding for built-in tests
Enable both EnableSTStorage and EnableXOR2Encoding in the default test
storage used by RunBuiltinTests and RunTest. This ensures the *.test
testdata files run against a storage that can persist and retrieve start
timestamps, matching real Prometheus deployment behaviour.
Coded with Claude Sonnet 4.6.
Signed-off-by: György Krajcsovits <gyorgy.krajcsovits@grafana.com>
* promqltest: use newTestStorage in ST roundtrip test
Reuse newTestStorage instead of constructing a separate teststorage
instance with explicit options. This keeps the roundtrip test consistent
with the rest of the test suite and removes redundant imports.
Coded with Claude Sonnet 4.6.
Signed-off-by: György Krajcsovits <gyorgy.krajcsovits@grafana.com>
* promqltest: scope ST/XOR2 storage options to package-internal tests
newTestStorage was enabling ST storage and XOR2 encoding globally,
which broke unrelated tests (e.g. TestStreamReadEndpoint) in other
packages that call RunBuiltinTests.
Instead, keep newTestStorage as a simple teststorage.New wrapper and
introduce a testStorageOptions package variable. An init() in the
internal test file sets it to enable ST and XOR2, so the options only
apply when the promqltest package itself is under test.
Coded with Claude Sonnet 4.6.
Signed-off-by: György Krajcsovits <gyorgy.krajcsovits@grafana.com>
* apply review comments
Signed-off-by: György Krajcsovits <gyorgy.krajcsovits@grafana.com>
---------
Signed-off-by: György Krajcsovits <gyorgy.krajcsovits@grafana.com>
Signed-off-by: George Krajcsovits <krajorama@users.noreply.github.com>
When last_over_time or first_over_time is applied to a subquery that
contains functions like abs(), round(), etc., the DropName flag should
be preserved. Previously, the flag was unconditionally overwritten based
solely on the function name, ignoring the input series state.
This fix checks if the input series (from a subquery) already has
DropName=true and respects that flag by using OR logic.
Before this fix:
last_over_time(abs(metric)[10m:]) incorrectly returned {__name__="metric", ...}
After this fix:
last_over_time(abs(metric)[10m:]) correctly returns {...} without __name__
The same behavior applies to first_over_time().
Fixes#18397
---------
Signed-off-by: Vamsi Mathala <vmathala@redhat.com>
* promql: add test for info() with data label matcher when info series goes stale
When info() is called with a data label matcher that doesn't match
the empty string (e.g. {data=~".+"}), samples at timestamps where
no info series is available should be dropped rather than falling
back to the original un-enriched series.
This case was missing from the test suite.
* docs: document info() behavior when info series is unavailable
Document that when no matching info series exists at a timestamp,
data label matchers that don't match the empty string cause the
sample to be dropped, while empty-matching matchers or no selector
return the series unenriched.
* promql: add test cases for info() fallback when info series goes stale
Add test cases for info(metric, {data=~".*"}) and info(metric) to
complement the existing info(metric, {data=~".+"}) test case, making
the behavioral contrast explicit: empty-matching matchers and no
selector fall back to the unenriched series, while non-empty-matching
matchers drop the sample.
---------
Signed-off-by: Arve Knudsen <arve.knudsen@gmail.com>
Add test cases for two edge cases in the info() function:
- Enrichment when inner series are missing one identifying label
- Conflicting labels across different info metrics should error
Signed-off-by: Arve Knudsen <arve.knudsen@gmail.com>
* promqltest: use AppenderV2 in load command
Switch the PromQL test framework's load command from storage.Appender
to storage.AppenderV2 in appendSample, appendCustomHistogram and
appendTill. ST is set to 0 (unknown) for now; a follow-up will add
per-sample ST specification in load statements.
Signed-off-by: György Krajcsovits <gyorgy.krajcsovits@grafana.com>
Coded with Claude Sonnet 4.6.
Signed-off-by: György Krajcsovits <gyorgy.krajcsovits@grafana.com>
* promqltest: fix unchecked Rollback error
Signed-off-by: György Krajcsovits <gyorgy.krajcsovits@grafana.com>
Coded with Claude Sonnet 4.6.
Signed-off-by: György Krajcsovits <gyorgy.krajcsovits@grafana.com>
---------
Signed-off-by: György Krajcsovits <gyorgy.krajcsovits@grafana.com>