Skip to content

Commit

Permalink
ui: add missing filters for workload insights and active execution pages
Browse files Browse the repository at this point in the history
Fixes #87741, #87783.

Previously, the workload insights page was missing a filter for insights
type for both the statement and transaction tabs. Furthermore, the
active execution pages for statement and transactions was also missing a
status filter.

This commit adds the ability to filter by insights type for the workload
insights page and the ability to filter by execution status for the
active execution pages.

Release note (ui change): added an insights type filter for the workload
insights page, added a execution status filter for the active execution
pages.
  • Loading branch information
gtr committed Jan 17, 2023
1 parent 6116ab4 commit 631cea4
Show file tree
Hide file tree
Showing 27 changed files with 305 additions and 35 deletions.
25 changes: 18 additions & 7 deletions pkg/ui/workspaces/cluster-ui/src/insights/types.ts
Expand Up @@ -200,7 +200,7 @@ export const highContentionInsight = (
const description = `This ${execType} waited on other ${execType}s to execute for ${waitDuration}.`;
return {
name: InsightNameEnum.highContention,
label: "High Contention",
label: InsightEnumToLabel.get(InsightNameEnum.highContention),
description: description,
tooltipDescription:
description + ` Click the ${execType} execution ID to see more details.`,
Expand All @@ -219,7 +219,7 @@ export const slowExecutionInsight = (
const description = `This ${execType} took longer than ${threshold} to execute.`;
return {
name: InsightNameEnum.slowExecution,
label: "Slow Execution",
label: InsightEnumToLabel.get(InsightNameEnum.slowExecution),
description: description,
tooltipDescription:
description + ` Click the ${execType} execution ID to see more details.`,
Expand All @@ -233,7 +233,7 @@ export const planRegressionInsight = (execType: InsightExecEnum): Insight => {
`search conditions, or a change in the database schema.`;
return {
name: InsightNameEnum.planRegression,
label: "Plan Regression",
label: InsightEnumToLabel.get(InsightNameEnum.planRegression),
description: description,
tooltipDescription:
description + ` Click the ${execType} execution ID to see more details.`,
Expand All @@ -246,7 +246,7 @@ export const suboptimalPlanInsight = (execType: InsightExecEnum): Insight => {
`due to outdated statistics or missing indexes.`;
return {
name: InsightNameEnum.suboptimalPlan,
label: "Suboptimal Plan",
label: InsightEnumToLabel.get(InsightNameEnum.suboptimalPlan),
description: description,
tooltipDescription:
description + ` Click the ${execType} execution ID to see more details.`,
Expand All @@ -259,7 +259,7 @@ export const highRetryCountInsight = (execType: InsightExecEnum): Insight => {
`'sql.insights.high_retry_count.threshold' cluster setting.`;
return {
name: InsightNameEnum.highRetryCount,
label: "High Retry Count",
label: InsightEnumToLabel.get(InsightNameEnum.highRetryCount),
description: description,
tooltipDescription:
description + ` Click the ${execType} execution ID to see more details.`,
Expand All @@ -272,7 +272,7 @@ export const failedExecutionInsight = (execType: InsightExecEnum): Insight => {
`saturation, or syntax errors.`;
return {
name: InsightNameEnum.failedExecution,
label: "Failed Execution",
label: InsightEnumToLabel.get(InsightNameEnum.failedExecution),
description: description,
tooltipDescription:
description + ` Click the ${execType} execution ID to see more details.`,
Expand Down Expand Up @@ -310,7 +310,18 @@ export const InsightExecOptions = new Map<string, string>([
[InsightExecEnum.STATEMENT.toString(), "Statement Executions"],
]);

export type WorkloadInsightEventFilters = Pick<Filters, "app">;
export const InsightEnumToLabel = new Map<string, string>([
[InsightNameEnum.highContention.toString(), "High Contention"],
[InsightNameEnum.slowExecution.toString(), "Slow Execution"],
[InsightNameEnum.suboptimalPlan.toString(), "Suboptimal Plan"],
[InsightNameEnum.highRetryCount.toString(), "High Retry Count"],
[InsightNameEnum.failedExecution.toString(), "Failed Execution"],
]);

export type WorkloadInsightEventFilters = Pick<
Filters,
"app" | "workloadInsightType"
>;

export type SchemaInsightEventFilters = Pick<
Filters,
Expand Down
26 changes: 26 additions & 0 deletions pkg/ui/workspaces/cluster-ui/src/insights/utils.ts
Expand Up @@ -63,6 +63,19 @@ export const filterTransactionInsights = (
} else {
filteredTransactions = filteredTransactions.filter(txn => !isInternal(txn));
}
if (filters.workloadInsightType && filters.workloadInsightType.length > 0) {
const workloadInsightTypes = filters.workloadInsightType
.toString()
.split(",");

filteredTransactions = filteredTransactions.filter(transaction =>
workloadInsightTypes.some(workloadType =>
transaction.insights.some(
txnInsight => workloadType === txnInsight.label,
),
),
);
}
if (search) {
search = search.toLowerCase();

Expand Down Expand Up @@ -205,6 +218,19 @@ export const filterStatementInsights = (
stmt => !isInternal(stmt.application),
);
}
if (filters.workloadInsightType && filters.workloadInsightType.length > 0) {
const workloadInsightTypes = filters.workloadInsightType
.toString()
.split(",");

filteredStatements = filteredStatements.filter(statement =>
workloadInsightTypes.some(workloadType =>
statement.insights.some(
stmtInsight => workloadType === stmtInsight.label,
),
),
);
}
if (search) {
search = search.toLowerCase();
filteredStatements = filteredStatements.filter(
Expand Down
Expand Up @@ -20,6 +20,7 @@ import { PageConfig, PageConfigItem } from "src/pageConfig/pageConfig";
import { Search } from "src/search/search";
import {
calculateActiveFilters,
defaultFilters,
Filter,
getFullFiltersAsStringRecord,
} from "src/queryFilter/filter";
Expand Down Expand Up @@ -62,6 +63,7 @@ const sortableTableCx = classNames.bind(sortableTableStyles);
export type StatementInsightsViewStateProps = {
statements: FlattenedStmtInsights;
statementsError: Error | null;
insightTypes: string[];
filters: WorkloadInsightEventFilters;
sortSetting: SortSetting;
selectedColumnNames: string[];
Expand Down Expand Up @@ -91,6 +93,7 @@ export const StatementInsightsView: React.FC<StatementInsightsViewProps> = (
sortSetting,
statements,
statementsError,
insightTypes,
filters,
timeScale,
isLoading,
Expand Down Expand Up @@ -210,7 +213,8 @@ export const StatementInsightsView: React.FC<StatementInsightsViewProps> = (

const clearFilters = () =>
onSubmitFilters({
app: "",
app: defaultFilters.app,
workloadInsightType: defaultFilters.workloadInsightType,
});

const apps = getAppsFromStatementInsights(
Expand Down Expand Up @@ -253,6 +257,8 @@ export const StatementInsightsView: React.FC<StatementInsightsViewProps> = (
onSubmitFilters={onSubmitFilters}
appNames={apps}
filters={filters}
workloadInsightTypes={insightTypes.sort()}
showWorkloadInsightTypes={true}
/>
</PageConfigItem>
<PageConfigItem className={commonStyles("separator")}>
Expand Down Expand Up @@ -294,7 +300,10 @@ export const StatementInsightsView: React.FC<StatementInsightsViewProps> = (
renderNoResult={
<EmptyInsightsTablePlaceholder
isEmptySearchResults={
search?.length > 0 && filteredStatements?.length === 0
(search?.length > 0 &&
filteredStatements?.length === 0) ||
(countActiveFilters > 0 &&
filteredStatements?.length === 0)
}
/>
}
Expand Down
Expand Up @@ -20,6 +20,7 @@ import { PageConfig, PageConfigItem } from "src/pageConfig/pageConfig";
import { Search } from "src/search/search";
import {
calculateActiveFilters,
defaultFilters,
Filter,
getFullFiltersAsStringRecord,
} from "src/queryFilter/filter";
Expand Down Expand Up @@ -56,6 +57,7 @@ const sortableTableCx = classNames.bind(sortableTableStyles);
export type TransactionInsightsViewStateProps = {
transactions: MergedTxnInsightEvent[];
transactionsError: Error | null;
insightTypes: string[];
filters: WorkloadInsightEventFilters;
sortSetting: SortSetting;
isLoading?: boolean;
Expand Down Expand Up @@ -83,6 +85,7 @@ export const TransactionInsightsView: React.FC<TransactionInsightsViewProps> = (
sortSetting,
transactions,
transactionsError,
insightTypes,
filters,
timeScale,
isLoading,
Expand Down Expand Up @@ -194,7 +197,8 @@ export const TransactionInsightsView: React.FC<TransactionInsightsViewProps> = (

const clearFilters = () =>
onSubmitFilters({
app: "",
app: defaultFilters.app,
workloadInsightType: defaultFilters.workloadInsightType,
});

const transactionInsights = transactions;
Expand Down Expand Up @@ -228,6 +232,8 @@ export const TransactionInsightsView: React.FC<TransactionInsightsViewProps> = (
onSubmitFilters={onSubmitFilters}
appNames={apps}
filters={filters}
workloadInsightTypes={insightTypes.sort()}
showWorkloadInsightTypes={true}
/>
</PageConfigItem>
<PageConfigItem className={commonStyles("separator")}>
Expand Down Expand Up @@ -265,7 +271,10 @@ export const TransactionInsightsView: React.FC<TransactionInsightsViewProps> = (
renderNoResult={
<EmptyInsightsTablePlaceholder
isEmptySearchResults={
search?.length > 0 && filteredTransactions?.length === 0
(search?.length > 0 &&
filteredTransactions?.length === 0) ||
(countActiveFilters > 0 &&
filteredTransactions?.length === 0)
}
/>
}
Expand Down
Expand Up @@ -32,6 +32,7 @@ import {
selectExecutionInsights,
selectExecutionInsightsError,
selectExecutionInsightsLoading,
selectInsightTypes,
} from "src/store/insights/statementInsights";
import {
actions as transactionInsights,
Expand All @@ -52,6 +53,7 @@ const transactionMapStateToProps = (
): TransactionInsightsViewStateProps => ({
transactions: selectTransactionInsights(state),
transactionsError: selectTransactionInsightsError(state),
insightTypes: selectInsightTypes(),
filters: selectFilters(state),
sortSetting: selectSortSetting(state),
timeScale: selectTimeScale(state),
Expand All @@ -64,6 +66,7 @@ const statementMapStateToProps = (
): StatementInsightsViewStateProps => ({
statements: selectExecutionInsights(state),
statementsError: selectExecutionInsightsError(state),
insightTypes: selectInsightTypes(),
filters: selectFilters(state),
sortSetting: selectSortSetting(state),
selectedColumnNames: selectColumns(state),
Expand Down
16 changes: 16 additions & 0 deletions pkg/ui/workspaces/cluster-ui/src/queryFilter/filter.spec.tsx
Expand Up @@ -17,6 +17,7 @@ describe("Test filter functions", (): void => {
app: "",
timeNumber: "0",
timeUnit: "seconds",
executionStatus: "",
fullScan: false,
sqlType: "",
database: "",
Expand All @@ -25,6 +26,7 @@ describe("Test filter functions", (): void => {
sessionStatus: "",
nodes: "",
username: "",
workloadInsightType: "",
};
const resultFilters = getFiltersFromQueryString("");
expect(resultFilters).toEqual(expectedFilters);
Expand All @@ -36,6 +38,7 @@ describe("Test filter functions", (): void => {
app: "$ internal",
timeNumber: "1",
timeUnit: "milliseconds",
executionStatus: "",
fullScan: true,
sqlType: "DML",
database: "movr",
Expand All @@ -44,6 +47,7 @@ describe("Test filter functions", (): void => {
sessionStatus: "idle",
nodes: "n1,n2",
username: "root",
workloadInsightType: "",
};
const resultFilters = getFiltersFromQueryString(
"app=%24+internal&timeNumber=1&timeUnit=milliseconds&fullScan=true&sqlType=DML&database=movr&sessionStatus=idle&username=root&regions=us-central&nodes=n1,n2&schemaInsightType=Drop+Unused+Index",
Expand All @@ -56,6 +60,7 @@ describe("Test filter functions", (): void => {
app: "",
timeNumber: "0",
timeUnit: "seconds",
executionStatus: "",
fullScan: true,
sqlType: "",
database: "",
Expand All @@ -64,6 +69,7 @@ describe("Test filter functions", (): void => {
sessionStatus: "",
nodes: "",
username: "",
workloadInsightType: "",
};
const resultFilters = getFiltersFromQueryString("fullScan=true");
expect(resultFilters).toEqual(expectedFilters);
Expand All @@ -74,6 +80,7 @@ describe("Test filter functions", (): void => {
app: "",
timeNumber: "0",
timeUnit: "seconds",
executionStatus: "",
fullScan: false,
sqlType: "",
database: "",
Expand All @@ -82,6 +89,7 @@ describe("Test filter functions", (): void => {
sessionStatus: "",
nodes: "",
username: "",
workloadInsightType: "",
};
const resultFilters = getFiltersFromQueryString("fullScan=false");
expect(resultFilters).toEqual(expectedFilters);
Expand All @@ -92,6 +100,7 @@ describe("Test filter functions", (): void => {
app: "",
timeNumber: "0",
timeUnit: "seconds",
executionStatus: "",
fullScan: false,
sqlType: "",
database: "",
Expand All @@ -100,6 +109,7 @@ describe("Test filter functions", (): void => {
sessionStatus: "open",
nodes: "",
username: "",
workloadInsightType: "",
};
const resultFilters = getFiltersFromQueryString("sessionStatus=open");
expect(resultFilters).toEqual(expectedFilters);
Expand All @@ -110,6 +120,7 @@ describe("Test filter functions", (): void => {
app: "",
timeNumber: "0",
timeUnit: "seconds",
executionStatus: "",
fullScan: false,
sqlType: "",
database: "",
Expand All @@ -118,6 +129,7 @@ describe("Test filter functions", (): void => {
sessionStatus: "idle",
nodes: "",
username: "",
workloadInsightType: "",
};
const resultFilters = getFiltersFromQueryString("sessionStatus=idle");
expect(resultFilters).toEqual(expectedFilters);
Expand All @@ -128,6 +140,7 @@ describe("Test filter functions", (): void => {
app: "",
timeNumber: "0",
timeUnit: "seconds",
executionStatus: "",
fullScan: false,
sqlType: "",
database: "",
Expand All @@ -136,6 +149,7 @@ describe("Test filter functions", (): void => {
sessionStatus: "closed",
nodes: "",
username: "",
workloadInsightType: "",
};
const resultFilters = getFiltersFromQueryString("sessionStatus=closed");
expect(resultFilters).toEqual(expectedFilters);
Expand All @@ -146,6 +160,7 @@ describe("Test filter functions", (): void => {
app: "",
timeNumber: "0",
timeUnit: "seconds",
executionStatus: "",
fullScan: false,
sqlType: "",
database: "",
Expand All @@ -154,6 +169,7 @@ describe("Test filter functions", (): void => {
sessionStatus: "",
nodes: "",
username: "",
workloadInsightType: "",
};
const resultFilters = getFiltersFromQueryString(
"schemaInsightType=Drop+Unused+Index",
Expand Down

0 comments on commit 631cea4

Please sign in to comment.