Skip to content

Commit

Permalink
ui: link insights to fingerprint details
Browse files Browse the repository at this point in the history
Now from the Insights page, clicking on the statement
or fingerprint ids, it will bring you to their respective
details page.

This commit also filter out transaction insights that didn't
have their value set yet (meaning they're still 0).

Finally, this commit fixes the start/end values being passed
to the combined statement endpoint, to the correct rounded
values, aligning what we say on the UI.

Fixes cockroachdb#87750

Release note (ui change): The fingerprint id values
for statement and transactions on the insights pages are
links that open the respective details page on the time period
of the execution of that statement/transaction.

Release note (bug fix): Sendind the proper start/end values
to the endpoint used on SQL Activity page, now returning the
full hour as described on the UI.
  • Loading branch information
maryliag committed Oct 21, 2022
1 parent 1ef7748 commit f5d1b8e
Show file tree
Hide file tree
Showing 24 changed files with 238 additions and 42 deletions.
4 changes: 4 additions & 0 deletions pkg/ui/workspaces/cluster-ui/src/api/insightsApi.ts
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,7 @@ const txnContentionQuery = `SELECT *
max(collection_ts) AS collection_ts,
sum(contention_duration) AS total_contention_duration
FROM crdb_internal.transaction_contention_events tce
WHERE waiting_txn_fingerprint_id != '\x0000000000000000'
GROUP BY waiting_txn_id, waiting_txn_fingerprint_id),
(SELECT txn_id FROM crdb_internal.cluster_execution_insights)
WHERE total_contention_duration > threshold
Expand Down Expand Up @@ -572,6 +573,7 @@ type ExecutionInsightsResponseRow = {
session_id: string;
txn_id: string;
txn_fingerprint_id: string; // hex string
implicit_txn: boolean;
stmt_id: string;
stmt_fingerprint_id: string; // hex string
query: string;
Expand Down Expand Up @@ -610,6 +612,7 @@ function getStatementInsightsFromClusterExecutionInsightsResponse(
return {
transactionID: row.txn_id,
transactionFingerprintID: row.txn_fingerprint_id,
implicitTxn: row.implicit_txn,
query: row.query,
startTime: start,
endTime: end,
Expand Down Expand Up @@ -653,6 +656,7 @@ const statementInsightsQuery: InsightQuery<
session_id,
txn_id,
encode(txn_fingerprint_id, 'hex') AS txn_fingerprint_id,
implicit_txn,
stmt_id,
encode(stmt_fingerprint_id, 'hex') AS stmt_fingerprint_id,
query AS non_prettified_query,
Expand Down
1 change: 1 addition & 0 deletions pkg/ui/workspaces/cluster-ui/src/insights/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,7 @@ export type StatementInsightEvent = {
transactionID: string;
statementFingerprintID: string;
transactionFingerprintID: string;
implicitTxn: boolean;
startTime: Moment;
elapsedTimeMillis: number;
sessionID: string;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ import classNames from "classnames/bind";
import { commonStyles } from "src/common";
import { getExplainPlanFromGist } from "src/api/decodePlanGistApi";
import { StatementInsightDetailsOverviewTab } from "./statementInsightDetailsOverviewTab";
import { TimeScale } from "../../timeScaleDropdown";

// Styles
import insightsDetailsStyles from "src/insights/workloadInsightDetails/insightsDetails.module.scss";
Expand All @@ -42,12 +43,24 @@ export interface StatementInsightDetailsStateProps {
isTenant?: boolean;
}

export interface StatementInsightDetailsDispatchProps {
setTimeScale: (ts: TimeScale) => void;
}

export type StatementInsightDetailsProps = StatementInsightDetailsStateProps &
StatementInsightDetailsDispatchProps &
RouteComponentProps<unknown>;

export const StatementInsightDetails: React.FC<
StatementInsightDetailsProps
> = ({ history, insightEventDetails, insightError, match, isTenant }) => {
> = ({
history,
insightEventDetails,
insightError,
match,
isTenant,
setTimeScale,
}) => {
const [explain, setExplain] = useState<string>(null);

const prevPage = (): void => history.goBack();
Expand Down Expand Up @@ -111,6 +124,7 @@ export const StatementInsightDetails: React.FC<
<Tabs.TabPane tab="Overview" key={TabKeysEnum.OVERVIEW}>
<StatementInsightDetailsOverviewTab
insightEventDetails={insightEventDetails}
setTimeScale={setTimeScale}
/>
</Tabs.TabPane>
{!isTenant && (
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,11 @@
// by the Apache License, Version 2.0, included in the file
// licenses/APL.txt.
import { connect } from "react-redux";
import { Dispatch } from "redux";
import { RouteComponentProps, withRouter } from "react-router-dom";
import {
StatementInsightDetails,
StatementInsightDetailsDispatchProps,
StatementInsightDetailsStateProps,
} from "./statementInsightDetails";
import { AppState } from "src/store";
Expand All @@ -19,6 +21,8 @@ import {
selectStatementInsightsError,
} from "src/store/insights/statementInsights";
import { selectIsTenant } from "src/store/uiConfig";
import { TimeScale } from "../../timeScaleDropdown";
import { actions as sqlStatsActions } from "../../store/sqlStats";

const mapStateToProps = (
state: AppState,
Expand All @@ -33,8 +37,25 @@ const mapStateToProps = (
};
};

const mapDispatchToProps = (
dispatch: Dispatch,
): StatementInsightDetailsDispatchProps => ({
setTimeScale: (ts: TimeScale) => {
dispatch(
sqlStatsActions.updateTimeScale({
ts: ts,
}),
);
},
});

export const StatementInsightDetailsConnected = withRouter(
connect<StatementInsightDetailsStateProps, RouteComponentProps>(
connect<
StatementInsightDetailsStateProps,
StatementInsightDetailsDispatchProps,
RouteComponentProps
>(
mapStateToProps,
mapDispatchToProps,
)(StatementInsightDetails),
);
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,8 @@ import summaryCardStyles from "src/summaryCard/summaryCard.module.scss";
import insightTableStyles from "src/insightsTable/insightsTable.module.scss";
import "antd/lib/col/style";
import "antd/lib/row/style";
import { StatementDetailsLink } from "../workloadInsights/util";
import { TimeScale } from "../../timeScaleDropdown";

const cx = classNames.bind(insightsDetailsStyles);
const tableCx = classNames.bind(insightTableStyles);
Expand Down Expand Up @@ -114,11 +116,12 @@ const insightsTableData = (

export interface StatementInsightDetailsOverviewTabProps {
insightEventDetails: StatementInsightEvent;
setTimeScale: (ts: TimeScale) => void;
}

export const StatementInsightDetailsOverviewTab: React.FC<
StatementInsightDetailsOverviewTabProps
> = ({ insightEventDetails }) => {
> = ({ insightEventDetails, setTimeScale }) => {
const isCockroachCloud = useContext(CockroachCloudContext);

const insightsColumns = useMemo(
Expand Down Expand Up @@ -195,7 +198,7 @@ export const StatementInsightDetailsOverviewTab: React.FC<
/>
<SummaryCardItem
label="Statement Fingerprint ID"
value={String(insightDetails.statementFingerprintID)}
value={StatementDetailsLink(insightDetails, setTimeScale)}
/>
</SummaryCard>
</Col>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,8 @@ import { commonStyles } from "src/common";
import insightTableStyles from "src/insightsTable/insightsTable.module.scss";
import { CockroachCloudContext } from "../../contexts";
import { InsightsError } from "../insightsErrorComponent";
import { TransactionDetailsLink } from "../workloadInsights/util";
import { TimeScale } from "../../timeScaleDropdown";

const tableCx = classNames.bind(insightTableStyles);

Expand All @@ -55,6 +57,7 @@ export interface TransactionInsightDetailsDispatchProps {
refreshTransactionInsightDetails: (
req: TransactionInsightEventDetailsRequest,
) => void;
setTimeScale: (ts: TimeScale) => void;
}

export type TransactionInsightDetailsProps =
Expand Down Expand Up @@ -152,7 +155,11 @@ export class TransactionInsightDetails extends React.Component<TransactionInsigh
<SummaryCard>
<SummaryCardItem
label="Transaction Fingerprint ID"
value={String(insightDetails.fingerprintID)}
value={TransactionDetailsLink(
insightDetails.fingerprintID,
insightDetails.startTime,
this.props.setTimeScale,
)}
/>
</SummaryCard>
</Col>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,9 @@ import {
selectTransactionInsightDetailsError,
actions,
} from "src/store/insightDetails/transactionInsightDetails";
import { TimeScale } from "../../timeScaleDropdown";
import { actions as sqlStatsActions } from "../../store/sqlStats";
import { Dispatch } from "redux";

const mapStateToProps = (
state: AppState,
Expand All @@ -33,9 +36,18 @@ const mapStateToProps = (
};
};

const mapDispatchToProps = {
const mapDispatchToProps = (
dispatch: Dispatch,
): TransactionInsightDetailsDispatchProps => ({
refreshTransactionInsightDetails: actions.refresh,
};
setTimeScale: (ts: TimeScale) => {
dispatch(
sqlStatsActions.updateTimeScale({
ts: ts,
}),
);
},
});

export const TransactionInsightDetailsConnected = withRouter(
connect<
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ export const statementInsightsPropsFixture: StatementInsightsViewProps = {
statementFingerprintID: "abc",
transactionFingerprintID: "defg",
transactionID: "f72f37ea-b3a0-451f-80b8-dfb27d0bc2a5",
implicitTxn: true,
query:
"SELECT IFNULL(a, b) FROM (SELECT (SELECT code FROM promo_codes WHERE code > $1 ORDER BY code LIMIT _) AS a, (SELECT code FROM promo_codes ORDER BY code LIMIT _) AS b)",
startTime: moment.utc("2022.08.10"),
Expand Down Expand Up @@ -47,6 +48,7 @@ export const statementInsightsPropsFixture: StatementInsightsViewProps = {
statementFingerprintID: "938x3",
transactionFingerprintID: "1971x3",
transactionID: "e72f37ea-b3a0-451f-80b8-dfb27d0bc2a5",
implicitTxn: true,
query: "INSERT INTO vehicles VALUES ($1, $2, __more1_10__)",
startTime: moment.utc("2022.08.10"),
endTime: moment.utc("2022.08.10 00:00:00.25"),
Expand All @@ -73,6 +75,7 @@ export const statementInsightsPropsFixture: StatementInsightsViewProps = {
statementFingerprintID: "hisas",
transactionFingerprintID: "3anc",
transactionID: "f72f37ea-b3a0-451f-80b8-dfb27d0bc2a0",
implicitTxn: true,
query:
"UPSERT INTO vehicle_location_histories VALUES ($1, $2, now(), $3, $4)",
startTime: moment.utc("2022.08.10"),
Expand Down Expand Up @@ -107,4 +110,5 @@ export const statementInsightsPropsFixture: StatementInsightsViewProps = {
refreshStatementInsights: () => {},
onSortChange: () => {},
onFiltersChange: () => {},
setTimeScale: () => {},
};
Original file line number Diff line number Diff line change
Expand Up @@ -17,12 +17,17 @@ import {
} from "src/sortedtable";
import { Count, DATE_FORMAT, Duration, limitText } from "src/util";
import { InsightExecEnum, StatementInsightEvent } from "src/insights";
import { InsightCell, insightsTableTitles } from "../util";
import {
InsightCell,
insightsTableTitles,
StatementDetailsLink,
} from "../util";
import { StatementInsights } from "../../../api";
import { Tooltip } from "@cockroachlabs/ui-components";
import { Link } from "react-router-dom";
import classNames from "classnames/bind";
import styles from "../util/workloadInsights.module.scss";
import { TimeScale } from "../../../timeScaleDropdown";

const cx = classNames.bind(styles);

Expand All @@ -35,7 +40,9 @@ interface StatementInsightsTable {
visibleColumns: ColumnDescriptor<StatementInsightEvent>[];
}

export function makeStatementInsightsColumns(): ColumnDescriptor<StatementInsightEvent>[] {
export function makeStatementInsightsColumns(
setTimeScale: (ts: TimeScale) => void,
): ColumnDescriptor<StatementInsightEvent>[] {
const execType = InsightExecEnum.STATEMENT;
return [
{
Expand All @@ -52,7 +59,8 @@ export function makeStatementInsightsColumns(): ColumnDescriptor<StatementInsigh
{
name: "statementFingerprintID",
title: insightsTableTitles.fingerprintID(execType),
cell: (item: StatementInsightEvent) => item.statementFingerprintID,
cell: (item: StatementInsightEvent) =>
StatementDetailsLink(item, setTimeScale),
sort: (item: StatementInsightEvent) => item.statementFingerprintID,
showByDefault: true,
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,6 @@ import { PageConfig, PageConfigItem } from "src/pageConfig/pageConfig";
import { Search } from "src/search/search";
import {
calculateActiveFilters,
defaultFilters,
Filter,
getFullFiltersAsStringRecord,
} from "src/queryFilter/filter";
Expand All @@ -48,6 +47,7 @@ import styles from "src/statementsPage/statementsPage.module.scss";
import sortableTableStyles from "src/sortedtable/sortedtable.module.scss";
import ColumnsSelector from "../../../columnsSelector/columnsSelector";
import { SelectOption } from "../../../multiSelectCheckbox/multiSelectCheckbox";
import { TimeScale } from "../../../timeScaleDropdown";

const cx = classNames.bind(styles);
const sortableTableCx = classNames.bind(sortableTableStyles);
Expand All @@ -66,6 +66,7 @@ export type StatementInsightsViewDispatchProps = {
onSortChange: (ss: SortSetting) => void;
refreshStatementInsights: () => void;
onColumnsChange: (selectedColumns: string[]) => void;
setTimeScale: (ts: TimeScale) => void;
};

export type StatementInsightsViewProps = StatementInsightsViewStateProps &
Expand Down Expand Up @@ -101,6 +102,7 @@ export const StatementInsightsView: React.FC<StatementInsightsViewProps> = (
onFiltersChange,
onSortChange,
onColumnsChange,
setTimeScale,
selectedColumnNames,
dropDownSelect,
} = props;
Expand Down Expand Up @@ -194,7 +196,7 @@ export const StatementInsightsView: React.FC<StatementInsightsViewProps> = (
resetPagination();
};

const defaultColumns = makeStatementInsightsColumns();
const defaultColumns = makeStatementInsightsColumns(setTimeScale);

const visibleColumns = defaultColumns.filter(x =>
isSelected(x, selectedColumnNames),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -66,4 +66,5 @@ export const transactionInsightsPropsFixture: TransactionInsightsViewProps = {
refreshTransactionInsights: () => {},
onSortChange: () => {},
onFiltersChange: () => {},
setTimeScale: () => {},
};
Original file line number Diff line number Diff line change
Expand Up @@ -17,18 +17,27 @@ import {
} from "src/sortedtable";
import { DATE_FORMAT, Duration } from "src/util";
import { InsightExecEnum, TransactionInsightEvent } from "src/insights";
import { InsightCell, insightsTableTitles, QueriesCell } from "../util";
import {
InsightCell,
insightsTableTitles,
QueriesCell,
TransactionDetailsLink,
} from "../util";
import { Link } from "react-router-dom";
import { TimeScale } from "../../../timeScaleDropdown";

interface TransactionInsightsTable {
data: TransactionInsightEvent[];
sortSetting: SortSetting;
onChangeSortSetting: (ss: SortSetting) => void;
pagination: ISortedTablePagination;
renderNoResult?: React.ReactNode;
setTimeScale: (ts: TimeScale) => void;
}

export function makeTransactionInsightsColumns(): ColumnDescriptor<TransactionInsightEvent>[] {
export function makeTransactionInsightsColumns(
setTimeScale: (ts: TimeScale) => void,
): ColumnDescriptor<TransactionInsightEvent>[] {
const execType = InsightExecEnum.TRANSACTION;
return [
{
Expand All @@ -44,7 +53,12 @@ export function makeTransactionInsightsColumns(): ColumnDescriptor<TransactionIn
{
name: "fingerprintID",
title: insightsTableTitles.fingerprintID(execType),
cell: (item: TransactionInsightEvent) => String(item.fingerprintID),
cell: (item: TransactionInsightEvent) =>
TransactionDetailsLink(
item.fingerprintID,
item.startTime,
setTimeScale,
),
sort: (item: TransactionInsightEvent) => item.fingerprintID,
},
{
Expand Down Expand Up @@ -90,7 +104,7 @@ export function makeTransactionInsightsColumns(): ColumnDescriptor<TransactionIn
export const TransactionInsightsTable: React.FC<
TransactionInsightsTable
> = props => {
const columns = makeTransactionInsightsColumns();
const columns = makeTransactionInsightsColumns(props.setTimeScale);
return (
<SortedTable columns={columns} className="statements-table" {...props} />
);
Expand Down
Loading

0 comments on commit f5d1b8e

Please sign in to comment.