Skip to content

Commit

Permalink
ui: insights transaction details support multiple blocking transactions
Browse files Browse the repository at this point in the history
closes #88264

Release justification: Category 2: Bug fixes and
low-risk updates to new functionality

Release note: (ui change): Add support for multiple
 blocking transaction on insights transaction
 details page. Merged the cards into the table,
 and fixed the total contention time.
  • Loading branch information
j82w committed Sep 22, 2022
1 parent 2b79929 commit ca2fbe4
Show file tree
Hide file tree
Showing 5 changed files with 182 additions and 79 deletions.
124 changes: 88 additions & 36 deletions pkg/ui/workspaces/cluster-ui/src/api/insightsApi.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,13 +10,14 @@

import {
executeInternalSql,
SqlExecutionRequest,
SqlExecutionResponse,
INTERNAL_SQL_API_APP,
LONG_TIMEOUT,
LARGE_RESULT_SIZE,
LONG_TIMEOUT,
SqlExecutionRequest,
SqlExecutionResponse,
} from "./sqlApi";
import {
BlockedContentionDetails,
InsightExecEnum,
InsightNameEnum,
StatementInsightEvent,
Expand Down Expand Up @@ -57,22 +58,25 @@ const txnContentionQuery = `SELECT *
FROM (SELECT waiting_txn_id,
encode(
waiting_txn_fingerprint_id, 'hex'
) AS waiting_txn_fingerprint_id,
) AS waiting_txn_fingerprint_id,
collection_ts,
contention_duration,
row_number() over (
PARTITION BY waiting_txn_fingerprint_id
ORDER BY
collection_ts DESC
) AS rank,
threshold
total_contention_duration AS contention_duration,
row_number() over (
PARTITION BY waiting_txn_fingerprint_id
ORDER BY
collection_ts DESC
) AS rank, threshold
FROM (SELECT "sql.insights.latency_threshold" :: INTERVAL AS threshold
FROM
[SHOW CLUSTER SETTING sql.insights.latency_threshold]),
(SELECT DISTINCT ON (waiting_txn_id) *
FROM crdb_internal.transaction_contention_events tce),
(SELECT waiting_txn_id,
waiting_txn_fingerprint_id,
max(collection_ts) AS collection_ts,
sum(contention_duration) AS total_contention_duration
FROM crdb_internal.transaction_contention_events tce
GROUP BY waiting_txn_id, waiting_txn_fingerprint_id),
(SELECT txn_id FROM crdb_internal.cluster_execution_insights)
WHERE contention_duration > threshold
WHERE total_contention_duration > threshold
OR waiting_txn_id = txn_id)
WHERE rank = 1`;

Expand Down Expand Up @@ -352,24 +356,47 @@ type TxnContentionDetailsResponseColumns = {
function transactionContentionDetailsResultsToEventState(
response: SqlExecutionResponse<TxnContentionDetailsResponseColumns>,
): TransactionContentionEventDetailsResponse {
if (!response.execution.txn_results[0].rows) {
const resultsRows = response.execution.txn_results[0].rows;
if (!resultsRows) {
// No data.
return;
}
const row = response.execution.txn_results[0].rows[0];

const blockingContentionDetails = new Array<BlockedContentionDetails>(
resultsRows.length,
);

let totalContentionTime = 0;
resultsRows.forEach((value, idx) => {
const contentionTimeInMs = moment
.duration(value.contention_duration)
.asMilliseconds();
totalContentionTime += contentionTimeInMs;
blockingContentionDetails[idx] = {
blockingExecutionID: value.blocking_txn_id,
blockingFingerprintID: value.blocking_txn_fingerprint_id,
blockingQueries: null,
collectionTimeStamp: moment(value.collection_ts),
contentionTimeMs: contentionTimeInMs,
contendedKey: value.key,
schemaName: value.schema_name,
databaseName: value.database_name,
tableName: value.table_name,
indexName:
value.index_name && value.index_name !== ""
? value.index_name
: "primary index",
};
});

const row = resultsRows[0];
return {
executionID: row.waiting_txn_id,
fingerprintID: row.waiting_txn_fingerprint_id,
startTime: moment(row.collection_ts),
elapsedTime: moment.duration(row.contention_duration).asMilliseconds(),
totalContentionTime: totalContentionTime,
blockingContentionDetails: blockingContentionDetails,
contentionThreshold: moment.duration(row.threshold).asMilliseconds(),
blockingExecutionID: row.blocking_txn_id,
blockingFingerprintID: row.blocking_txn_fingerprint_id,
schemaName: row.schema_name,
databaseName: row.database_name,
tableName: row.table_name,
indexName: row.index_name,
contendedKey: row.key,
insightName: InsightNameEnum.highContention,
execType: InsightExecEnum.TRANSACTION,
};
Expand Down Expand Up @@ -425,9 +452,13 @@ export function getTransactionInsightEventDetailsState(
return executeInternalSql<FingerprintStmtsResponseColumns>(
waitingFingerprintStmtsRequest,
).then(waitingTxnStmtQueries => {
const blockingTxnFingerprintId =
contentionResults.execution.txn_results[0].rows[0]
.blocking_txn_fingerprint_id;
let blockingTxnFingerprintId: string[] = [];
contentionResults.execution.txn_results.forEach(txnResult => {
blockingTxnFingerprintId = blockingTxnFingerprintId.concat(
txnResult.rows.map(x => x.blocking_txn_fingerprint_id),
);
});

const blockingTxnFingerprintRequest: SqlExecutionRequest = {
statements: [
{
Expand All @@ -441,9 +472,17 @@ export function getTransactionInsightEventDetailsState(
return executeInternalSql<TxnStmtFingerprintsResponseColumns>(
blockingTxnFingerprintRequest,
).then(blockingTxnStmtFingerprintIDs => {
const blockingStmtFingerprintIDs =
blockingTxnStmtFingerprintIDs.execution.txn_results[0].rows[0]
.query_ids;
let blockingStmtFingerprintIDs: string[] = [];
blockingTxnStmtFingerprintIDs.execution.txn_results[0].rows.map(
row => {
if (row.query_ids && row.query_ids.length > 0) {
blockingStmtFingerprintIDs = blockingStmtFingerprintIDs.concat(
row.query_ids,
);
}
},
);

const blockingFingerprintStmtsRequest: SqlExecutionRequest = {
statements: [
{
Expand Down Expand Up @@ -492,6 +531,25 @@ export function combineTransactionInsightEventDetailsState(
waitingFingerprintStmtState &&
blockingFingerprintStmtState
) {
txnContentionDetailsState.blockingContentionDetails.forEach(blockedRow => {
const currBlockedFingerprintStmts = blockingTxnFingerprintState.filter(
x => x.fingerprintID === blockedRow.blockingFingerprintID,
);
if (
!currBlockedFingerprintStmts ||
currBlockedFingerprintStmts.length != 1
) {
return;
}

blockedRow.blockingQueries = currBlockedFingerprintStmts[0].queryIDs.map(
id =>
blockingFingerprintStmtState.find(
stmt => stmt.stmtFingerprintID === id,
)?.query,
);
});

res = {
...txnContentionDetailsState,
application: waitingTxnFingerprintState[0].application,
Expand All @@ -501,12 +559,6 @@ export function combineTransactionInsightEventDetailsState(
stmt => stmt.stmtFingerprintID === id,
)?.query,
),
blockingQueries: blockingTxnFingerprintState[0].queryIDs.map(
id =>
blockingFingerprintStmtState.find(
stmt => stmt.stmtFingerprintID === id,
)?.query,
),
};
}
return res;
Expand Down
30 changes: 20 additions & 10 deletions pkg/ui/workspaces/cluster-ui/src/insights/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -38,15 +38,8 @@ export type TransactionInsightEvent = {
execType: InsightExecEnum;
};

export type TransactionInsightEventDetails = {
executionID: string;
queries: string[];
insights: Insight[];
startTime: Moment;
elapsedTime: number;
contentionThreshold: number;
application: string;
fingerprintID: string;
export type BlockedContentionDetails = {
collectionTimeStamp: Moment;
blockingExecutionID: string;
blockingFingerprintID: string;
blockingQueries: string[];
Expand All @@ -55,6 +48,19 @@ export type TransactionInsightEventDetails = {
databaseName: string;
tableName: string;
indexName: string;
contentionTimeMs: number;
};

export type TransactionInsightEventDetails = {
executionID: string;
queries: string[];
insights: Insight[];
startTime: Moment;
totalContentionTime: number;
contentionThreshold: number;
application: string;
fingerprintID: string;
blockingContentionDetails: BlockedContentionDetails[];
execType: InsightExecEnum;
};

Expand Down Expand Up @@ -97,7 +103,11 @@ export type EventExecution = {
fingerprintID: string;
queries: string[];
startTime: Moment;
elapsedTime: number;
contentionTimeMs: number;
schemaName: string;
databaseName: string;
tableName: string;
indexName: string;
execType: InsightExecEnum;
};

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,16 +42,40 @@ export function makeInsightDetailsColumns(
sort: (item: EventExecution) => item.queries.length,
},
{
name: "startTime",
title: insightsTableTitles.startTime(execType),
name: "contentionStartTime",
title: insightsTableTitles.contentionStartTime(execType),
cell: (item: EventExecution) => item.startTime.format(DATE_FORMAT),
sort: (item: EventExecution) => item.startTime.unix(),
},
{
name: "elapsedTime",
title: insightsTableTitles.elapsedTime(execType),
cell: (item: EventExecution) => Duration(item.elapsedTime * 1e6),
sort: (item: EventExecution) => item.elapsedTime,
name: "contention",
title: insightsTableTitles.contention(execType),
cell: (item: EventExecution) => Duration(item.contentionTimeMs * 1e6),
sort: (item: EventExecution) => item.contentionTimeMs,
},
{
name: "schemaName",
title: insightsTableTitles.schemaName(execType),
cell: (item: EventExecution) => item.schemaName,
sort: (item: EventExecution) => item.schemaName,
},
{
name: "databaseName",
title: insightsTableTitles.databaseName(execType),
cell: (item: EventExecution) => item.databaseName,
sort: (item: EventExecution) => item.databaseName,
},
{
name: "tableName",
title: insightsTableTitles.tableName(execType),
cell: (item: EventExecution) => item.tableName,
sort: (item: EventExecution) => item.tableName,
},
{
name: "indexName",
title: insightsTableTitles.indexName(execType),
cell: (item: EventExecution) => item.indexName,
sort: (item: EventExecution) => item.indexName,
},
];
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,17 +15,13 @@ import { Heading } from "@cockroachlabs/ui-components";
import { Col, Row } from "antd";
import "antd/lib/col/style";
import "antd/lib/row/style";
import moment from "moment";
import { Button } from "src/button";
import { Loading } from "src/loading";
import { SqlBox, SqlBoxSize } from "src/sql";
import { SummaryCard, SummaryCardItem } from "src/summaryCard";
import { DATE_FORMAT_24_UTC } from "src/util/format";
import { getMatchParamByName } from "src/util/query";
import {
WaitTimeInsightsLabels,
WaitTimeInsightsPanel,
} from "src/detailsPanels/waitTimeInsightsPanel";
import { WaitTimeInsightsLabels } from "src/detailsPanels/waitTimeInsightsPanel";
import {
TransactionInsightEventDetailsRequest,
TransactionInsightEventDetailsResponse,
Expand Down Expand Up @@ -107,7 +103,7 @@ export class TransactionInsightDetails extends React.Component<TransactionInsigh
rec = {
type: "HighContention",
details: {
duration: insightDetails.elapsedTime,
duration: insightDetails.totalContentionTime,
description: insight.description,
},
};
Expand All @@ -119,16 +115,22 @@ export class TransactionInsightDetails extends React.Component<TransactionInsigh
}

const tableData = insightsTableData();
const blockingExecutions: EventExecution[] = [
{
executionID: insightDetails.blockingExecutionID,
fingerprintID: insightDetails.blockingFingerprintID,
queries: insightDetails.blockingQueries,
startTime: insightDetails.startTime,
elapsedTime: insightDetails.elapsedTime,
execType: insightDetails.execType,
},
];
const blockingExecutions: EventExecution[] =
insightDetails.blockingContentionDetails.map(x => {
return {
executionID: x.blockingExecutionID,
fingerprintID: x.blockingFingerprintID,
queries: x.blockingQueries,
startTime: x.collectionTimeStamp,
contentionTimeMs: x.contentionTimeMs,
execType: insightDetails.execType,
schemaName: x.schemaName,
databaseName: x.databaseName,
tableName: x.tableName,
indexName: x.indexName,
};
});

return (
<>
<section className={tableCx("section")}>
Expand Down Expand Up @@ -164,17 +166,6 @@ export class TransactionInsightDetails extends React.Component<TransactionInsigh
</Row>
</section>
<section className={tableCx("section")}>
<WaitTimeInsightsPanel
execType={insightDetails.execType}
executionID={insightDetails.executionID}
schemaName={insightDetails.schemaName}
tableName={insightDetails.tableName}
indexName={insightDetails.indexName}
databaseName={insightDetails.databaseName}
waitTime={moment.duration(insightDetails.elapsedTime)}
waitingExecutions={[]}
blockingExecutions={[]}
/>
<Row gutter={24}>
<Col className="gutter-row">
<Heading type="h5">
Expand Down
Loading

0 comments on commit ca2fbe4

Please sign in to comment.