Skip to content

PromQL offset / @ time-shift modifiers have no IR representation #40

Closed

Description

@milindsrivastava1997

Problem

PromQL's offset modifier (metric offset 1h) and @ modifier (metric @ 1609746000) shift the evaluation/lookback time of a vector selector. Unlike without(...) (#39), which is blocked on missing catalog metadata, this is blocked on a missing IR node: there is no time-shift concept anywhere in relational::QueryExpr or canonical QueryExpr to carry the shift amount, so both modifiers are rejected unconditionally rather than partially/incorrectly lowered.

These are common in real dashboards and alerts (week-over-week comparisons, anomaly detection baselines), so this is a meaningful coverage gap distinct from the scalar-operand and without gaps.

Reproduction

crates/lower/src/promql.rs, vs_parts:

fn vs_parts(vs: &VectorSelector) -> Result<(String, Vec<L2Expr>)> {
    // `offset` / `@` shift the evaluation/lookback time. The intent algebra has
    // no representation for either, so silently lowering them (as if absent)
    // would change the query's meaning. Reject rather than mislower.
    if vs.offset.is_some() || vs.at.is_some() {
        return Err(LoweringError::UnsupportedFeature(
            "`offset` / `@` time-shift modifiers have no intent-algebra representation".into(),
        ));
    }
    ...

Any query with offset or @ on a vector/matrix selector — e.g. rate(http_requests_total[5m] offset 1h) or http_requests_total @ 1609746000 — fails to lower with LoweringError::UnsupportedFeature. No test exercises a successful lowering of either modifier.

Activity

  1. zzylol commented on Jul 9, 2026

    @zzylol
    Contributor

    Reopening: this was closed as completed, but the fix never landed on main.

    The implementation commit fff0a2e (feat(promql): lower offset / @ time-shift modifiers to a TimeShift node (#40)) exists only on the unmerged branch feat/40-offset-at-modifiers:

    $ git merge-base --is-ancestor fff0a2e main; echo $?
    1                      # not an ancestor
    $ git branch -a --contains fff0a2e
      feat/40-offset-at-modifiers
      remotes/origin/feat/40-offset-at-modifiers
    

    Unlike the other closed feature issues (#84, #89, …), whose branches show as unmerged only because they were squash-merged, there is no equivalent squashed commit for this one on main, and grep -rn TimeShift crates/ir/src/ returns nothing.

    crates/frontend-promql/src/promql.rs:1414 on main still rejects unconditionally:

    http_requests_total offset 5m
    → unsupported feature: `offset` / `@` time-shift modifiers have no intent-algebra representation
    

    Corpus impact (measured on main)

    65 rejections in the Prometheus testdata corpus, and it is the only failure mode in the official-docs corpus — all 4 failing docs queries are offset/@:

    http_requests_total offset 5m
    sum(http_requests_total{method="GET"} offset 5m)
    http_requests_total @ 1609746000
    http_requests_total @ 1609746000 offset 5m
    

    That makes it the highest-impact real-world PromQL gap remaining. Either feat/40-offset-at-modifiers needs to be rebased and merged, or this issue should be reclosed as not planned with the branch's rationale recorded.

  2. reopened this on Jul 9, 2026
  3. zzylol commented on Jul 9, 2026

    @zzylol
    Contributor

    Correction to the corpus figures above: the docs corpus has 5 failures, not 4. Four are offset/@; the fifth is {__name__=~"job:.*"}, which is rejected deliberately per #67.

    Verified output:

    docs corpus: Tally { lowered: 44, rejected: 5, unparseable: 0 }
    
    [1] {__name__=~"job:.*"}                              => non-equality `__name__` matcher (per #67)
    [2] http_requests_total offset 5m                     => offset / @
    [3] sum(http_requests_total{method="GET"} offset 5m)  => offset / @
    [4] http_requests_total @ 1609746000                  => offset / @
    [5] http_requests_total @ 1609746000 offset 5m        => offset / @
    

    The substance is unchanged: offset/@ is 4 of the 5 docs-corpus failures and the only unintentional one, plus 65 rejections in the testdata corpus.

  4. zzylol commented on Jul 9, 2026

    @zzylol
    Contributor

    Retraction — I was wrong, re-closing.

    offset / @ is supported on main. This issue was correctly closed, and my reopen was based on a stale local ref. Apologies for the noise.

    What happened: my local main was 2 commits behind origin/main, and the branch I was measuring from (test/asapquery-sql-corpus) is based on that older main. So git merge-base --is-ancestor fff0a2e main was answering about a main that predated the merge. PR #106 merged feat/40-offset-at-modifiers into main on 2026-07-06 (merge commit 7f907a98ba), and origin/main does contain the work:

    $ git show origin/main:crates/ir/src/intent_algebra/query_expr.rs | grep -c TimeShift
    16
    $ git show origin/main:crates/frontend-promql/src/promql.rs | grep -n TimeShift | head -1
    47://! | `<selector> offset <d>` / `<selector> @ <ts>`/`start()`/`end()` | `TimeShift{shift}` …
    

    Verified by running the corpus against a clean origin/main worktree (9fdd3d7):

    corpus on stale branch on origin/main
    docs 44 lowered, 5 rejected 48 lowered, 1 rejected
    testdata 1441 lowered, 147 rejected 1502 lowered, 86 rejected

    The 65 offset/@ rejections are gone. The single remaining docs rejection is {__name__=~"job:.*"}, which is the deliberate #67 behaviour.

    Both of my earlier comments on this issue should be disregarded. I've corrected the corpus figures in #108, #109 and #112, which were all measured against the same stale tree — the parser gaps in #108 are unaffected (still exactly 235 parse failures), but the denominators changed.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions