forked from cockroachdb/cockroach
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
ui: new plan table on statement details
Previously, the Explain Plan tab on Statement Details was showing only one plan. This commit introduces a table of plan with their respective executions stats. When a plan is clicked on the table, it shows the Plan and its statistics. Fixes cockroachdb#72129 Release justification: Category 4 Release note (ui change): Explain Plan tab on Statement Details shows statistics for all the plans executed by the selected statement on the selected period.
- Loading branch information
Showing
7 changed files
with
334 additions
and
15 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
11 changes: 11 additions & 0 deletions
11
pkg/ui/workspaces/cluster-ui/src/statementDetails/planDetails/index.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
// Copyright 2022 The Cockroach Authors. | ||
// | ||
// Use of this software is governed by the Business Source License | ||
// included in the file licenses/BSL.txt. | ||
// | ||
// As of the Change Date specified in that file, in accordance with | ||
// the Business Source License, use of this software will be governed | ||
// by the Apache License, Version 2.0, included in the file | ||
// licenses/APL.txt. | ||
|
||
export * from "./planDetails"; |
76 changes: 76 additions & 0 deletions
76
pkg/ui/workspaces/cluster-ui/src/statementDetails/planDetails/planDetails.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,76 @@ | ||
// Copyright 2022 The Cockroach Authors. | ||
// | ||
// Use of this software is governed by the Business Source License | ||
// included in the file licenses/BSL.txt. | ||
// | ||
// As of the Change Date specified in that file, in accordance with | ||
// the Business Source License, use of this software will be governed | ||
// by the Apache License, Version 2.0, included in the file | ||
// licenses/APL.txt. | ||
|
||
import React, { useState } from "react"; | ||
import { Helmet } from "react-helmet"; | ||
import { ArrowLeft } from "@cockroachlabs/icons"; | ||
import { | ||
PlansSortedTable, | ||
makeExplainPlanColumns, | ||
PlanHashStats, | ||
} from "./plansTable"; | ||
import { Button } from "../../button"; | ||
import { SqlBox } from "../../sql"; | ||
|
||
interface PlanDetailsProps { | ||
plans: PlanHashStats[]; | ||
} | ||
|
||
export function PlanDetails({ plans }: PlanDetailsProps): React.ReactElement { | ||
const [plan, setPlan] = useState<PlanHashStats | null>(null); | ||
const handleDetails = (plan: PlanHashStats): void => { | ||
setPlan(plan); | ||
}; | ||
const backToPlanTable = (): void => { | ||
setPlan(null); | ||
}; | ||
|
||
if (plan) { | ||
return renderExplainPlan(plan, backToPlanTable); | ||
} else { | ||
return renderPlanTable(plans, handleDetails); | ||
} | ||
} | ||
|
||
function renderPlanTable( | ||
plans: PlanHashStats[], | ||
handleDetails: (plan: PlanHashStats) => void, | ||
): React.ReactElement { | ||
const columns = makeExplainPlanColumns(handleDetails); | ||
return ( | ||
<PlansSortedTable | ||
columns={columns} | ||
data={plans} | ||
className="statements-table" | ||
/> | ||
); | ||
} | ||
|
||
function renderExplainPlan( | ||
plan: PlanHashStats, | ||
backToPlanTable: () => void, | ||
): React.ReactElement { | ||
return ( | ||
<div> | ||
<Helmet title="Plan Details" /> | ||
<Button | ||
onClick={backToPlanTable} | ||
type="unstyled-link" | ||
size="small" | ||
icon={<ArrowLeft fontSize={"10px"} />} | ||
iconPosition="left" | ||
className="small-margin" | ||
> | ||
All Plans | ||
</Button> | ||
<SqlBox value={plan.explain_plan} /> | ||
</div> | ||
); | ||
} |
140 changes: 140 additions & 0 deletions
140
pkg/ui/workspaces/cluster-ui/src/statementDetails/planDetails/plansTable.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,140 @@ | ||
// Copyright 2022 The Cockroach Authors. | ||
// | ||
// Use of this software is governed by the Business Source License | ||
// included in the file licenses/BSL.txt. | ||
// | ||
// As of the Change Date specified in that file, in accordance with | ||
// the Business Source License, use of this software will be governed | ||
// by the Apache License, Version 2.0, included in the file | ||
// licenses/APL.txt. | ||
|
||
import React from "react"; | ||
import { ColumnDescriptor, SortedTable } from "src/sortedtable"; | ||
import { Tooltip } from "@cockroachlabs/ui-components"; | ||
import { cockroach } from "@cockroachlabs/crdb-protobuf-client"; | ||
import { | ||
Duration, | ||
formatNumberForDisplay, | ||
longToInt, | ||
TimestampToMoment, | ||
} from "../../util"; | ||
|
||
export type PlanHashStats = cockroach.server.serverpb.StatementDetailsResponse.ICollectedStatementGroupedByPlanHash; | ||
export class PlansSortedTable extends SortedTable<PlanHashStats> {} | ||
|
||
const planDetailsColumnLabels = { | ||
planID: "Plan ID", | ||
last_exec_time: "Last Execution Time", | ||
avg_exec_time: "Average Execution Time", | ||
exec_count: "Execution Count", | ||
avg_rows_read: "Average Rows Read", | ||
}; | ||
export type PlanDetailsTableColumnKeys = keyof typeof planDetailsColumnLabels; | ||
|
||
type PlanDetailsTableTitleType = { | ||
[key in PlanDetailsTableColumnKeys]: () => JSX.Element; | ||
}; | ||
|
||
export const planDetailsTableTitles: PlanDetailsTableTitleType = { | ||
planID: () => { | ||
return ( | ||
<Tooltip | ||
style="tableTitle" | ||
placement="bottom" | ||
content={"The ID of the Plan."} | ||
> | ||
{planDetailsColumnLabels.planID} | ||
</Tooltip> | ||
); | ||
}, | ||
last_exec_time: () => { | ||
return ( | ||
<Tooltip | ||
style="tableTitle" | ||
placement="bottom" | ||
content={"The last time this Plan was executed."} | ||
> | ||
{planDetailsColumnLabels.last_exec_time} | ||
</Tooltip> | ||
); | ||
}, | ||
avg_exec_time: () => { | ||
return ( | ||
<Tooltip | ||
style="tableTitle" | ||
placement="bottom" | ||
content={"The average execution time for this Plan."} | ||
> | ||
{planDetailsColumnLabels.avg_exec_time} | ||
</Tooltip> | ||
); | ||
}, | ||
exec_count: () => { | ||
return ( | ||
<Tooltip | ||
style="tableTitle" | ||
placement="bottom" | ||
content={"The execution count for this Plan."} | ||
> | ||
{planDetailsColumnLabels.exec_count} | ||
</Tooltip> | ||
); | ||
}, | ||
avg_rows_read: () => { | ||
return ( | ||
<Tooltip | ||
style="tableTitle" | ||
placement="bottom" | ||
content={"The average of rows read by this Plan."} | ||
> | ||
{planDetailsColumnLabels.avg_rows_read} | ||
</Tooltip> | ||
); | ||
}, | ||
}; | ||
|
||
export function makeExplainPlanColumns( | ||
handleDetails: (plan: PlanHashStats) => void, | ||
): ColumnDescriptor<PlanHashStats>[] { | ||
const duration = (v: number) => Duration(v * 1e9); | ||
return [ | ||
{ | ||
name: "planID", | ||
title: planDetailsTableTitles.planID(), | ||
cell: (item: PlanHashStats) => ( | ||
<a onClick={() => handleDetails(item)}>{longToInt(item.plan_hash)}</a> | ||
), | ||
sort: (item: PlanHashStats) => longToInt(item.plan_hash), | ||
alwaysShow: true, | ||
}, | ||
{ | ||
name: "last_exec_time", | ||
title: planDetailsTableTitles.last_exec_time(), | ||
cell: (item: PlanHashStats) => | ||
TimestampToMoment(item.stats.last_exec_timestamp).format( | ||
"MMM DD, YYYY HH:MM", | ||
), | ||
sort: (item: PlanHashStats) => | ||
TimestampToMoment(item.stats.last_exec_timestamp).unix(), | ||
}, | ||
{ | ||
name: "avg_exec_time", | ||
title: planDetailsTableTitles.avg_exec_time(), | ||
cell: (item: PlanHashStats) => | ||
formatNumberForDisplay(item.stats.run_lat.mean, duration), | ||
sort: (item: PlanHashStats) => item.stats.run_lat.mean, | ||
}, | ||
{ | ||
name: "exec_count", | ||
title: planDetailsTableTitles.exec_count(), | ||
cell: (item: PlanHashStats) => longToInt(item.stats.count), | ||
sort: (item: PlanHashStats) => longToInt(item.stats.count), | ||
}, | ||
{ | ||
name: "avg_rows_read", | ||
title: planDetailsTableTitles.avg_rows_read(), | ||
cell: (item: PlanHashStats) => longToInt(item.stats.rows_read.mean), | ||
sort: (item: PlanHashStats) => longToInt(item.stats.rows_read.mean), | ||
}, | ||
]; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.