Skip to content

feat(offset): implement LogQL offset directive — shift eval window for range and instant queries#357

Merged
szibis merged 9 commits into
mainfrom
feature/offset-directive
May 13, 2026
Merged

feat(offset): implement LogQL offset directive — shift eval window for range and instant queries#357
szibis merged 9 commits into
mainfrom
feature/offset-directive

Conversation

@szibis
Copy link
Copy Markdown
Collaborator

@szibis szibis commented May 13, 2026

Summary

  • Implements the offset directive gap tracked in KNOWN_ISSUES.md: queries like rate({app="nginx"}[5m] offset 1h) previously silently stripped the offset; they now correctly shift the evaluation window
  • Adds extractLogQLOffset() to parse and strip the offset clause from LogQL; multiple distinct offsets in the same query return HTTP 400
  • handleQueryRange shifts start/end backward by the offset duration before dispatching to VictoriaLogs; handleQuery shifts time (defaulting to now when omitted)
  • Offset extraction runs before preferWorkingParser so the parser probe targets the shifted historical window

Test Plan

  • go test ./internal/proxy/... -run 'Offset|offset' -v — 18 offset unit + integration tests pass
  • go test ./... — 2518 tests, no regressions
  • Manual: query with offset 1h returns data from 1 hour ago (not current window)
  • Manual: query with two different offsets (offset 1h + offset 2h) returns HTTP 400
  • Manual: instant query (/loki/api/v1/query) with offset 30m and no time param shifts correctly to now-30m

@github-actions github-actions Bot added size/XL Extra large change scope/translator LogQL translator scope/proxy Proxy core scope/docs Documentation scope/tests Tests feature New feature labels May 13, 2026
@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented May 13, 2026

PR Quality Report

Compared against base branch main.

Coverage and tests

Signal Base PR Delta
Test count 2507 2524 17
Coverage 87.2% 87.2% 0.0% (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 1778.0 ns/op 1770.0 ns/op -0.4% (stable)
QueryRange cache-hit memory 200.0 B/op 200.0 B/op 0.0% (stable)
QueryRange cache-hit allocations 7.0 allocs/op 7.0 allocs/op 0.0% (stable)
QueryRange cache-bypass CPU cost 2021.0 ns/op 2024.0 ns/op +0.1% (stable)
QueryRange cache-bypass memory 286.0 B/op 285.0 B/op -0.3% (stable)
QueryRange cache-bypass allocations 7.0 allocs/op 7.0 allocs/op 0.0% (stable)
Labels cache-hit CPU cost 685.0 ns/op 685.5 ns/op +0.1% (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 825.9 ns/op 811.5 ns/op -1.7% (stable)
Labels cache-bypass memory 53.0 B/op 53.0 B/op 0.0% (stable)
Labels cache-bypass allocations 3.0 allocs/op 3.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.

szibis added 9 commits May 13, 2026 22:01
…lause

Adds logqlOffsetRE and extractLogQLOffset() to query_translation.go.
The function finds "] offset <dur>" clauses, strips all occurrences,
and returns the parsed duration. Errors on multiple distinct offsets.
Unit-tested with 8 cases covering no-offset, simple, negative, 1d,
outer aggregation, error, and repeated-same-offset scenarios.
… mutation safety

Move the LogQL offset extraction block to run after resolveGrafanaRangeTemplateTokens
but before preferWorkingParser so that parser probing uses the shifted historical window
where offset data actually lives. Add Form map alias safety comment.
…r instant queries

Extends the offset directive support to instant queries (GET /loki/api/v1/query).
Strips the offset clause from the LogQL query and shifts the eval `time` parameter
backward by `offsetDur` before calling `preferWorkingParser`, matching the same
pattern already applied in `handleQueryRange` for range queries.

Adds three integration tests: offset shifts time, no-offset leaves time untouched,
and multiple distinct offsets return HTTP 400.
…hift

When a client omits the `time` parameter (Loki allows this, defaulting
to now), parseLokiTimeToUnixNano("") returned (0, false) and the offset
shift was silently skipped. Materialise the default before parsing so
the offset is always applied.
@szibis szibis force-pushed the feature/offset-directive branch from d05aa87 to 7a1f55c Compare May 13, 2026 20:02
@github-actions github-actions Bot added size/XL Extra large change and removed size/XL Extra large change labels May 13, 2026
@szibis szibis merged commit 49ea4e4 into main May 13, 2026
25 checks passed
@szibis szibis deleted the feature/offset-directive branch May 13, 2026 20:02
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

feature New feature scope/docs Documentation scope/proxy Proxy core scope/tests Tests scope/translator LogQL translator size/XL Extra large change

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant