Skip to content

Tag CloudFetch, Arrow schema, and result-fetch errors for telemetry#417

Draft
prathamesh-db wants to merge 1 commit into
prathamesh/PECOBLR-3537-classify-reads-categoryfrom
prathamesh/PECOBLR-3537-tag-group-a
Draft

Tag CloudFetch, Arrow schema, and result-fetch errors for telemetry#417
prathamesh-db wants to merge 1 commit into
prathamesh/PECOBLR-3537-classify-reads-categoryfrom
prathamesh/PECOBLR-3537-tag-group-a

Conversation

@prathamesh-db

Copy link
Copy Markdown
Collaborator

What

Attaches source-declared error categories at the error sites on the
result-materialization paths, so telemetry reports a precise
error_name instead of the generic error fallback:

Category Site
chunk_download_error CloudFetch batch download failures (internal/rows/arrowbased/batchloader.go)
arrow_schema_parsing_error Arrow schema convert / serialize / read failures (internal/rows/arrowbased/arrowRows.go)
result_set_error result-page fetch (internal/rows/rowscanner/resultPageIterator.go) and result-set metadata fetch (internal/rows/rows.go)
statement_execution_timeout sentinel WatchTimeout in the poll loop (internal/backend/thrift/backend.go)

A fetch aborted via the results context (e.g. on Close) is left untagged, so
it still classifies as cancelled/timeout rather than result_set_error,
matching the CloudFetch path.

statement_execution_timeout is unreachable in production today (the sole
Watch call uses timeout=0, so the branch never fires and emits no
telemetry); it is tagged and commented so it classifies correctly if a nonzero
poll timeout is ever enabled.

Why it's safe

  • All tags use the existing WithCategory chaining, which returns the same
    concrete pointer
    , so errors.Is/errors.As, the dbsqlerr.DBError
    assertion in the Arrow scan path, Error() strings, and sentinel identity
    are all unchanged.
  • Each live tag reaches classifyError via the row-iteration path
    (NextiterationErrAfterExecute), verified by the added tests.

Also: a latent bug fix

rows.getResultSetSchema wrapped the wrong (nil) variable on a
GetResultSetMetadata failure, dropping the real cause from the error chain.
Fixed to wrap the actual cause. This doesn't change the telemetry category (the
tag wins regardless), but it restores Cause()/Unwrap().


Stacked on #415 (base is that branch, not main); auto-retargets to main once #415 merges.

Design doc: https://docs.google.com/document/d/12ufP1eZrgFxWt6xzINfkhfrE-NnhB29zCa5PKokVfp8/edit
Jira: PECOBLR-3537

Third step of PECOBLR-3537. Attaches source-declared error categories at
the error sites on the result-materialization paths, so telemetry reports
a precise error_name instead of the generic "error" fallback:

- chunk_download_error: CloudFetch batch download failures
  (internal/rows/arrowbased/batchloader.go).
- arrow_schema_parsing_error: Arrow schema convert/serialize/read failures
  (internal/rows/arrowbased/arrowRows.go).
- result_set_error: result-page fetch failure
  (internal/rows/rowscanner/resultPageIterator.go) and result-set metadata
  fetch failure (internal/rows/rows.go). A caller cancellation/deadline is
  left untagged at these sites so it still classifies as cancelled/timeout.
- statement_execution_timeout: sentinel WatchTimeout in the poll loop
  (internal/backend/thrift/backend.go). This branch is unreachable in
  production today (the sole Watch call uses timeout=0), so it emits no
  telemetry; it is tagged and commented so it classifies correctly if a
  nonzero poll timeout is ever enabled.

All tags use the existing WithCategory chaining, which returns the same
concrete pointer, so errors.Is/As, the dbsqlerr.DBError assertion in the
Arrow scan path, Error() strings, and sentinel identity are unchanged.
Each live tag reaches classifyError via the row-iteration path
(Next -> iterationErr -> AfterExecute), verified by the added tests.

Separately, this fixes a latent bug in rows.getResultSetSchema where a
GetResultSetMetadata failure wrapped the wrong (nil) variable instead of
the real cause, dropping it from the error chain. This does not change the
telemetry category (the tag wins regardless) but restores Cause()/Unwrap().

unsupported_operation (staging default case) is deferred to a follow-up:
it is on a separate path and depends on more fragile invariants.

Signed-off-by: Prathamesh Baviskar <prathamesh.baviskar@databricks.com>
@prathamesh-db prathamesh-db self-assigned this Jul 21, 2026
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