Skip to content

fix(chsql): synthesize TimeUnix on instant-mode VectorSetOp derived arms#707

Merged
tsouza merged 1 commit into
mainfrom
fix/otelcol-kiosk-or-union-residue
May 22, 2026
Merged

fix(chsql): synthesize TimeUnix on instant-mode VectorSetOp derived arms#707
tsouza merged 1 commit into
mainfrom
fix/otelcol-kiosk-or-union-residue

Conversation

@tsouza
Copy link
Copy Markdown
Owner

@tsouza tsouza commented May 22, 2026

Summary

PR #706 introduced a per-arm canonical 4-column projection (SELECT MetricName, Attributes, TimeUnix, Value FROM (<arm>)) on every VectorSetOp arm so a UNION ALL between matrix-shape and canonical-shape arms unifies positional column types. That fix covered the matrix-mode path (range-step) but the same canonical-shape SELECT trips CH 24.x in instant mode (no step):

code: 47, message: Unknown expression identifier 'TimeUnix' in scope
    SELECT '' AS MetricName, Attributes, TimeUnix, Value FROM (...)

or, on a different folding,

code: 1, message: Resolve identifier 'TimeUnix' from parent scope only supported for constants and CTE.

The inner SELECT for an instant-mode RangeWindow / Aggregate / MetricsAggregate / MetricsHistogramOverTime only exposes (group-keys..., <ValueColumn>) — no TimeUnix column to reference. PR #701's new otelcol-observability dashboard surfaced the residue on the "Send failures (5m)" + "Processor refusals (5m)" stat panels (instant /api/v1/query, not query_range):

sum(increase(otelcol_exporter_send_failed_log_records[5m])
    or increase(otelcol_exporter_send_failed_metric_points[5m])
    or increase(otelcol_exporter_send_failed_spans[5m]))

both 502 the cerberus engine; Grafana surfaces them to the browser as a 400, and the panel-kiosk spec catches the resulting console-error trail.

Fix

vectorSetOpCanonicalArmFrag now mirrors wrapWithSampleProjection's instant branch: for derived-shape arms in instant mode, synthesize TimeUnix as (now64(9) - toIntervalNanosecond(5_000_000_000)) instead of referencing it as a column. Matrix-mode arms (OuterRange > 0) still reference TimeUnix by name because emitWindowedArrayPairsMatrix / emitWindowedArrayMatrix already alias anchor_ts AS TimeUnix on the outer SELECT.

The matrix path is unchanged — covered by the existing binary_or_increase_range_canonicalises_arms.txtar fixture. The new binary_or_increase_instant_canonicalises_arms.txtar fixture pins the instant-mode path so this residue can't silently regress.

Live verification

Against the rebuilt compose stack (PR #701 dashboards applied locally), both failing queries return HTTP 200 with the fix:

$ curl -sG -w 'HTTP:%{http_code}\n' 'http://localhost:8080/api/v1/query' \
    --data-urlencode 'query=sum by (processor) (rate(otelcol_processor_dropped_log_records[5m]) or rate(otelcol_processor_dropped_metric_points[5m]) or rate(otelcol_processor_dropped_spans[5m]))'
{"status":"success",...}
HTTP:200

$ curl -sG -w 'HTTP:%{http_code}\n' 'http://localhost:8080/api/v1/query' \
    --data-urlencode 'query=sum(increase(otelcol_exporter_send_failed_log_records[5m]) or increase(otelcol_exporter_send_failed_metric_points[5m]) or increase(otelcol_exporter_send_failed_spans[5m]))'
{"status":"success",...}
HTTP:200

Test plan

🤖 Generated with Claude Code

PR #706's vectorSetOpCanonicalArmFrag projects every VectorSetOp arm as
SELECT MetricName, Attributes, TimeUnix, Value but the inner SELECT for
an instant-mode RangeWindow / Aggregate / MetricsAggregate /
MetricsHistogramOverTime only exposes (group-keys..., Value). The bare
TimeUnix column reference then fails at CH 24.x with
"Unknown expression identifier 'TimeUnix'" / "Resolve identifier
'TimeUnix' from parent scope only supported for constants and CTE".

PR #701's new otelcol-observability dashboard surfaced the residue
on the "Send failures (5m)" + "Processor refusals (5m)" stat panels,
which Grafana renders via instant /api/v1/query (no step). Both fire
as
  sum(increase(otelcol_..._log_records[5m])
      or increase(otelcol_..._metric_points[5m])
      or increase(otelcol_..._spans[5m]))
and consistently 502 the cerberus engine (browser shows 400).

Mirror the wrapWithSampleProjection instant branch: synthesize
TimeUnix as (now64(9) - toIntervalNanosecond(5_000_000_000)) for
derived-shape arms in instant mode. Matrix-mode arms (OuterRange > 0)
still reference TimeUnix by name because emitWindowedArrayPairsMatrix
already aliases anchor_ts AS TimeUnix on the outer SELECT — covered by
the existing binary_or_increase_range_canonicalises_arms fixture; the
new binary_or_increase_instant_canonicalises_arms fixture pins the
instant-mode path.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
@tsouza tsouza enabled auto-merge (squash) May 22, 2026 18:31
@tsouza tsouza merged commit c1bbfe4 into main May 22, 2026
22 checks passed
@tsouza tsouza deleted the fix/otelcol-kiosk-or-union-residue branch May 22, 2026 18:39
tsouza added a commit that referenced this pull request May 22, 2026
… (#720)

PR #706 / #707 added per-arm canonical-shape projection +
instant-mode TimeUnix synthesis to fix SQL emission errors on
nested PromQL or-chains. The 2026-05-22 dirty-fixes audit asked
whether these helpers became unreachable after PR #710
(TableFor -> TablesFor for unsuffixed OTel sums) and PR #716
(extended to _count/_sum suffixes).

Reachability test on the post-#710/#716 tree lowered the
PR #706 failing-shape query and recorded
vectorSetOpCanonicalArmFrag invocations on both arms with
derived=true and the synthesised anchor branch taken. The
workarounds remain on the live emit path because #710/#716
fix which Scan tables get resolved (orthogonal to UNION ALL
column-type unification + missing-identifier-on-derived-inner).

Adds a NOTE block to vectorSetOpCanonicalArmFrag's docstring
documenting the audit so a future reviewer does not delete
the helpers on the assumption they were per-shape patches
for the gauge/sum routing bug.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant