Skip to content

Commit 56829d8

Browse files
ui: surface SQL commenter query tags in insights
This commit adds support for displaying SQL commenter query tags in the CockroachDB DB Console insights UI, addressing GitHub issue #146664. Changes: - Add query_tags to statement insights API response - Update TypeScript types to include queryTags field - Add Query Tags column to statement insights table (hidden by default) - Display query tags on statement insight detail pages - Add proper column titles and tooltips for query tags The query tags were already being stored in the backend execution insights tables by PR #145435. This change surfaces that data in the frontend UI, allowing users to correlate query performance with application context provided via SQL commenter tags. Fixes #146664 Release note (ui change): The DB Console insights page now displays SQL commenter query tags for statement executions. Query tags provide application context (such as application name, user ID, or feature flags) embedded in SQL comments using the sqlcommenter format. This information can help correlate slow query performance with specific application state. The Query Tags column is available in the statement insights table but hidden by default - it can be enabled via the Columns selector. 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <[email protected]>
1 parent bbe6bc6 commit 56829d8

File tree

6 files changed

+54
-6
lines changed

6 files changed

+54
-6
lines changed

pkg/ui/workspaces/cluster-ui/src/api/stmtInsightsApi.ts

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,7 @@ export type StmtInsightsResponseRow = {
6666
error_code: string;
6767
last_error_redactable: string;
6868
status: StatementStatus;
69+
query_tags: Array<{ name: string; value: string }>;
6970
};
7071

7172
const stmtColumns = `
@@ -97,7 +98,8 @@ plan_gist,
9798
cpu_sql_nanos,
9899
error_code,
99100
last_error_redactable,
100-
status
101+
status,
102+
query_tags
101103
`;
102104

103105
const stmtInsightsOverviewQuery = (req?: StmtInsightsReq): string => {
@@ -241,6 +243,7 @@ export function formatStmtInsights(
241243
errorCode: row.error_code,
242244
errorMsg: row.last_error_redactable,
243245
status: row.status,
246+
queryTags: row.query_tags || [],
244247
} as StmtInsightEvent;
245248
});
246249
}

pkg/ui/workspaces/cluster-ui/src/insights/types.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -120,6 +120,7 @@ export type StmtInsightEvent = InsightEventBase & {
120120
execType?: InsightExecEnum;
121121
status: StatementStatus;
122122
errorMsg?: string;
123+
queryTags?: Array<{ name: string; value: string }>;
123124
};
124125

125126
export type Insight = {

pkg/ui/workspaces/cluster-ui/src/insights/workloadInsightDetails/statementInsightDetailsOverviewTab.tsx

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -171,6 +171,21 @@ export const StatementInsightDetailsOverviewTab: React.FC<
171171
label="Statement Fingerprint ID"
172172
value={StatementDetailsLink(insightDetails)}
173173
/>
174+
{insightDetails?.queryTags &&
175+
insightDetails.queryTags.length > 0 && (
176+
<SummaryCardItem
177+
label="Query Tags"
178+
value={
179+
<div>
180+
{insightDetails.queryTags.map((tag, index) => (
181+
<div key={index}>
182+
<strong>{tag.name}:</strong> {tag.value}
183+
</div>
184+
))}
185+
</div>
186+
}
187+
/>
188+
)}
174189
</SummaryCard>
175190
</Col>
176191
</Row>

pkg/ui/workspaces/cluster-ui/src/insights/workloadInsights/statementInsights/statementInsightsTable.tsx

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -146,6 +146,28 @@ export function makeStatementInsightsColumns(): ColumnDescriptor<StmtInsightEven
146146
sort: (item: StmtInsightEvent) => item.application,
147147
showByDefault: true,
148148
},
149+
{
150+
name: "queryTags",
151+
title: insightsTableTitles.queryTags(execType),
152+
cell: (item: StmtInsightEvent) => {
153+
if (!item.queryTags || item.queryTags.length === 0) {
154+
return "N/A";
155+
}
156+
const tagsStr = item.queryTags
157+
.map(tag => `${tag.name}=${tag.value}`)
158+
.join(", ");
159+
return (
160+
<Tooltip placement="bottom" content={tagsStr}>
161+
<span className={cx("queries-row")}>{limitText(tagsStr, 30)}</span>
162+
</Tooltip>
163+
);
164+
},
165+
sort: (item: StmtInsightEvent) =>
166+
item.queryTags
167+
? item.queryTags.map(tag => `${tag.name}=${tag.value}`).join(", ")
168+
: "",
169+
showByDefault: false,
170+
},
149171
{
150172
name: "rowsProcessed",
151173
title: insightsTableTitles.rowsProcessed(execType),

pkg/ui/workspaces/cluster-ui/src/insights/workloadInsights/util/insightsColumns.tsx

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ export const insightsColumnLabels = {
3636
tableName: "Table Name",
3737
indexName: "Index Name",
3838
cpu: "SQL CPU Time",
39+
queryTags: "Query Tags",
3940
};
4041

4142
export type InsightsTableColumnKeys = keyof typeof insightsColumnLabels;
@@ -240,4 +241,14 @@ export const insightsTableTitles: InsightsTableTitleType = {
240241
"cpu",
241242
);
242243
},
244+
queryTags: (execType: InsightExecEnum) => {
245+
return makeToolTip(
246+
<p>
247+
The query tags extracted from comments in the {execType} query. These
248+
tags provide application context and can be used to correlate query
249+
performance with client-side application state.
250+
</p>,
251+
"queryTags",
252+
);
253+
},
243254
};

pkg/ui/workspaces/cluster-ui/src/statementsPage/statementsPage.fixture.ts

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,6 @@ import { DEFAULT_STATS_REQ_OPTIONS } from "src/api/statementsApi";
1515
import { mockStmtStats } from "src/api/testUtils";
1616
import { RequestError } from "src/util";
1717

18-
1918
import { StatementDiagnosticsReport } from "../api";
2019

2120
import { StatementsPageProps } from "./statementsPage";
@@ -414,10 +413,7 @@ export const statementsPagePropsWithRequestError: StatementsPageProps = {
414413
data: null,
415414
lastUpdated,
416415
valid: true,
417-
error: new RequestError(
418-
403,
419-
"this operation requires admin privilege",
420-
),
416+
error: new RequestError(403, "this operation requires admin privilege"),
421417
inFlight: false,
422418
},
423419
};

0 commit comments

Comments
 (0)