diff --git a/pkg/ui/workspaces/cluster-ui/src/api/insightsApi.ts b/pkg/ui/workspaces/cluster-ui/src/api/insightsApi.ts index f6a34c4f9db4..07f174aa23fb 100644 --- a/pkg/ui/workspaces/cluster-ui/src/api/insightsApi.ts +++ b/pkg/ui/workspaces/cluster-ui/src/api/insightsApi.ts @@ -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 @@ -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; @@ -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, @@ -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, diff --git a/pkg/ui/workspaces/cluster-ui/src/insights/types.ts b/pkg/ui/workspaces/cluster-ui/src/insights/types.ts index c9a39b797fb4..a1b8add48b3d 100644 --- a/pkg/ui/workspaces/cluster-ui/src/insights/types.ts +++ b/pkg/ui/workspaces/cluster-ui/src/insights/types.ts @@ -70,6 +70,7 @@ export type StatementInsightEvent = { transactionID: string; statementFingerprintID: string; transactionFingerprintID: string; + implicitTxn: boolean; startTime: Moment; elapsedTimeMillis: number; sessionID: string; diff --git a/pkg/ui/workspaces/cluster-ui/src/insights/workloadInsightDetails/statementInsightDetails.tsx b/pkg/ui/workspaces/cluster-ui/src/insights/workloadInsightDetails/statementInsightDetails.tsx index 5b65f4c5dadc..28e171499f9c 100644 --- a/pkg/ui/workspaces/cluster-ui/src/insights/workloadInsightDetails/statementInsightDetails.tsx +++ b/pkg/ui/workspaces/cluster-ui/src/insights/workloadInsightDetails/statementInsightDetails.tsx @@ -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"; @@ -42,12 +43,24 @@ export interface StatementInsightDetailsStateProps { isTenant?: boolean; } +export interface StatementInsightDetailsDispatchProps { + setTimeScale: (ts: TimeScale) => void; +} + export type StatementInsightDetailsProps = StatementInsightDetailsStateProps & + StatementInsightDetailsDispatchProps & RouteComponentProps; export const StatementInsightDetails: React.FC< StatementInsightDetailsProps -> = ({ history, insightEventDetails, insightError, match, isTenant }) => { +> = ({ + history, + insightEventDetails, + insightError, + match, + isTenant, + setTimeScale, +}) => { const [explain, setExplain] = useState(null); const prevPage = (): void => history.goBack(); @@ -111,6 +124,7 @@ export const StatementInsightDetails: React.FC< {!isTenant && ( diff --git a/pkg/ui/workspaces/cluster-ui/src/insights/workloadInsightDetails/statementInsightDetailsConnected.tsx b/pkg/ui/workspaces/cluster-ui/src/insights/workloadInsightDetails/statementInsightDetailsConnected.tsx index da772b1f5fc3..fafa4989c308 100644 --- a/pkg/ui/workspaces/cluster-ui/src/insights/workloadInsightDetails/statementInsightDetailsConnected.tsx +++ b/pkg/ui/workspaces/cluster-ui/src/insights/workloadInsightDetails/statementInsightDetailsConnected.tsx @@ -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"; @@ -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, @@ -33,8 +37,25 @@ const mapStateToProps = ( }; }; +const mapDispatchToProps = ( + dispatch: Dispatch, +): StatementInsightDetailsDispatchProps => ({ + setTimeScale: (ts: TimeScale) => { + dispatch( + sqlStatsActions.updateTimeScale({ + ts: ts, + }), + ); + }, +}); + export const StatementInsightDetailsConnected = withRouter( - connect( + connect< + StatementInsightDetailsStateProps, + StatementInsightDetailsDispatchProps, + RouteComponentProps + >( mapStateToProps, + mapDispatchToProps, )(StatementInsightDetails), ); diff --git a/pkg/ui/workspaces/cluster-ui/src/insights/workloadInsightDetails/statementInsightDetailsOverviewTab.tsx b/pkg/ui/workspaces/cluster-ui/src/insights/workloadInsightDetails/statementInsightDetailsOverviewTab.tsx index 24e6bf6d5d97..f0d381cb4abd 100644 --- a/pkg/ui/workspaces/cluster-ui/src/insights/workloadInsightDetails/statementInsightDetailsOverviewTab.tsx +++ b/pkg/ui/workspaces/cluster-ui/src/insights/workloadInsightDetails/statementInsightDetailsOverviewTab.tsx @@ -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); @@ -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( @@ -195,7 +198,7 @@ export const StatementInsightDetailsOverviewTab: React.FC< /> diff --git a/pkg/ui/workspaces/cluster-ui/src/insights/workloadInsightDetails/transactionInsightDetails.tsx b/pkg/ui/workspaces/cluster-ui/src/insights/workloadInsightDetails/transactionInsightDetails.tsx index 8e2394b913c1..174e0df65ea1 100644 --- a/pkg/ui/workspaces/cluster-ui/src/insights/workloadInsightDetails/transactionInsightDetails.tsx +++ b/pkg/ui/workspaces/cluster-ui/src/insights/workloadInsightDetails/transactionInsightDetails.tsx @@ -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); @@ -55,6 +57,7 @@ export interface TransactionInsightDetailsDispatchProps { refreshTransactionInsightDetails: ( req: TransactionInsightEventDetailsRequest, ) => void; + setTimeScale: (ts: TimeScale) => void; } export type TransactionInsightDetailsProps = @@ -152,7 +155,11 @@ export class TransactionInsightDetails extends React.Component diff --git a/pkg/ui/workspaces/cluster-ui/src/insights/workloadInsightDetails/transactionInsightDetailsConnected.tsx b/pkg/ui/workspaces/cluster-ui/src/insights/workloadInsightDetails/transactionInsightDetailsConnected.tsx index bb5aa21caa91..3b5d4e14f6f7 100644 --- a/pkg/ui/workspaces/cluster-ui/src/insights/workloadInsightDetails/transactionInsightDetailsConnected.tsx +++ b/pkg/ui/workspaces/cluster-ui/src/insights/workloadInsightDetails/transactionInsightDetailsConnected.tsx @@ -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, @@ -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< diff --git a/pkg/ui/workspaces/cluster-ui/src/insights/workloadInsights/statementInsights/statementInsights.fixture.ts b/pkg/ui/workspaces/cluster-ui/src/insights/workloadInsights/statementInsights/statementInsights.fixture.ts index c02e3194467b..8bd4e7f708c1 100644 --- a/pkg/ui/workspaces/cluster-ui/src/insights/workloadInsights/statementInsights/statementInsights.fixture.ts +++ b/pkg/ui/workspaces/cluster-ui/src/insights/workloadInsights/statementInsights/statementInsights.fixture.ts @@ -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"), @@ -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"), @@ -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"), @@ -107,4 +110,5 @@ export const statementInsightsPropsFixture: StatementInsightsViewProps = { refreshStatementInsights: () => {}, onSortChange: () => {}, onFiltersChange: () => {}, + setTimeScale: () => {}, }; diff --git a/pkg/ui/workspaces/cluster-ui/src/insights/workloadInsights/statementInsights/statementInsightsTable.tsx b/pkg/ui/workspaces/cluster-ui/src/insights/workloadInsights/statementInsights/statementInsightsTable.tsx index 8a4cc81da334..fab052e60fdf 100644 --- a/pkg/ui/workspaces/cluster-ui/src/insights/workloadInsights/statementInsights/statementInsightsTable.tsx +++ b/pkg/ui/workspaces/cluster-ui/src/insights/workloadInsights/statementInsights/statementInsightsTable.tsx @@ -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); @@ -35,7 +40,9 @@ interface StatementInsightsTable { visibleColumns: ColumnDescriptor[]; } -export function makeStatementInsightsColumns(): ColumnDescriptor[] { +export function makeStatementInsightsColumns( + setTimeScale: (ts: TimeScale) => void, +): ColumnDescriptor[] { const execType = InsightExecEnum.STATEMENT; return [ { @@ -52,7 +59,8 @@ export function makeStatementInsightsColumns(): ColumnDescriptor item.statementFingerprintID, + cell: (item: StatementInsightEvent) => + StatementDetailsLink(item, setTimeScale), sort: (item: StatementInsightEvent) => item.statementFingerprintID, showByDefault: true, }, diff --git a/pkg/ui/workspaces/cluster-ui/src/insights/workloadInsights/statementInsights/statementInsightsView.tsx b/pkg/ui/workspaces/cluster-ui/src/insights/workloadInsights/statementInsights/statementInsightsView.tsx index 161405f53cfc..d680483e9a79 100644 --- a/pkg/ui/workspaces/cluster-ui/src/insights/workloadInsights/statementInsights/statementInsightsView.tsx +++ b/pkg/ui/workspaces/cluster-ui/src/insights/workloadInsights/statementInsights/statementInsightsView.tsx @@ -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"; @@ -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); @@ -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 & @@ -101,6 +102,7 @@ export const StatementInsightsView: React.FC = ( onFiltersChange, onSortChange, onColumnsChange, + setTimeScale, selectedColumnNames, dropDownSelect, } = props; @@ -194,7 +196,7 @@ export const StatementInsightsView: React.FC = ( resetPagination(); }; - const defaultColumns = makeStatementInsightsColumns(); + const defaultColumns = makeStatementInsightsColumns(setTimeScale); const visibleColumns = defaultColumns.filter(x => isSelected(x, selectedColumnNames), diff --git a/pkg/ui/workspaces/cluster-ui/src/insights/workloadInsights/transactionInsights/transactionInsights.fixture.ts b/pkg/ui/workspaces/cluster-ui/src/insights/workloadInsights/transactionInsights/transactionInsights.fixture.ts index 72270f546623..005fb7681615 100644 --- a/pkg/ui/workspaces/cluster-ui/src/insights/workloadInsights/transactionInsights/transactionInsights.fixture.ts +++ b/pkg/ui/workspaces/cluster-ui/src/insights/workloadInsights/transactionInsights/transactionInsights.fixture.ts @@ -66,4 +66,5 @@ export const transactionInsightsPropsFixture: TransactionInsightsViewProps = { refreshTransactionInsights: () => {}, onSortChange: () => {}, onFiltersChange: () => {}, + setTimeScale: () => {}, }; diff --git a/pkg/ui/workspaces/cluster-ui/src/insights/workloadInsights/transactionInsights/transactionInsightsTable.tsx b/pkg/ui/workspaces/cluster-ui/src/insights/workloadInsights/transactionInsights/transactionInsightsTable.tsx index 5a5776405746..4a402c54d859 100644 --- a/pkg/ui/workspaces/cluster-ui/src/insights/workloadInsights/transactionInsights/transactionInsightsTable.tsx +++ b/pkg/ui/workspaces/cluster-ui/src/insights/workloadInsights/transactionInsights/transactionInsightsTable.tsx @@ -17,8 +17,14 @@ 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[]; @@ -26,9 +32,12 @@ interface TransactionInsightsTable { onChangeSortSetting: (ss: SortSetting) => void; pagination: ISortedTablePagination; renderNoResult?: React.ReactNode; + setTimeScale: (ts: TimeScale) => void; } -export function makeTransactionInsightsColumns(): ColumnDescriptor[] { +export function makeTransactionInsightsColumns( + setTimeScale: (ts: TimeScale) => void, +): ColumnDescriptor[] { const execType = InsightExecEnum.TRANSACTION; return [ { @@ -44,7 +53,12 @@ export function makeTransactionInsightsColumns(): ColumnDescriptor String(item.fingerprintID), + cell: (item: TransactionInsightEvent) => + TransactionDetailsLink( + item.fingerprintID, + item.startTime, + setTimeScale, + ), sort: (item: TransactionInsightEvent) => item.fingerprintID, }, { @@ -90,7 +104,7 @@ export function makeTransactionInsightsColumns(): ColumnDescriptor = props => { - const columns = makeTransactionInsightsColumns(); + const columns = makeTransactionInsightsColumns(props.setTimeScale); return ( ); diff --git a/pkg/ui/workspaces/cluster-ui/src/insights/workloadInsights/transactionInsights/transactionInsightsView.tsx b/pkg/ui/workspaces/cluster-ui/src/insights/workloadInsights/transactionInsights/transactionInsightsView.tsx index 7bc1fc06af8e..5783046556bb 100644 --- a/pkg/ui/workspaces/cluster-ui/src/insights/workloadInsights/transactionInsights/transactionInsightsView.tsx +++ b/pkg/ui/workspaces/cluster-ui/src/insights/workloadInsights/transactionInsights/transactionInsightsView.tsx @@ -20,7 +20,6 @@ import { PageConfig, PageConfigItem } from "src/pageConfig/pageConfig"; import { Search } from "src/search/search"; import { calculateActiveFilters, - defaultFilters, Filter, getFullFiltersAsStringRecord, } from "src/queryFilter/filter"; @@ -43,6 +42,7 @@ import { InsightsError } from "../../insightsErrorComponent"; import styles from "src/statementsPage/statementsPage.module.scss"; import sortableTableStyles from "src/sortedtable/sortedtable.module.scss"; +import { TimeScale } from "../../../timeScaleDropdown"; const cx = classNames.bind(styles); const sortableTableCx = classNames.bind(sortableTableStyles); @@ -59,6 +59,7 @@ export type TransactionInsightsViewDispatchProps = { onFiltersChange: (filters: WorkloadInsightEventFilters) => void; onSortChange: (ss: SortSetting) => void; refreshTransactionInsights: () => void; + setTimeScale: (ts: TimeScale) => void; }; export type TransactionInsightsViewProps = TransactionInsightsViewStateProps & @@ -78,6 +79,7 @@ export const TransactionInsightsView: React.FC = ( refreshTransactionInsights, onFiltersChange, onSortChange, + setTimeScale, dropDownSelect, } = props; @@ -232,6 +234,7 @@ export const TransactionInsightsView: React.FC = ( data={filteredTransactions} sortSetting={sortSetting} onChangeSortSetting={onChangeSortSetting} + setTimeScale={setTimeScale} renderNoResult={ void, +): React.ReactElement { + const txnID = HexStringToInt64String(transactionFingerprintID); + const path = `/transaction/${txnID}`; + const timeScale: TimeScale = { + windowSize: moment.duration(65, "minutes"), + fixedWindowEnd: startTime.add(1, "hour"), + sampleSize: moment.duration(1, "hour"), + key: "Custom", + }; + return ( + setTimeScale(timeScale)}> +
{String(transactionFingerprintID)}
+ + ); +} + +export function StatementDetailsLink( + insightDetails: StatementInsightEvent, + setTimeScale: (tw: TimeScale) => void, +): React.ReactElement { + const linkProps = { + statementFingerprintID: HexStringToInt64String( + insightDetails.statementFingerprintID, + ), + appNames: [insightDetails.application], + implicitTxn: insightDetails.implicitTxn, + }; + const timeScale: TimeScale = { + windowSize: moment.duration(insightDetails.elapsedTimeMillis), + fixedWindowEnd: insightDetails.endTime, + sampleSize: moment.duration(1, "hour"), + key: "Custom", + }; + + return ( + setTimeScale(timeScale)} + > +
{String(insightDetails.statementFingerprintID)}
+ + ); +} diff --git a/pkg/ui/workspaces/cluster-ui/src/insights/workloadInsights/util/index.ts b/pkg/ui/workspaces/cluster-ui/src/insights/workloadInsights/util/index.ts index 67f1409e71c9..e7804d1d751d 100644 --- a/pkg/ui/workspaces/cluster-ui/src/insights/workloadInsights/util/index.ts +++ b/pkg/ui/workspaces/cluster-ui/src/insights/workloadInsights/util/index.ts @@ -13,3 +13,4 @@ export * from "./queriesCell"; export * from "./emptyInsightsTablePlaceholder"; export * from "./insightsColumns"; export * from "./dropDownSelect"; +export * from "./detailsLinks"; diff --git a/pkg/ui/workspaces/cluster-ui/src/insights/workloadInsights/workloadInsightsPageConnected.tsx b/pkg/ui/workspaces/cluster-ui/src/insights/workloadInsights/workloadInsightsPageConnected.tsx index 40d07acce4d0..ea5b399c96c0 100644 --- a/pkg/ui/workspaces/cluster-ui/src/insights/workloadInsights/workloadInsightsPageConnected.tsx +++ b/pkg/ui/workspaces/cluster-ui/src/insights/workloadInsights/workloadInsightsPageConnected.tsx @@ -39,7 +39,14 @@ import { selectFilters, selectSortSetting, } from "src/store/insights/transactionInsights"; -import { bindActionCreators } from "redux"; +import { bindActionCreators, Dispatch } from "redux"; +import { TimeScale } from "../../timeScaleDropdown"; +import { actions as sqlStatsActions } from "../../store/sqlStats"; +import { + StatementInsightDetails, + StatementInsightDetailsDispatchProps, + StatementInsightDetailsStateProps, +} from "../workloadInsightDetails"; const transactionMapStateToProps = ( state: AppState, @@ -62,7 +69,9 @@ const statementMapStateToProps = ( selectedColumnNames: selectColumns(state), }); -const TransactionDispatchProps = { +const TransactionDispatchProps = ( + dispatch: Dispatch, +): TransactionInsightsViewDispatchProps => ({ onFiltersChange: (filters: WorkloadInsightEventFilters) => localStorageActions.update({ key: "filters/InsightsPage", @@ -73,10 +82,19 @@ const TransactionDispatchProps = { key: "sortSetting/InsightsPage", value: ss, }), + setTimeScale: (ts: TimeScale) => { + dispatch( + sqlStatsActions.updateTimeScale({ + ts: ts, + }), + ); + }, refreshTransactionInsights: transactionInsights.refresh, -}; +}); -const StatementDispatchProps: StatementInsightsViewDispatchProps = { +const StatementDispatchProps = ( + dispatch: Dispatch, +): StatementInsightsViewDispatchProps => ({ onFiltersChange: (filters: WorkloadInsightEventFilters) => localStorageActions.update({ key: "filters/InsightsPage", @@ -92,8 +110,15 @@ const StatementDispatchProps: StatementInsightsViewDispatchProps = { key: "showColumns/StatementInsightsPage", value: value.join(","), }), + setTimeScale: (ts: TimeScale) => { + dispatch( + sqlStatsActions.updateTimeScale({ + ts: ts, + }), + ); + }, refreshStatementInsights: statementInsights.refresh, -}; +}); type StateProps = { transactionInsightsViewStateProps: TransactionInsightsViewStateProps; @@ -120,14 +145,8 @@ export const WorkloadInsightsPageConnected = withRouter( statementInsightsViewStateProps: statementMapStateToProps(state, props), }), dispatch => ({ - transactionInsightsViewDispatchProps: bindActionCreators( - TransactionDispatchProps, - dispatch, - ), - statementInsightsViewDispatchProps: bindActionCreators( - StatementDispatchProps, - dispatch, - ), + transactionInsightsViewDispatchProps: TransactionDispatchProps(dispatch), + statementInsightsViewDispatchProps: StatementDispatchProps(dispatch), }), (stateProps, dispatchProps) => ({ transactionInsightsViewProps: { diff --git a/pkg/ui/workspaces/cluster-ui/src/statementsPage/statementsPage.tsx b/pkg/ui/workspaces/cluster-ui/src/statementsPage/statementsPage.tsx index af806653a969..be92e398c4ab 100644 --- a/pkg/ui/workspaces/cluster-ui/src/statementsPage/statementsPage.tsx +++ b/pkg/ui/workspaces/cluster-ui/src/statementsPage/statementsPage.tsx @@ -73,7 +73,7 @@ import { timeScale1hMinOptions, TimeScaleDropdown, timeScaleToString, - toDateRange, + toRoundedDateRange, } from "../timeScaleDropdown"; import { commonStyles } from "../common"; @@ -153,7 +153,7 @@ export type StatementsPageProps = StatementsPageDispatchProps & function statementsRequestFromProps( props: StatementsPageProps, ): cockroach.server.serverpb.StatementsRequest { - const [start, end] = toDateRange(props.timeScale); + const [start, end] = toRoundedDateRange(props.timeScale); return new cockroach.server.serverpb.StatementsRequest({ combined: true, start: Long.fromNumber(start.unix()), diff --git a/pkg/ui/workspaces/cluster-ui/src/store/sqlStats/sqlStats.sagas.ts b/pkg/ui/workspaces/cluster-ui/src/store/sqlStats/sqlStats.sagas.ts index 1924e3d0456c..6b1514167f00 100644 --- a/pkg/ui/workspaces/cluster-ui/src/store/sqlStats/sqlStats.sagas.ts +++ b/pkg/ui/workspaces/cluster-ui/src/store/sqlStats/sqlStats.sagas.ts @@ -23,7 +23,7 @@ import { UpdateTimeScalePayload, } from "./sqlStats.reducer"; import { actions as sqlDetailsStatsActions } from "../statementDetails/statementDetails.reducer"; -import { toDateRange } from "../../timeScaleDropdown"; +import { toRoundedDateRange } from "../../timeScaleDropdown"; export function* refreshSQLStatsSaga(action: PayloadAction) { yield put(sqlStatsActions.request(action.payload)); @@ -50,7 +50,7 @@ export function* updateSQLStatsTimeScaleSaga( value: ts, }), ); - const [start, end] = toDateRange(ts); + const [start, end] = toRoundedDateRange(ts); const req = new cockroach.server.serverpb.StatementsRequest({ combined: true, start: Long.fromNumber(start.unix()), diff --git a/pkg/ui/workspaces/cluster-ui/src/transactionDetails/transactionDetails.tsx b/pkg/ui/workspaces/cluster-ui/src/transactionDetails/transactionDetails.tsx index 7d649a2def23..e11e67a5798f 100644 --- a/pkg/ui/workspaces/cluster-ui/src/transactionDetails/transactionDetails.tsx +++ b/pkg/ui/workspaces/cluster-ui/src/transactionDetails/transactionDetails.tsx @@ -67,7 +67,7 @@ import { timeScale1hMinOptions, TimeScaleDropdown, timeScaleToString, - toDateRange, + toRoundedDateRange, } from "../timeScaleDropdown"; import timeScaleStyles from "../timeScaleDropdown/timeScale.module.scss"; @@ -113,7 +113,7 @@ interface TState { function statementsRequestFromProps( props: TransactionDetailsProps, ): protos.cockroach.server.serverpb.StatementsRequest { - const [start, end] = toDateRange(props.timeScale); + const [start, end] = toRoundedDateRange(props.timeScale); return new protos.cockroach.server.serverpb.StatementsRequest({ combined: true, start: Long.fromNumber(start.unix()), diff --git a/pkg/ui/workspaces/cluster-ui/src/transactionsPage/transactionsPage.tsx b/pkg/ui/workspaces/cluster-ui/src/transactionsPage/transactionsPage.tsx index 92d6c174eee8..46915d17503d 100644 --- a/pkg/ui/workspaces/cluster-ui/src/transactionsPage/transactionsPage.tsx +++ b/pkg/ui/workspaces/cluster-ui/src/transactionsPage/transactionsPage.tsx @@ -63,10 +63,10 @@ import { commonStyles } from "../common"; import { TimeScaleDropdown, TimeScale, - toDateRange, timeScaleToString, timeScale1hMinOptions, getValidOption, + toRoundedDateRange, } from "../timeScaleDropdown"; import { InlineAlert } from "@cockroachlabs/ui-components"; import { TransactionViewType } from "./transactionsPageTypes"; @@ -118,7 +118,7 @@ export type TransactionsPageProps = TransactionsPageStateProps & function statementsRequestFromProps( props: TransactionsPageProps, ): protos.cockroach.server.serverpb.StatementsRequest { - const [start, end] = toDateRange(props.timeScale); + const [start, end] = toRoundedDateRange(props.timeScale); return new protos.cockroach.server.serverpb.StatementsRequest({ combined: true, start: Long.fromNumber(start.unix()), diff --git a/pkg/ui/workspaces/db-console/src/redux/statements/statementsSagas.ts b/pkg/ui/workspaces/db-console/src/redux/statements/statementsSagas.ts index c4e2a66e1ce2..53d502b51947 100644 --- a/pkg/ui/workspaces/db-console/src/redux/statements/statementsSagas.ts +++ b/pkg/ui/workspaces/db-console/src/redux/statements/statementsSagas.ts @@ -41,7 +41,7 @@ import { createStatementDiagnosticsAlertLocalSetting, cancelStatementDiagnosticsAlertLocalSetting, } from "src/redux/alerts"; -import { TimeScale, toDateRange } from "@cockroachlabs/cluster-ui"; +import { TimeScale, toRoundedDateRange } from "@cockroachlabs/cluster-ui"; import Long from "long"; import { setTimeScale } from "src/redux/timeScale"; @@ -157,7 +157,7 @@ export function* setCombinedStatementsTimeScaleSaga( const ts = action.payload; yield put(setTimeScale(ts)); - const [start, end] = toDateRange(ts); + const [start, end] = toRoundedDateRange(ts); const req = new CombinedStatementsRequest({ combined: true, start: Long.fromNumber(start.unix()), diff --git a/pkg/ui/workspaces/db-console/src/views/insights/statementInsightDetailsPage.tsx b/pkg/ui/workspaces/db-console/src/views/insights/statementInsightDetailsPage.tsx index 86d16c15d642..aeb17cfb477f 100644 --- a/pkg/ui/workspaces/db-console/src/views/insights/statementInsightDetailsPage.tsx +++ b/pkg/ui/workspaces/db-console/src/views/insights/statementInsightDetailsPage.tsx @@ -10,11 +10,13 @@ import { StatementInsightDetails, StatementInsightDetailsStateProps, + StatementInsightDetailsDispatchProps, } from "@cockroachlabs/cluster-ui"; import { connect } from "react-redux"; import { RouteComponentProps, withRouter } from "react-router-dom"; import { AdminUIState } from "src/redux/state"; import { selectStatementInsightDetails } from "src/views/insights/insightsSelectors"; +import { setGlobalTimeScaleAction } from "src/redux/statements"; const mapStateToProps = ( state: AdminUIState, @@ -28,9 +30,18 @@ const mapStateToProps = ( }; }; +const mapDispatchToProps: StatementInsightDetailsDispatchProps = { + setTimeScale: setGlobalTimeScaleAction, +}; + const StatementInsightDetailsPage = withRouter( - connect( + connect< + StatementInsightDetailsStateProps, + StatementInsightDetailsDispatchProps, + RouteComponentProps + >( mapStateToProps, + mapDispatchToProps, )(StatementInsightDetails), ); diff --git a/pkg/ui/workspaces/db-console/src/views/insights/transactionInsightDetailsPage.tsx b/pkg/ui/workspaces/db-console/src/views/insights/transactionInsightDetailsPage.tsx index 12401e70f5eb..ca83816f3c4c 100644 --- a/pkg/ui/workspaces/db-console/src/views/insights/transactionInsightDetailsPage.tsx +++ b/pkg/ui/workspaces/db-console/src/views/insights/transactionInsightDetailsPage.tsx @@ -18,6 +18,7 @@ import { RouteComponentProps, withRouter } from "react-router-dom"; import { refreshTransactionInsightDetails } from "src/redux/apiReducers"; import { AdminUIState } from "src/redux/state"; import { selectTransactionInsightDetails } from "src/views/insights/insightsSelectors"; +import { setGlobalTimeScaleAction } from "src/redux/statements"; const mapStateToProps = ( state: AdminUIState, @@ -33,8 +34,9 @@ const mapStateToProps = ( }; }; -const mapDispatchToProps = { +const mapDispatchToProps: TransactionInsightDetailsDispatchProps = { refreshTransactionInsightDetails: refreshTransactionInsightDetails, + setTimeScale: setGlobalTimeScaleAction, }; const TransactionInsightDetailsPage = withRouter( diff --git a/pkg/ui/workspaces/db-console/src/views/insights/workloadInsightsPage.tsx b/pkg/ui/workspaces/db-console/src/views/insights/workloadInsightsPage.tsx index 45ff91ba834b..e545fffa1df1 100644 --- a/pkg/ui/workspaces/db-console/src/views/insights/workloadInsightsPage.tsx +++ b/pkg/ui/workspaces/db-console/src/views/insights/workloadInsightsPage.tsx @@ -33,6 +33,7 @@ import { } from "src/views/insights/insightsSelectors"; import { bindActionCreators } from "redux"; import { LocalSetting } from "src/redux/localsettings"; +import { setGlobalTimeScaleAction } from "src/redux/statements"; export const insightStatementColumnsLocalSetting = new LocalSetting< AdminUIState, @@ -69,6 +70,7 @@ const TransactionDispatchProps = { onFiltersChange: (filters: WorkloadInsightEventFilters) => filtersLocalSetting.set(filters), onSortChange: (ss: SortSetting) => sortSettingLocalSetting.set(ss), + setTimeScale: setGlobalTimeScaleAction, refreshTransactionInsights: refreshTransactionInsights, }; @@ -79,6 +81,7 @@ const StatementDispatchProps: StatementInsightsViewDispatchProps = { refreshStatementInsights: refreshStatementInsights, onColumnsChange: (value: string[]) => insightStatementColumnsLocalSetting.set(value.join(",")), + setTimeScale: setGlobalTimeScaleAction, }; type StateProps = {