Skip to content

[FSE-1855] Read Flink statement warnings from status.warnings - #3419

Open
Ramin Gharib (raminqaf) wants to merge 1 commit into
mainfrom
fse-1855-cli-statement-warnings
Open

[FSE-1855] Read Flink statement warnings from status.warnings#3419
Ramin Gharib (raminqaf) wants to merge 1 commit into
mainfrom
fse-1855-cli-statement-warnings

Conversation

@raminqaf

@raminqaf Ramin Gharib (raminqaf) commented Jul 30, 2026

Copy link
Copy Markdown
Member

Release Notes

New Features

  • Show Flink SQL statement warnings with their severity, reason, and timestamp in the Flink SQL shell, on dry runs, and in confluent flink statement describe and confluent flink statement create. Warnings are listed most severe first.
  • Add a warnings field to the serialized output of confluent flink statement describe, confluent flink statement create, and confluent flink statement list so -o json and -o yaml consumers can read each warning's severity, reason, message, and creation time.

Bug Fixes

  • Fix Flink SQL statement warnings disappearing shortly after a statement was submitted, and multiple warnings being joined into a single unreadable line.

Checklist

  • I have successfully built and used a custom CLI binary, without linter issues from this PR.
  • I have clearly specified in the What section below whether this PR applies to Confluent Cloud, Confluent Platform, or both.
  • I have verified this PR in Confluent Cloud pre-prod or production environment, if applicable. Not yet done. Verified against the integration test server only, see Test & Review.
  • I have verified this PR in Confluent Platform on-premises environment, if applicable. Not applicable, see What.
  • I have attached manual CLI verification results or screenshots in the Test & Review section below.
  • I have added appropriate CLI integration or unit tests for any new or updated commands and functionality.
  • I confirm that this PR introduces no breaking changes or backward compatibility issues.
  • I have indicated the potential customer impact if something goes wrong in the Blast Radius section below.
  • I have put checkmarks below confirming that the feature associated with this PR is enabled in:
    • Confluent Cloud prod
    • Confluent Cloud stag
    • Confluent Platform
    • Check this box if the feature is enabled for certain organizations only

The CLI only renders the warnings the API returns. Where a statement has no warnings, output is unchanged, so no CLI-side enablement is needed.

What

Applies to Confluent Cloud only. The warnings field is part of the Confluent Cloud Flink statement status. The Confluent Platform on-premises code paths are untouched.

The CLI displayed statement warnings by printing status.detail as a warning banner. That field is a single flat string. It has no severity, no machine-readable reason, and no timestamp, and it is rewritten as a statement moves through its lifecycle. Two consequences for users: warnings vanished from view shortly after submission, and several warnings arrived concatenated into one long line that was hard to read and impossible to render as a list.

Statement warnings are now read from the structured status.warnings array. Each warning is rendered with its severity, reason, and creation time, most severe first:

Warnings:

CRITICAL [HIGH_STATE_OPERATOR_WITHOUT_TTL] (Logged: 2022-01-01T00:00:00Z)
Your query includes one or more highly state-intensive operators but does not set a time-to-live (TTL) value.

MODERATE [MISSING_WINDOW_START_END] (Logged: 2022-01-01T00:00:00Z)
The GROUP BY clause contains only `window_start` with no corresponding `window_end`.

Notes on the approach:

  • Surfaces covered. The Flink SQL shell, dry runs, confluent flink statement describe, and confluent flink statement create. confluent flink statement list carries the warnings in serialized output but does not render a block per row, which would bury the table.
  • Serialized output. A new warnings field is added to describe, create, and list. It is omitempty, so output for statements without warnings is byte-for-byte unchanged. This is an additive field only.
  • Human output keeps prose out of the table. A warning message is a paragraph, so it is printed below the table rather than in a cell.
  • status.detail is still printed when a statement has no warnings, and always for a failed statement, where the detail carries the failure reason. Skipping it when warnings are present avoids showing the same warning twice, since the detail can still repeat the warning text.
  • Unrecognized severities are displayed, not dropped. Severity is an extensible enum, so a value this version of the CLI does not know is still shown and sorted last.

Blast Radius

Confluent Cloud customers using confluent flink shell, confluent flink statement describe, confluent flink statement create, or confluent flink statement list.

If something goes wrong, the worst case is a display defect: warnings are not shown, are shown in the wrong order, or the Status Detail line is omitted for a statement that has warnings. Statement submission, execution, and results are not touched, so no customer would be blocked from running a statement. Serialized output gains a field and loses none, so existing scripts that parse -o json or -o yaml continue to work.

Confluent Platform on-premises users are unaffected.

References

Test & Review

Automated:

  • Unit tests for the conversion from the API type, severity ordering, unrecognized severities, timestamp rendering in UTC, and the header format. See pkg/flink/types/statement_warning_test.go.
  • Unit tests for the print rules, including that a failed statement still shows its detail alongside its warnings, and that a statement without warnings prints exactly what it did before. See pkg/flink/types/processed_statement_test.go.
  • A snapshot test for the shell path in pkg/flink/internal/controller/statement_controller_test.go. Writing this caught a real bug: the formatter only produced sorted output when the slice came from the converter, so a caller-built slice printed unsorted. The formatter now sorts a copy of its input.
  • Integration tests for describe in human and YAML output, with new golden files. The test server returns warnings only for a dedicated statement name, so no existing golden file changed.

Commands run:

go test ./internal/... ./pkg/...
golangci-lint run
make integration-test INTEGRATION_TEST_ARGS="-run TestCLI/TestFlinkStatement"

Verified output, human format:

+--------------------------+---------------------------------------------------------+
| Creation Date            | 2022-01-01 00:00:00 +0000 UTC                           |
| Name                     | my-statement-with-warnings                              |
| Statement                | CREATE TABLE test;                                      |
| Compute Pool             | lfcp-123456                                             |
| Status                   | COMPLETED                                               |
| Status Detail            | SQL statement is completed                              |
| Latest Offsets           | customers_source=partition:0,offset:9223372036854775808 |
| Latest Offsets Timestamp | 2022-01-01 00:00:00 +0000 UTC                           |
| Properties               | sql.current-catalog=default                             |
|                          | sql.current-database=my-cluster                         |
| Principal                | u-123456                                                |
+--------------------------+---------------------------------------------------------+

Warnings:

CRITICAL [HIGH_STATE_OPERATOR_WITHOUT_TTL] (Logged: 2022-01-01T00:00:00Z)
Your query includes one or more highly state-intensive operators but does not set a time-to-live (TTL) value.

MODERATE [MISSING_WINDOW_START_END] (Logged: 2022-01-01T00:00:00Z)
The GROUP BY clause contains only `window_start` with no corresponding `window_end`.

Verified output, -o yaml:

creation_date: 2022-01-01T00:00:00Z
name: my-statement-with-warnings
statement: CREATE TABLE test;
compute_pool: lfcp-123456
status: COMPLETED
status_detail: SQL statement is completed
warnings:
    - severity: CRITICAL
      reason: HIGH_STATE_OPERATOR_WITHOUT_TTL
      message: Your query includes one or more highly state-intensive operators but does not set a time-to-live (TTL) value.
      created_at: 2022-01-01T00:00:00Z
    - severity: MODERATE
      reason: MISSING_WINDOW_START_END
      message: The GROUP BY clause contains only `window_start` with no corresponding `window_end`.
      created_at: 2022-01-01T00:00:00Z
latest_offsets:
    customers_source: partition:0,offset:9223372036854775808
latest_offsets_timestamp: 2022-01-01T00:00:00Z
properties:
    sql.current-catalog: default
    sql.current-database: my-cluster
principal: u-123456

Built and tested locally

Describe output:
image

From Flink Shell
image

@raminqaf
Ramin Gharib (raminqaf) requested a review from a team as a code owner July 30, 2026 11:14
Copilot AI review requested due to automatic review settings July 30, 2026 11:14
@confluent-cla-assistant

Copy link
Copy Markdown

🎉 All Contributor License Agreements have been signed. Ready to merge.
Please push an empty commit if you would like to re-run the checks to verify CLA status for all contributors.

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR updates the Flink statement UX and serialized outputs to consume structured statement warnings from status.warnings (severity/reason/message/timestamp), ensuring warnings don’t disappear as status.detail changes over a statement’s lifecycle and enabling reliable -o json/-o yaml consumption.

Changes:

  • Introduces a StatementWarning type plus conversion/formatting utilities, including severity-based ordering.
  • Plumbs structured warnings into Flink statement create/describe/list outputs (human + serialized), and into shell/dry-run status messaging.
  • Adds unit tests, snapshot tests, and integration goldens to cover sorting, rendering, and output stability.

Reviewed changes

Copilot reviewed 15 out of 15 changed files in this pull request and generated 3 comments.

Show a summary per file
File Description
pkg/flink/types/statement_warning.go Adds structured warning model, conversion from SDK type, severity sorting, and terminal formatter.
pkg/flink/types/statement_warning_test.go Unit tests for warning conversion/sorting and formatting rules.
pkg/flink/types/processed_statement.go Carries warnings on processed statements and prints them (while reducing legacy status.detail duplication in shell/dry-run flows).
pkg/flink/types/processed_statement_test.go Unit tests for status-detail vs structured-warnings printing rules.
pkg/flink/internal/store/store.go Refreshes warnings while polling since warnings can appear after submission.
pkg/flink/internal/controller/statement_controller_test.go Adds snapshot coverage for structured warnings in the shell execution path.
pkg/flink/internal/controller/.snapshots/TestStatementControllerTestSuite-TestExecuteStatementWithStructuredWarnings Snapshot output for structured warnings ordering/rendering in shell flow.
internal/flink/command_statement.go Adds shared printStatementWarnings helper and extends statement output struct with warnings for serialization.
internal/flink/command_statement_describe.go Includes warnings in serialized output and prints a human-readable warnings block below the table.
internal/flink/command_statement_create.go Includes warnings in serialized output and prints a human-readable warnings block below the table.
internal/flink/command_statement_list.go Adds warnings to serialized list output (kept out of human table rows).
test/test-server/flink_gateway_router.go Test server now returns structured warnings for a dedicated statement name.
test/flink_test.go Adds integration test cases for describing a statement with warnings (human + YAML).
test/fixtures/output/flink/statement/describe-warnings.golden Golden for human describe output including warnings block.
test/fixtures/output/flink/statement/describe-warnings-yaml.golden Golden for YAML describe output including structured warnings.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread internal/flink/command_statement_describe.go
Comment thread internal/flink/command_statement_create.go
Comment thread pkg/flink/types/statement_warning.go Outdated
@airlock-confluentinc
airlock-confluentinc Bot force-pushed the fse-1855-cli-statement-warnings branch from 9b3f8e9 to 4a26984 Compare July 30, 2026 12:30

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks!

I left a comment. Also, could we get some manual test results from the flink shell?

Comment on lines +18 to +26
if output.GetFormat(cmd) != output.Human {
return
}

if block := types.FormatStatementWarnings(warnings); block != "" {
output.Println(false, "")
output.Println(false, block)
output.Println(false, "")
}

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would it work for the ticket to log these to -v (warn), at least for the non-shell outputs?

It's only in the human readable output so it's not necessarily an issue, but it does deviate from the usual pattern for CLI outputs.

If we do want these to always be displayed, let's write it to stderr instead.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good point on the convention, moved to stderr for the non-shell commands. stdout is now just the table, so redirecting or piping gives you clean data, and -o json/-o yaml are untouched since they carry the warnings in the payload itself.
I left the shell on stdout. Everything there is already conversational output on stdout, including the status messages and the old Details: banner, so splitting only the warnings onto stderr would be inconsistent with the surrounding lines.
On -v: I'd rather not hide them behind a verbosity flag. The requirement for this feature is that all warnings are always shown, which is the whole reason for moving them out of status.detail, so making them opt-in would undo that.
Goldens are unchanged since the integration harness captures combined output.

The CLI showed statement warnings by printing status.detail as a warning banner. That field is a single flat string with no severity, reason, or timestamp, and it gets overwritten during the statement lifecycle, so warnings were short-lived and could not be rendered as a list.

Statement warnings are now read from the structured status.warnings array and rendered most severe first, in the SQL shell, on dry runs, and in `confluent flink statement describe` and `create`. Serialized output carries the warnings verbatim under a new `warnings` field, so `-o json` and `-o yaml` consumers get severity, reason, message, and created_at.

status.detail is still printed when a statement has no warnings, and always for a failed statement where it holds the failure reason.
@airlock-confluentinc
airlock-confluentinc Bot force-pushed the fse-1855-cli-statement-warnings branch from 4a26984 to b729b60 Compare July 31, 2026 06:18
@sonarqube-confluent

Copy link
Copy Markdown

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.

3 participants