Skip to content

Commit

Permalink
Merge #83103
Browse files Browse the repository at this point in the history
83103: ui: add period label to SQL Activity pages r=maryliag a=maryliag

This commit adds the period label with information
about the period to which we're showing information from.
The label is added to Statement, Statement Details,
Transaction and Transaction Details pages.

Partially addresses #82914
Fixes #74523

Statement page no filter
<img width="851" alt="Screen Shot 2022-06-20 at 10 17 23 AM" src="https://user-images.githubusercontent.com/1017486/174626137-729a8351-a32d-46df-a884-a9aeb49a8ace.png">

Statement Page with filter
<img width="883" alt="Screen Shot 2022-06-20 at 10 17 07 AM" src="https://user-images.githubusercontent.com/1017486/174626135-e39be0d4-045c-49bc-b886-4337cb4baf21.png">

Statement Details Overview Tab
<img width="468" alt="Screen Shot 2022-06-20 at 10 18 24 AM" src="https://user-images.githubusercontent.com/1017486/174626138-2b5bae17-f64f-4ddd-a8eb-de0f92f53a3b.png">

Statement Details Explain Tab
<img width="463" alt="Screen Shot 2022-06-20 at 10 18 30 AM" src="https://user-images.githubusercontent.com/1017486/174626141-1e925490-667c-47e9-bc6e-b8227d189c1a.png">

Transaction page no filter
<img width="874" alt="Screen Shot 2022-06-20 at 10 21 24 AM" src="https://user-images.githubusercontent.com/1017486/174626144-10448c80-df40-4b85-bae5-19484fa97752.png">

Transaction page with filter
<img width="756" alt="Screen Shot 2022-06-20 at 10 21 38 AM" src="https://user-images.githubusercontent.com/1017486/174626146-16a0ad7b-7506-4447-8f5e-c29a0d9cde56.png">

Transaction Details
<img width="647" alt="Screen Shot 2022-06-20 at 10 36 51 AM" src="https://user-images.githubusercontent.com/1017486/174626147-de9619c6-b11e-42c7-90b3-57a5bed1f6f6.png">


This commit also removed the tab Exec Stats from the
Statement Details page.

Fixes #74526

Release note (ui change): Add period label to pages Statement, Statement Details, 
Transaction and Transaction Details, with information about the
period to which we're showing information from. Removal of
Exec stats tab under Statement Details page.

Co-authored-by: Marylia Gutierrez <[email protected]>
  • Loading branch information
craig[bot] and maryliag committed Jun 23, 2022
2 parents 9e47dc9 + b68baf5 commit 9cb9bc5
Show file tree
Hide file tree
Showing 9 changed files with 109 additions and 244 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
// it's fixed during scrolling, but not when the page
// is scrolled to the top. This combination of padding
// and negative margins achieves that.
padding-bottom: 10px;
padding-bottom: 5px;
padding-top: 10px;
margin-bottom: -10px;
margin-top: -10px;
Expand Down
259 changes: 22 additions & 237 deletions pkg/ui/workspaces/cluster-ui/src/statementDetails/statementDetails.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@ import { ArrowLeft } from "@cockroachlabs/icons";
import { Location } from "history";
import _ from "lodash";
import Long from "long";
import { format as d3Format } from "d3-format";
import { Helmet } from "react-helmet";
import { Link, RouteComponentProps } from "react-router-dom";
import classNames from "classnames/bind";
Expand All @@ -29,12 +28,7 @@ import { AxisUnits } from "../graphs";
import { AlignedData, Options } from "uplot";

import {
NumericStat,
intersperse,
Bytes,
Duration,
FixLong,
stdDev,
unique,
queryByName,
appAttr,
Expand All @@ -47,13 +41,11 @@ import { Loading } from "src/loading";
import { Button } from "src/button";
import { SqlBox, SqlBoxSize } from "src/sql";
import { SortSetting } from "src/sortedtable";
import { Tooltip } from "@cockroachlabs/ui-components";
import { PlanDetails } from "./planDetails";
import { SummaryCard } from "src/summaryCard";
import { latencyBreakdown, genericBarChart } from "src/barCharts";
import { DiagnosticsView } from "./diagnostics/diagnosticsView";
import sortedTableStyles from "src/sortedtable/sortedtable.module.scss";
import summaryCardStyles from "src/summaryCard/summaryCard.module.scss";
import timeScaleStyles from "src/timeScaleDropdown/timeScale.module.scss";
import styles from "./statementDetails.module.scss";
import { commonStyles } from "src/common";
import { NodeSummaryStats } from "../nodes";
Expand All @@ -62,6 +54,7 @@ import { StatementDetailsRequest } from "src/api/statementsApi";
import {
TimeScale,
TimeScaleDropdown,
timeScaleToString,
toRoundedDateRange,
} from "../timeScaleDropdown";
import SQLActivityError from "../sqlActivity/errorComponent";
Expand Down Expand Up @@ -97,25 +90,6 @@ export interface StatementDetailsState {
currentTab?: string;
}

interface NumericStatRow {
name: string;
value: NumericStat;
bar?: () => ReactNode;
summary?: boolean;
// You can override the table's formatter on a per-row basis with this format
// method.
format?: (v: number) => string;
}

interface NumericStatTableProps {
title?: string;
description?: string;
measure: string;
rows: NumericStatRow[];
count: number;
format?: (v: number) => string;
}

export type NodesSummary = {
nodeStatuses: cockroach.server.status.statuspb.INodeStatus[];
nodeIDs: string[];
Expand Down Expand Up @@ -174,8 +148,8 @@ export type StatementDetailsOwnProps = StatementDetailsDispatchProps &
StatementDetailsStateProps;

const cx = classNames.bind(styles);
const sortableTableCx = classNames.bind(sortedTableStyles);
const summaryCardStylesCx = classNames.bind(summaryCardStyles);
const timeScaleStylesCx = classNames.bind(timeScaleStyles);

function getStatementDetailsRequest(
timeScale: TimeScale,
Expand All @@ -195,7 +169,6 @@ function AppLink(props: { app: string }) {
if (!props.app) {
return <Text className={cx("app-name", "app-name__unset")}>(unset)</Text>;
}

const searchParams = new URLSearchParams({ [appAttr]: props.app });

return (
Expand Down Expand Up @@ -226,87 +199,6 @@ function renderTransactionType(implicitTxn: boolean) {
return "Explicit";
}

class NumericStatTable extends React.Component<NumericStatTableProps> {
static defaultProps = {
format: (v: number) => `${v}`,
};

render() {
const { rows } = this.props;
return (
<table
className={classNames(
sortableTableCx("sort-table"),
cx("statements-table"),
)}
>
<thead>
<tr
className={sortableTableCx(
"sort-table__row",
"sort-table__row--header",
)}
>
<th
className={sortableTableCx(
"sort-table__cell",
"sort-table__cell--header",
)}
>
{this.props.title}
</th>
<th className={sortableTableCx("sort-table__cell")}>
Mean {this.props.measure}
</th>
<th className={sortableTableCx("sort-table__cell")}>
Standard Deviation
</th>
</tr>
</thead>
<tbody>
{rows.map((row: NumericStatRow, idx) => {
let { format } = this.props;
if (row.format) {
format = row.format;
}
const className = sortableTableCx(
"sort-table__row",
"sort-table__row--body",
{
"sort-table__row--summary": row.summary,
},
);
return (
<tr className={className} key={idx}>
<th
className={sortableTableCx(
"sort-table__cell",
"sort-table__cell--header",
)}
style={{ textAlign: "left" }}
>
{row.name}
</th>
<td className={sortableTableCx("sort-table__cell")}>
{row.bar ? row.bar() : null}
</td>
<td
className={sortableTableCx(
"sort-table__cell",
"sort-table__cell--active",
)}
>
{format(stdDev(row.value, this.props.count))}
</td>
</tr>
);
})}
</tbody>
</table>
);
}
}

export class StatementDetails extends React.Component<
StatementDetailsProps,
StatementDetailsState
Expand Down Expand Up @@ -496,8 +388,8 @@ export class StatementDetails extends React.Component<
renderTabs = (): React.ReactElement => {
const { currentTab } = this.state;
const { stats } = this.props.statementDetails.statement;

const hasData = Number(stats.count) > 0;
const period = timeScaleToString(this.props.timeScale);

return (
<Tabs
Expand All @@ -507,10 +399,10 @@ export class StatementDetails extends React.Component<
activeKey={currentTab}
>
<TabPane tab="Overview" key="overview">
{this.renderOverviewTabContent(hasData)}
{this.renderOverviewTabContent(hasData, period)}
</TabPane>
<TabPane tab="Explain Plans" key="explain-plan">
{this.renderExplainPlanTabContent(hasData)}
{this.renderExplainPlanTabContent(hasData, period)}
</TabPane>
{!this.props.isTenant && !this.props.hasViewActivityRedactedRole && (
<TabPane
Expand All @@ -524,13 +416,6 @@ export class StatementDetails extends React.Component<
{this.renderDiagnosticsTabContent(hasData)}
</TabPane>
)}
<TabPane
tab="Execution Stats"
key="execution-stats"
className={cx("fit-content-width")}
>
{this.renderExecutionStatsTabContent(hasData)}
</TabPane>
</Tabs>
);
};
Expand Down Expand Up @@ -570,7 +455,10 @@ export class StatementDetails extends React.Component<
</>
);

renderOverviewTabContent = (hasData: boolean): React.ReactElement => {
renderOverviewTabContent = (
hasData: boolean,
period: string,
): React.ReactElement => {
if (!hasData) {
return this.renderNoDataWithTimeScaleAndSqlBoxTabContent();
}
Expand Down Expand Up @@ -676,6 +564,10 @@ export class StatementDetails extends React.Component<
/>
</PageConfigItem>
</PageConfig>
<p className={timeScaleStylesCx("time-label", "label-margin")}>
Showing aggregated stats from{" "}
<span className={timeScaleStylesCx("bold")}>{period}</span>
</p>
<section className={cx("section")}>
<Row gutter={24}>
<Col className="gutter-row" span={24}>
Expand Down Expand Up @@ -798,7 +690,10 @@ export class StatementDetails extends React.Component<
);
};

renderExplainPlanTabContent = (hasData: boolean): React.ReactElement => {
renderExplainPlanTabContent = (
hasData: boolean,
period: string,
): React.ReactElement => {
if (!hasData) {
return this.renderNoDataWithTimeScaleAndSqlBoxTabContent();
}
Expand All @@ -814,6 +709,10 @@ export class StatementDetails extends React.Component<
/>
</PageConfigItem>
</PageConfig>
<p className={timeScaleStylesCx("time-label", "label-margin")}>
Showing explain plans from{" "}
<span className={timeScaleStylesCx("bold")}>{period}</span>
</p>
<section className={cx("section")}>
<Row gutter={24}>
<Col className="gutter-row" span={24}>
Expand Down Expand Up @@ -848,118 +747,4 @@ export class StatementDetails extends React.Component<
/>
);
};

renderExecutionStatsTabContent = (hasData: boolean): React.ReactElement => {
if (!hasData) {
return this.renderNoDataTabContent();
}
const { stats } = this.props.statementDetails.statement;

const count = FixLong(stats.count).toInt();
const { statement } = this.props.statementDetails;
const {
parseBarChart,
planBarChart,
runBarChart,
overheadBarChart,
overallBarChart,
} = latencyBreakdown(statement);
return (
<>
<SummaryCard>
<h3
className={classNames(
commonStyles("base-heading"),
summaryCardStylesCx("summary--card__title"),
)}
>
Execution Latency By Phase
<div className={cx("numeric-stats-table__tooltip")}>
<Tooltip content="The execution latency of this statement, broken down by phase.">
<div className={cx("numeric-stats-table__tooltip-hover-area")}>
<div className={cx("numeric-stats-table__info-icon")}>i</div>
</div>
</Tooltip>
</div>
</h3>
<NumericStatTable
title="Phase"
measure="Latency"
count={count}
format={(v: number) => Duration(v * 1e9)}
rows={[
{ name: "Parse", value: stats.parse_lat, bar: parseBarChart },
{ name: "Plan", value: stats.plan_lat, bar: planBarChart },
{ name: "Run", value: stats.run_lat, bar: runBarChart },
{
name: "Overhead",
value: stats.overhead_lat,
bar: overheadBarChart,
},
{
name: "Overall",
summary: true,
value: stats.service_lat,
bar: overallBarChart,
},
]}
/>
</SummaryCard>
<SummaryCard>
<h3
className={classNames(
commonStyles("base-heading"),
summaryCardStylesCx("summary--card__title"),
)}
>
Other Execution Statistics
</h3>
<NumericStatTable
title="Stat"
measure="Quantity"
count={count}
format={d3Format(".2f")}
rows={[
{
name: "Rows Read",
value: stats.rows_read,
bar: genericBarChart(stats.rows_read, stats.count),
},
{
name: "Disk Bytes Read",
value: stats.bytes_read,
bar: genericBarChart(stats.bytes_read, stats.count, Bytes),
format: Bytes,
},
{
name: "Rows Written",
value: stats.rows_written,
bar: genericBarChart(stats.rows_written, stats.count),
},
{
name: "Network Bytes Sent",
value: stats.exec_stats.network_bytes,
bar: genericBarChart(
stats.exec_stats.network_bytes,
stats.exec_stats.count,
Bytes,
),
format: Bytes,
},
].filter(function (r) {
if (
r.name === "Network Bytes Sent" &&
r.value &&
r.value.mean === 0
) {
// Omit if empty.
return false;
}
return r.value;
})}
/>
</SummaryCard>
</>
);
};
}
Loading

0 comments on commit 9cb9bc5

Please sign in to comment.