Skip to content

fix: sum, avg, max and min over time with unwrap answer the sample at end on query_range, like Loki - #727

Merged
szibis merged 4 commits into
mainfrom
fix/unwrap-range-last-point
Oct 22, 2026
Merged

szibis merged 4 commits into
mainfrom
fix/unwrap-range-last-point

Conversation

@szibis

@szibis szibis commented Oct 12, 2026 •

Copy link
Copy Markdown
Collaborator

Summary

Gap semantics/unwrap-range-last-point. Over an hour at step 60s, sum by (level) (max_over_time({service_name="api-gateway"} | json | unwrap status | __error__="" [5m])) has 61 samples on Loki 3.7.7 (start..end inclusive, pkg/logql/range_vector.go) and 60 on the proxy. The same happens for sum_over_time, avg_over_time and min_over_time.

Cause. These functions use VictoriaLogs stats_query_range. Its bucket labelled T holds [T, T+step), and the request's start/end were passed through unchanged. So the point at end came from the bucket after end, which is empty when the data stops at end.

Fix. sum/avg/max/min_over_time with an unwrap stage now take the shifted fetch that count_over_time with range == step already uses: fetch from start−step, then relabel each bucket +step and keep [start, end]. There is no new dispatch path and no new VictoriaLogs feature (metric_binary.go, range_metric_compat.go).

  • range == step: samples and values match Loki, which also fixes that half of semantics/unwrap-over-time-range-windows.
  • range ≠ step: the end sample is present on dense data, but each value is still one step bucket rather than the (t-range, t] window. That remains the open semantics/unwrap-over-time-range-windows.

Tests

  • TestUnwrapOverTimeRangeEmitsEndSample: 3 VictoriaLogs versions × json/logfmt × 4 functions × 5 shapes; 96 subtests failed before the fix.
  • TestUnwrapOverTimeTumblingMatchesLoki: values against a Loki-semantics reference; 24 subtests failed before the fix.
  • TestStatsRateRangeEqualsStepShift_Detection: updated for the flipped cases.
  • TestCompat_UnwrapRangeEndSample (e2e vs Loki).

Rebased on main

Rebased onto main after the VictoriaLogs v1.49.0 floor (#770), the sum without fold (#739) and #582. The pre-v1.45 epoch-grid case is gone (the offset argument exists on every supported version); the emulator variants are now unknown, v1.49.0 and v1.52.0. On main the new tests fail: TestUnwrapOverTimeRangeEmitsEndSample 96 of 120 cases (the 24 that pass end between evaluation times), TestUnwrapOverTimeTumblingMatchesLoki 24 of 24, TestStatsRateRangeEqualsStepShift_Detection 7 of 33; on this branch they pass.

Two tests on main pinned the end-sample bug itself, and their answers change. Loki evaluates start..end inclusive (start=base-120, end=base, step=60: three samples); main answered two, each labelled one step early.

  • TestWithoutFoldIsLimitedToTheOperatorsItProves (query_range columns only; instant and limit columns unchanged): the old values are now one step later, plus the sample at end, for example max without (pod) x=20,12 y=24,8 → x=36,20,12 y=32,24,8 and max(sum without ...) 164,68 → 260,164,68. The sliding [5m] values at step 60 still follow the open row semantics/unwrap-over-time-range-windows.
  • TestExtractionListOutsideWithoutKeepsItsGrouping: 24 golden entries (tumbling and sliding unwrap sum, avg, min and max). The LogsQL sent to VictoriaLogs is identical in all 24; each new answer is the old one with every timestamp one step later and at most one extra sample; the tumbling [5m] cases at step 300 now match Loki exactly.

stddev_over_time and stdvar_over_time with unwrap still drop the sample at end (not covered here). Capped unit run (the proxy package in batches on this host), -race on the touched tests, vet with every tag, lint and the conformance and changelog gates pass.

Proofs in progress

  • e2e against Loki on VictoriaLogs v1.49.0 and v1.52.0 (unwrap_range_end_sample_test.go).
  • A/B at 1h/6h/24h/7d plus the control set (binary operations included), real Grafana range matrix with the fix proof, benchstat and the backend-safety load test.

Rebased onto main (2026-10-22)

Base moved from 8d57747b (v2.19.0) to 304b5549 (v2.25.1 plus #827). The PR is not stacked on #728 or #730; it is rebased on origin/main alone. Head d26f6a07, four commits, all signed, subjects unchanged.

Conflict Resolution
CHANGELOG.md (main's [Unreleased] is empty, the entry sat next to a cut section) Rebuilt from main: this PR's entry is the only content of ## [Unreleased] / ### Fixed; no released section edited.
bench/visual/spec.json (two entries appended at the same place: main's explore-unwrap-quantile-over-time from #731 and this PR's explore-unwrap-max-over-time-end-sample) Kept both entries.
conformance/registry/generated/wiring.json, conformance/reports/{gaps,parity-gaps,roadmap}.md Not hand-merged: took main's and regenerated with the repo generators (wire.py, perf_evidence.py, coverage_map.py, gaps.py, translation_map.py, roadmap.py, matrix_link.py, parity_gaps.py); folded into the "visual fix proof page ... regenerated reports" commit.
Go (metric_binary.go, range_metric_compat.go, tests) No textual conflicts; nothing on main since v2.19.0 (#731 quantile, #761, #770 floor) changes these paths.

Main since the previous rebase changed nothing this fix assumes: the golden table of TestExtractionListOutsideWithoutKeepsItsGrouping and TestWithoutFoldIsLimitedToTheOperatorsItProves still carry the 24 and the query_range columns changed by this PR, and they pass.

Gates (phase 1, no Docker, capped GOMEMLIMIT=3GiB GOMAXPROCS=4)

  • gofmt -l, go build ./..., go vet ./... and go vet ./test/e2e-compat/... and go vet -tags=e2e ./test/e2e-compat/... (the e2e files carry //go:build e2e; compile only, nothing run): clean.
  • go test -short -count=1 -p 1 ./... and the ./internal/... -json run that feeds the conformance gate: all 13 packages ok (internal/proxy 120 s; peak RSS 1.33 GB with /usr/bin/time -l; not compared with main in this phase).
  • go test -count=1 -run 'TestSlidingWindowStats_|TestOrderedJSONExtractedMetricDifferential' ./internal/proxy without -short (the tests that skip under -short and declare the registry items near this change; CI's evidence step runs without -short): ok.
  • -race on the touched tests: TestUnwrapOverTimeRangeEmitsEndSample, TestUnwrapOverTimeTumblingMatchesLoki, TestStatsRateRangeEqualsStepShift_Detection, TestWithoutFoldIsLimitedToTheOperatorsItProves, TestExtractionListOutsideWithoutKeepsItsGrouping ok.
  • python3 scripts/ci/check_conformance.py --go-results <unit json>: ok (414 tests declare 137 items, 133 with a passing run, 0 failing).
  • python3 -m unittest discover -s scripts/ci/tests -p 'test_*.py': 181 tests OK. Harness tests (bench/ab, bench/visual, bench/parity): OK.
  • python3 scripts/ci/check_changelog_pr.py --base origin/main --head HEAD: ok. go run ./cmd/configdoc -check: ok.

Overlaps. With #728: only CHANGELOG.md, bench/visual/spec.json and the generated files conflict textually; first_over_time and last_over_time are not touched by this fix. With #730: internal/proxy/extraction_list_outside_without_test.go (this PR changes the answers of 24 goldens, #730 changes the gate text in the sent LogsQL of 50) conflicts, so whichever of the two lands second regenerates that table. Merged together in a scratch tree (727+728+730), the only failing test is that golden table.

Proofs to be refreshed (phase 2, need the stack)

Supported VictoriaLogs for the e2e runs: the floor v1.49.0 and the newest v1.53.0, with the CI pin v1.52.0 (the PR text from before the floor moved named older lines). Commands run from the worktree $SCRATCH/wt-727 on the PR head; the Colima VM colima-lvp is the Docker host (DOCKER_CONTEXT=colima-lvp), and the shared e2e stack must not be running while a fresh stack is started on the same ports.

1. e2e vs Loki (one fresh stack per group and per VictoriaLogs version)

docker --context colima-lvp build -t loki-vl-proxy:e2e-pr727 .
for V in v1.49.0 v1.52.0 v1.53.0; do
  ( cd test/e2e-compat && DOCKER_CONTEXT=colima-lvp PROXY_IMAGE=loki-vl-proxy:e2e-pr727 \
      VICTORIALOGS_IMAGE=victoriametrics/victoria-logs:$V docker compose up -d --no-build \
    && ../../scripts/ci/wait_e2e_stack.sh 180 )
  # this PR's tests (they ingest their own fixtures and wait for Loki; no TestSetup needed)
  go test -v -tags=e2e -timeout=600s -count=1 -run '^(TestCompat_UnwrapRangeEndSample)$' ./test/e2e-compat/
  ( cd test/e2e-compat && DOCKER_CONTEXT=colima-lvp docker compose down -v )
done

Then the two CI groups that cover the touched code, each on its own fresh stack on v1.52.0 and v1.49.0 (same up/down lines, -run pattern copied from .github/workflows/ci.yaml):

go test -v -tags=e2e -timeout=600s -count=1 -run '^(TestSetup_IngestLogs|TestCompat_.*|TestExtended_.*|TestChaining_.*|TestAlertingCompat_.*|TestExplore_HTTPQueryRangeContracts|TestLokiFunctions_.*|TestGrafanaDatasourceCatalogAndHealth|TestProxyCompatibilitySurface|TestPinnedCompatibilityMatrixMatchesCompose)$' ./test/e2e-compat/
go test -v -tags=e2e -timeout=600s -count=1 -run '^(TestSetup_IngestLogs|TestQuerySemanticsMatrixManifest|TestQuerySemanticsOperationsInventory|TestQuerySemanticsMatrix|TestGrafanaClickout_.*|TestMissingOps_.*|TestRangeMetricCompatibility.*|TestLogQL_Exhaustive_.*|TestPipeline_.*|TestEdge_DropErrorInstantQueryReturnsAggregatedResult|TestEdge_DetectedFieldsAfterJsonDropPipelineIncludesJsonFields)$' ./test/e2e-compat/

2. A/B proof (previous release / base vs PR vs Loki, own compose project and ports)

python3 bench/ab/pr_smoke.py --base origin/main --out $SCRATCH/ab-727 --loki-mem 3g --vl-mem 4g --project ab727 --ranges 1h,6h,24h --runs 5 --refresh-s 60 --refresh-runs 5
# sets the selection names for this change: control, json-filter-pushdown, loki-profile-otel-metadata, metric-latency-gap, pattern-line-filter-anchoring; add unwrap-sum-without and unwrap-validity by hand (the unwrap shapes)
# a 7d pass and the control set explicitly (perf_matrix.py --set <set> --ranges 1h,6h,24h,7d --runs 5 --target main=... --target branch=... --target loki=... --out raw.json;
#   python3 bench/ab/report.py summarize raw.json --baseline main --candidate branch --label pr727-<set> --save bench/ab/results/)
python3 bench/ab/pr_smoke.py --same-build --out $SCRATCH/ab-727-aa --project ab727a    # noise floor

Plus go test -run '^$' -bench <touched benchmarks> -benchmem -count=6 ./internal/translator ./internal/proxy on origin/main and the head, compared with benchstat, and the backend-safety load test (many 24h/7d queries concurrently, VictoriaLogs RestartCount before and after, /labels probe answering 200).

3. Visual proof (isolated stack, base | PR | Loki)

python3 bench/visual/plan.py --base origin/main --out $SCRATCH/vs727/plan.json
python3 bench/visual/ci_run.py --base origin/main --plan $SCRATCH/vs727/plan.json --out $SCRATCH/vs727 --project vs727 --port-offset 200 --hours 24
python3 bench/visual/visual_comment.py --out $SCRATCH/vs727 --mode artifact --md $SCRATCH/vs727/comment.md

Plan: explore-unwrap-max-over-time-end-sample at 15m/1h/6h (the fix proof, fixes: semantics/unwrap-range-last-point) plus the core set (explore-logs-plain, explore-metric-plain, explore-A, explore-pattern-filter-anchored, explore-unwrap-quantile-over-time, dd-landing, dd-service-logs, dd-fields); 19 captures.

4. Real Grafana range matrix: the shapes below through the Loki-type datasources of the proxy and of Loki direct, over 5m, 15m, 1h, 6h, 24h and 7d where the data exists, compared for status, errors, series counts and totals.

Matrix shapes: sum by (level) (max_over_time({service_name="api-gateway"} | json | unwrap status | __error__="" [$__auto])) and the same with sum_over_time, avg_over_time, min_over_time, plus ... unwrap duration_ms forms; range == step and range != step.

@github-actions github-actions Bot added size/L Large change scope/proxy Proxy core scope/docs Documentation scope/tests Tests bugfix Bug fix labels Oct 12, 2026
@github-actions

github-actions Bot commented Oct 12, 2026 •

Copy link
Copy Markdown
Contributor

⚪ Performance A/B: no change beyond noise

25 shape×range — 25 ⚪ same · results vs Loki: 24 same, 0 new difference(s), 1 pre-existing

Every shape is within noise of the base build (±30% and 100 ms).

¹ re-measured with 7 runs, on windows the first pass did not use, after it moved beyond noise.

25 unchanged shape×range (within noise)
shape range base p50 PR p50 change Loki p50 PR ÷ Loki result vs Loki
⚪ bytes_over_time by app 1h 52 ms 54 ms ⚪ +4% 75 ms 0.72× ✅ same
⚪ drilldown service landing 1h 30 ms 23 ms ⚪ -23% 26 ms 0.88× ✅ same
⚪ instant json volume instant 24 ms 25 ms ⚪ +4% 80 ms 0.31× ✅ same
⚪ instant ungrouped rate instant 4 ms 4 ms ⚪ +0% 60 ms 0.07× ✅ same
⚪ json rate by level (no filter, no drop) 1h 400 400 ⚪ +0% 400 — ✅ same
⚪ json volume no filters 1h 144 ms 144 ms ⚪ +0% 51 ms 2.82× ✅ same
⚪ logs plain 1h 54 ms 59 ms ⚪ +9% 32 ms 1.84× ✅ same
⚪ logs | json 1h 78 ms 79 ms ⚪ +1% 54 ms 1.46× ✅ same
⚪ stream-label count by app 1h 24 ms 19 ms ⚪ -21% 37 ms 0.51× ✅ same
⚪ topk rate by app 1h 36 ms 35 ms ⚪ -3% 76 ms 0.46× ➖ differs (as base)
⚪ ungrouped rate 1h 9 ms 9 ms ⚪ +0% 81 ms 0.11× ✅ same
⚪ A explore volume, 2 filters, drop 1h 138 ms 127 ms ⚪ -8% 125 ms 1.02× ✅ same
⚪ D volume, no filters 1h 145 ms 144 ms ¹ ⚪ -1% 56 ms 2.57× ✅ same
⚪ I grafana volume of B 1h 83 ms 100 ms ⚪ +20% 133 ms 0.75× ✅ same
⚪ O2 explore log volume (Grafana form), underscore structured-metadata filter 1h 52 ms 56 ms ⚪ +8% 42 ms 1.33× ✅ same
⚪ DL6 explore volume, level filter before json 1h 103 ms 105 ms ⚪ +2% 48 ms 2.19× ✅ same
⚪ A1 nginx include GET, log query 1h 16 ms 18 ms ⚪ +12% 8 ms 2.25× ✅ same
⚪ A2 nginx exclude GET, log query 1h 35 ms 34 ms ⚪ -3% 10 ms 3.40× ✅ same
⚪ A3 nginx include GET, count_over_time 1h 11 ms 11 ms ⚪ +0% 6 ms 1.83× ✅ same
⚪ A4 nginx exclude GET, count_over_time 1h 14 ms 14 ms ⚪ +0% 5 ms 2.80× ✅ same
⚪ A5 drilldown exclude, volume by detected_level 1h 20 ms 20 ms ⚪ +0% 5 ms 4.00× ✅ same
⚪ A6 nginx include ends on a literal, log query 1h 11 ms 11 ms ⚪ +0% 5 ms 2.20× ✅ same
⚪ A7 nginx exclude ends on a literal, log query 1h 19 ms 22 ms ⚪ +16% 11 ms 2.00× ✅ same
⚪ A8 nginx include two literals, count_over_time 1h 19 ms 17 ms ⚪ -11% 6 ms 2.83× ✅ same
⚪ A9 nginx include two literals, ends on a literal, count_over_time 1h 16 ms 16 ms ⚪ +0% 5 ms 3.20× ✅ same
Cold (first-run) timings — what a user opening a panel sees
shape range base cold PR cold Loki cold PR ÷ Loki cold
bytes_over_time by app 1h 55 ms 51 ms 474 ms 0.11×
drilldown service landing 1h 27 ms 35 ms 483 ms 0.07×
instant json volume instant 29 ms 26 ms 80 ms 0.32×
instant ungrouped rate instant 4 ms 5 ms 61 ms 0.08×
json rate by level (no filter, no drop) 1h 400 400 400 —
json volume no filters 1h 144 ms 145 ms 63 ms † 2.30×
logs plain 1h 79 ms 57 ms 47 ms 1.21×
logs | json 1h 85 ms 86 ms 50 ms 1.72×
stream-label count by app 1h 26 ms 27 ms 400 ms 0.07×
topk rate by app 1h 36 ms 36 ms 554 ms 0.06×
ungrouped rate 1h 9 ms 9 ms 508 ms 0.02×
A explore volume, 2 filters, drop 1h 1.34 s 1.19 s 469 ms 2.54×
D volume, no filters 1h 290 ms 194 ms 52 ms † 3.73×
I grafana volume of B 1h 119 ms 121 ms 1.12 s 0.11×
O2 explore log volume (Grafana form), underscore structured-metadata filter 1h 123 ms 109 ms 587 ms 0.19×
DL6 explore volume, level filter before json 1h 138 ms 133 ms 513 ms 0.26×
A1 nginx include GET, log query 1h 24 ms 17 ms 10 ms 1.70×
A2 nginx exclude GET, log query 1h 50 ms 50 ms 9 ms 5.56×
A3 nginx include GET, count_over_time 1h 11 ms 11 ms 25 ms 0.44×
A4 nginx exclude GET, count_over_time 1h 13 ms 14 ms 32 ms 0.44×
A5 drilldown exclude, volume by detected_level 1h 30 ms 30 ms 28 ms 1.07×
A6 nginx include ends on a literal, log query 1h 17 ms 12 ms 20 ms 0.60×
A7 nginx exclude ends on a literal, log query 1h 19 ms 19 ms 10 ms 1.90×
A8 nginx include two literals, count_over_time 1h 17 ms 17 ms 25 ms 0.68×
A9 nginx include two literals, ends on a literal, count_over_time 1h 16 ms 16 ms 22 ms 0.73×

† Loki's own counters say its results cache answered this cold run: not a computed time.

Why these shapes
  • internal/proxy/range_metric_compat.go → 21: control/bytes_over_time by app, control/instant json volume, control/instant ungrouped rate, control/json volume no filters, control/stream-label count by app, control/topk rate by app, control/ungrouped rate, json-filter-pushdown/A explore volume, 2 filters, drop …
  • control smoke → 8: control/drilldown service landing, control/instant ungrouped rate, control/json rate by level (no filter, no drop), control/json volume no filters, control/logs plain, control/logs | json, control/stream-label count by app, control/topk rate by app

base ddfe13968f → PR ca067aff34 · 4 runs (first is cold), warm p50 · ranges 1h · noise ±30% and 100 ms · VictoriaLogs restarts 0→0 · 3.4 min. Same runner, one fresh stack, targets interleaved per request. How to read and reproduce: bench/ab/README.md.

@github-actions

github-actions Bot commented Oct 12, 2026 •

Copy link
Copy Markdown
Contributor

✅ Visual smoke: passed with warnings

Base ddfe13968f vs PR de6d00d661, Grafana through the proxy builds and Loki on one fresh stack; run.
Loaded again, once and more patiently, after a first-pass difference or an unsettled page: explore-unwrap-max-over-time-end-sample 15m, explore-unwrap-max-over-time-end-sample 1h, explore-unwrap-max-over-time-end-sample 6h.
Core set: 5 capture(s) at 1h. Detailed set: 5 entries (explore-unwrap-max-over-time-end-sample, explore-metric-plain, explore-A, explore-pattern-filter-anchored, explore-unwrap-quantile-over-time). 19 capture(s), 15m/1h/6h, 24h and 7d stay out of PR runs.

Fix proof

Captures of the exact cases this pull request adds or fixes (registry case, base | PR | Loki). The verdict compares the PR with Loki where the base did not match. The gate fails a case unless one capture is fixed or improved, or, beyond the Loki data window, the base failed where Loki and the PR both answered with data (the label does not excuse it; only visual: none on the case does).

semantics/unwrap-range-last-point: 🟡 improved

page range base = PR (data) vs Loki (PR) verdict
explore-unwrap-max-over-time-end-sample 15m differs (1) 1 difference(s), 1 on base too 🟡 improved
explore-unwrap-max-over-time-end-sample 1h differs (1) 1 difference(s), 1 on base too 🟡 improved
explore-unwrap-max-over-time-end-sample 6h differs (1) n/a (beyond the Loki window) ⚪ undecided
explore-unwrap-max-over-time-end-sample-15m: improved

explore-unwrap-max-over-time-end-sample-15m

explore-unwrap-max-over-time-end-sample-1h: improved

explore-unwrap-max-over-time-end-sample-1h

explore-unwrap-max-over-time-end-sample-6h: undecided

explore-unwrap-max-over-time-end-sample-6h

Regression check

page range set base = PR (data) vs Loki (PR) pixel diff result
dd-fields 1h core ✅ identical identical (4 explained, 1 history-dependent) 0.11% ✅
dd-landing 1h core ✅ identical identical (3 explained) 0.14% ✅
dd-service-logs 1h core ✅ identical identical (3 explained, 1 history-dependent) 0.11% ✅
explore-logs-plain 1h core ✅ identical 1 difference(s), 1 on base too 0.07% ✅
explore-metric-plain 1h core ✅ identical 1 difference(s), 1 on base too 0.04% ✅
explore-A 15m detailed ✅ identical 1 difference(s), 1 on base too 0.04% ✅
explore-A 1h detailed ✅ identical 1 difference(s), 1 on base too 0.04% ✅
explore-A 6h detailed ✅ identical n/a (beyond the Loki window) 0.04% ✅
explore-metric-plain 15m detailed ✅ identical 1 difference(s), 1 on base too 0.04% ✅
explore-metric-plain 6h detailed ✅ identical n/a (beyond the Loki window) 0.04% ✅
explore-pattern-filter-anchored 15m detailed ✅ identical 1 difference(s), 1 on base too 0.07% ✅
explore-pattern-filter-anchored 1h detailed ✅ identical 1 difference(s), 1 on base too 0.07% ✅
explore-pattern-filter-anchored 6h detailed ✅ identical n/a (beyond the Loki window) 0.07% ✅
explore-unwrap-max-over-time-end-sample 15m detailed differs (1): query ('max by (level) (max_over_time({service_name="api-gat 1 difference(s), 1 on base too 0.28% ✅ improved (closer to Loki)
explore-unwrap-max-over-time-end-sample 1h detailed differs (1): query ('max by (level) (max_over_time({service_name="api-gat 1 difference(s), 1 on base too 0.12% ✅ improved (closer to Loki)
explore-unwrap-max-over-time-end-sample 6h detailed differs (1): query ('max by (level) (max_over_time({service_name="api-gat n/a (beyond the Loki window) 0.06% ✅ improved (closer to Loki)
explore-unwrap-quantile-over-time 15m detailed ✅ identical 1 difference(s), 1 on base too 0.04% ✅
explore-unwrap-quantile-over-time 1h detailed ✅ identical 1 difference(s), 1 on base too 0.04% ✅
explore-unwrap-quantile-over-time 6h detailed ✅ identical n/a (beyond the Loki window) 0.04% ✅

Gate: a base-vs-PR data difference passes when the PR is closer to Loki, and fails when the PR diverges from Loki or Loki cannot decide it (at a range Loki does not hold, a difference passes when the same page proved it closer to Loki at a shorter range; otherwise label the pull request visual-change-expected to accept an intended change). Also failing: a panel empty on the PR but not on the base, an error banner, panel error, error answer or new "No data" panel on the PR, a PR side that never settled, a difference that did not reproduce on the recapture. Pixel differences only warn.

explore-unwrap-max-over-time-end-sample-6h: no Loki data at this range; the same differences match Loki at a shorter range (1): query ('max by (level) (max_over_tim
  • no Loki data at this range; the same differences match Loki at a shorter range (1): query ('max by (level) (max_over_time({service_name="api-gateway"} | json | unwrap status | __er: {"level": "error"}: timestamps differ (1080 vs 1081 points)

explore-unwrap-max-over-time-end-sample-6h

Core set montages (5): base | PR | Loki

dd-fields-1h

dd-fields-1h

dd-landing-1h

dd-landing-1h

dd-service-logs-1h

dd-service-logs-1h

explore-logs-plain-1h

explore-logs-plain-1h

explore-metric-plain-1h

explore-metric-plain-1h

All montages of this run: pr-visuals/pr-727.

@github-actions

github-actions Bot commented Oct 12, 2026 •

Copy link
Copy Markdown
Contributor

PR Quality Report

Compared against base branch main.

Coverage and tests

Signal Base PR Delta
Test count 12064 12218 154
Coverage 88.5% 88.4% -0.1% (stable)

Compatibility

Track Base PR Delta
Loki API 100.0% 11/11 (100.0%) 0.0% (stable)
Logs Drilldown 100.0% 17/17 (100.0%) 0.0% (stable)
VictoriaLogs 100.0% 11/11 (100.0%) 0.0% (stable)

Performance smoke

Lower CPU cost (ns/op) is better. Lower benchmark memory cost (B/op, allocs/op) is better. Higher throughput is better. Lower load-test memory growth is better. Benchmark rows are medians from repeated samples.

Signal Base PR Delta
QueryRange cache-hit CPU cost 3454.0 ns/op 3485.0 ns/op +0.9% (stable)
QueryRange cache-hit memory 1240.0 B/op 1240.0 B/op 0.0% (stable)
QueryRange cache-hit allocations 27.0 allocs/op 27.0 allocs/op 0.0% (stable)
QueryRange cache-bypass CPU cost 4122.0 ns/op 4076.0 ns/op -1.1% (stable)
QueryRange cache-bypass memory 1305.0 B/op 1303.0 B/op -0.2% (stable)
QueryRange cache-bypass allocations 27.0 allocs/op 27.0 allocs/op 0.0% (stable)
Labels cache-hit CPU cost 918.6 ns/op 911.6 ns/op -0.8% (stable)
Labels cache-hit memory 48.0 B/op 48.0 B/op 0.0% (stable)
Labels cache-hit allocations 3.0 allocs/op 3.0 allocs/op 0.0% (stable)
Labels cache-bypass CPU cost 1533.0 ns/op 1506.0 ns/op -1.8% (stable)
Labels cache-bypass memory 400.0 B/op 400.0 B/op 0.0% (stable)
Labels cache-bypass allocations 14.0 allocs/op 14.0 allocs/op 0.0% (stable)

State

  • Coverage, compatibility, and sampled performance are reported here from the same PR workflow.
  • This is a delta report, not a release gate by itself. Required checks still decide merge safety.
  • Performance is a smoke comparison, not a full benchmark lab run.
  • Delta states use the same noise guards as the quality gate (percent + absolute + low-baseline checks), so report labels match merge-gate behavior.

@github-actions github-actions Bot added size/XL Extra large change and removed size/L Large change labels Oct 12, 2026
@szibis
szibis force-pushed the fix/unwrap-range-last-point branch from 1a34147 to b8f4962 Compare October 12, 2026 11:01
@github-actions github-actions Bot added size/XL Extra large change and removed size/XL Extra large change labels Oct 12, 2026
@github-actions github-actions Bot added size/XL Extra large change and removed size/XL Extra large change labels Oct 12, 2026
@szibis
szibis force-pushed the fix/unwrap-range-last-point branch from fa407ac to 810cc10 Compare October 19, 2026 10:26
@szibis
szibis marked this pull request as ready for review October 19, 2026 10:26
@github-actions github-actions Bot added size/XL Extra large change and removed size/XL Extra large change labels Oct 19, 2026
@szibis
szibis force-pushed the fix/unwrap-range-last-point branch from 810cc10 to d26f6a0 Compare October 22, 2026 14:25
@github-actions github-actions Bot removed the size/XL Extra large change label Oct 22, 2026
@github-actions github-actions Bot added the size/XL Extra large change label Oct 22, 2026
@szibis
szibis force-pushed the fix/unwrap-range-last-point branch from d26f6a0 to f6f6e67 Compare October 22, 2026 18:25
@github-actions github-actions Bot added size/XL Extra large change and removed size/XL Extra large change labels Oct 22, 2026
… end on query_range, like Loki

Loki evaluates a range query at start, start+step, ... up to and including end, each over (t-range, t]. These functions were read from VictoriaLogs' step buckets as labelled, so the point at end was the bucket after the last line and was missing while the data stops at end. They are now fetched from start-step on anchored step buckets and relabelled onto the evaluation time each closes, as rate and count_over_time over a range equal to the step already are. For a range equal to the step the values are Loki's window; a longer or shorter range keeps the step-sized bucket value.
@szibis
szibis force-pushed the fix/unwrap-range-last-point branch from f6f6e67 to de6d00d Compare October 22, 2026 18:43
@github-actions github-actions Bot added size/XL Extra large change and removed size/XL Extra large change labels Oct 22, 2026
@szibis
szibis merged commit 1c79dd3 into main Oct 22, 2026
74 checks passed
@szibis
szibis deleted the fix/unwrap-range-last-point branch October 22, 2026 19:37
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bugfix Bug fix scope/docs Documentation scope/proxy Proxy core scope/tests Tests size/XL Extra large change

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant