Skip to content

Commit

Permalink
server,ui: the transactionDetail page now shows statement stats scope…
Browse files Browse the repository at this point in the history
…d by

transaction fingerprint ID

Previously, the transactionDetail page showed statement statistics aggregated
across **all** executions of that statement fingerprint. This led to
confusing UX and the statement statistics were subsequently removed
from transactionDetail page.
This commit reintroduces statement statistics on the transactionDetail
page. The statistics now are only aggregated across the statement
fingerprints that are part of the selected transaction fingerprint.

Resolves cockroachdb#59205 cockroachdb#65106

Release note (ui change): transactionDetail page now shows statement
statistics scoped by the transaction fingeprint.
  • Loading branch information
Azhng committed Nov 19, 2021
1 parent 8422bbb commit bc2b9ee
Show file tree
Hide file tree
Showing 6 changed files with 56 additions and 19 deletions.
22 changes: 15 additions & 7 deletions pkg/server/combined_statement_stats.go
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,7 @@ func collectCombinedStatements(
query := fmt.Sprintf(
`SELECT
fingerprint_id,
transaction_fingerprint_id,
app_name,
aggregated_ts,
metadata,
Expand All @@ -122,7 +123,7 @@ func collectCombinedStatements(
FROM crdb_internal.statement_statistics
%s`, whereClause)

const expectedNumDatums = 7
const expectedNumDatums = 8

it, err := ie.QueryIteratorEx(ctx, "combined-stmts-by-interval", nil,
sessiondata.InternalExecutorOverride{
Expand Down Expand Up @@ -157,30 +158,37 @@ func collectCombinedStatements(
return nil, err
}

app := string(tree.MustBeDString(row[1]))
aggregatedTs := tree.MustBeDTimestampTZ(row[2]).Time
var transactionFingerprintID uint64
if transactionFingerprintID, err = sqlstatsutil.DatumToUint64(row[1]); err != nil {
return nil, err
}

app := string(tree.MustBeDString(row[2]))
aggregatedTs := tree.MustBeDTimestampTZ(row[3]).Time

var metadata roachpb.CollectedStatementStatistics
metadataJSON := tree.MustBeDJSON(row[3]).JSON
metadataJSON := tree.MustBeDJSON(row[4]).JSON
if err = sqlstatsutil.DecodeStmtStatsMetadataJSON(metadataJSON, &metadata); err != nil {
return nil, err
}

metadata.Key.App = app
metadata.Key.TransactionFingerprintID =
roachpb.TransactionFingerprintID(transactionFingerprintID)

statsJSON := tree.MustBeDJSON(row[4]).JSON
statsJSON := tree.MustBeDJSON(row[5]).JSON
if err = sqlstatsutil.DecodeStmtStatsStatisticsJSON(statsJSON, &metadata.Stats); err != nil {
return nil, err
}

planJSON := tree.MustBeDJSON(row[5]).JSON
planJSON := tree.MustBeDJSON(row[6]).JSON
plan, err := sqlstatsutil.JSONToExplainTreePlanNode(planJSON)
if err != nil {
return nil, err
}
metadata.Stats.SensitiveInfo.MostRecentPlanDescription = *plan

aggInterval := tree.MustBeDInterval(row[6]).Duration
aggInterval := tree.MustBeDInterval(row[7]).Duration

stmt := serverpb.StatementsResponse_CollectedStatementStatistics{
Key: serverpb.StatementsResponse_ExtendedStatementStatisticsKey{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,12 @@ import { SqlBox } from "../sql";
import { aggregateStatements } from "../transactionsPage/utils";
import { Loading } from "../loading";
import { SummaryCard } from "../summaryCard";
import { Bytes, Duration, formatNumberForDisplay } from "src/util";
import {
Bytes,
calculateTotalWorkload,
Duration,
formatNumberForDisplay,
} from "src/util";
import { UIConfigState } from "../store";

import summaryCardStyles from "../summaryCard/summaryCard.module.scss";
Expand All @@ -40,7 +45,7 @@ import { formatTwoPlaces } from "../barCharts";
import { ArrowLeft } from "@cockroachlabs/icons";
import {
populateRegionNodeForStatements,
makeStatementFingerprintColumn,
makeStatementsColumns,
} from "src/statementsTable/statementsTable";
import { TransactionInfo } from "src/transactionsTable";
import Long from "long";
Expand All @@ -64,6 +69,7 @@ interface TransactionDetailsProps {
error?: Error | null;
resetSQLStats: () => void;
isTenant: UIConfigState["isTenant"];
transactionFingerprintId: Long;
}

interface TState {
Expand Down Expand Up @@ -110,6 +116,7 @@ export class TransactionDetails extends React.Component<
handleDetails,
error,
nodeRegions,
transactionFingerprintId,
} = this.props;
return (
<div>
Expand All @@ -132,7 +139,12 @@ export class TransactionDetails extends React.Component<
render={() => {
const { statements, transactionStats, isTenant } = this.props;
const { sortSetting, pagination } = this.state;
const aggregatedStatements = aggregateStatements(statements);
const txnScopedStmts = statements.filter(s =>
s.key.key_data.transaction_fingerprint_id.equals(
transactionFingerprintId,
),
);
const aggregatedStatements = aggregateStatements(txnScopedStmts);
populateRegionNodeForStatements(
aggregatedStatements,
nodeRegions,
Expand Down Expand Up @@ -285,12 +297,14 @@ export class TransactionDetails extends React.Component<
<div className={cx("table-area")}>
<SortedTable
data={aggregatedStatements}
columns={[
makeStatementFingerprintColumn(
"transactionDetails",
"",
),
]}
columns={makeStatementsColumns(
aggregatedStatements,
"", // selectedApp
calculateTotalWorkload(aggregatedStatements),
nodeRegions,
"transactionDetails",
isTenant,
)}
className={cx("statements-table")}
sortSetting={sortSetting}
onChangeSortSetting={this.onChangeSortSetting}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,7 @@ interface TState {
statementFingerprintIds: Long[] | null;
aggregatedTs: Timestamp | null;
transactionStats: TransactionStats | null;
transactionFingerprintId: Long | null;
}

export interface TransactionsPageStateProps {
Expand Down Expand Up @@ -135,6 +136,7 @@ export class TransactionsPage extends React.Component<
aggregatedTs: null,
statementFingerprintIds: null,
transactionStats: null,
transactionFingerprintId: null,
};

refreshData = (): void => {
Expand Down Expand Up @@ -244,6 +246,8 @@ export class TransactionsPage extends React.Component<
transaction?.stats_data?.statement_fingerprint_ids,
transactionStats: transaction?.stats_data?.stats,
aggregatedTs: transaction?.stats_data?.aggregated_ts,
transactionFingerprintId:
transaction?.stats_data?.transaction_fingerprint_id,
});
};

Expand Down Expand Up @@ -460,6 +464,7 @@ export class TransactionsPage extends React.Component<
aggregatedTs,
statementFingerprintIds,
transactionStats,
transactionFingerprintId,
} = this.state;
const transactionDetails =
statementFingerprintIds &&
Expand All @@ -483,6 +488,7 @@ export class TransactionsPage extends React.Component<
error={this.props.error}
resetSQLStats={this.props.resetSQLStats}
isTenant={this.props.isTenant}
transactionFingerprintId={transactionFingerprintId}
/>
);
}
Expand Down
4 changes: 2 additions & 2 deletions pkg/ui/workspaces/cluster-ui/src/transactionsPage/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,11 +22,11 @@ import {
aggregateNumericStats,
FixLong,
longToInt,
statementKey,
TimestampToNumber,
addStatementStats,
flattenStatementStats,
DurationToNumber,
transactionScopedStatementKey,
} from "../util";

type Statement = protos.cockroach.server.serverpb.StatementsResponse.ICollectedStatementStatistics;
Expand Down Expand Up @@ -81,7 +81,7 @@ export const aggregateStatements = (
const statsKey: { [key: string]: AggregateStatistics } = {};

flattenStatementStats(statements).forEach(s => {
const key = statementKey(s);
const key = transactionScopedStatementKey(s);
if (!(key in statsKey)) {
statsKey[key] = {
label: s.statement,
Expand Down
10 changes: 10 additions & 0 deletions pkg/ui/workspaces/cluster-ui/src/util/appStats/appStats.ts
Original file line number Diff line number Diff line change
Expand Up @@ -213,6 +213,7 @@ export interface ExecutionStatistics {
full_scan: boolean;
failed: boolean;
node_id: number;
transaction_fingerprint_id: Long;
stats: StatementStatistics;
}

Expand All @@ -231,6 +232,7 @@ export function flattenStatementStats(
full_scan: stmt.key.key_data.full_scan,
failed: stmt.key.key_data.failed,
node_id: stmt.key.node_id,
transaction_fingerprint_id: stmt.key.key_data.transaction_fingerprint_id,
stats: stmt.stats,
}));
}
Expand Down Expand Up @@ -260,3 +262,11 @@ export function statementKey(stmt: ExecutionStatistics): string {
stmt.aggregation_interval
);
}

// transactionScopedStatementKey is similar to statementKey, except that
// it appends the transactionFingerprintID to the string key it generated.
export function transactionScopedStatementKey(
stmt: ExecutionStatistics,
): string {
return statementKey(stmt) + stmt.transaction_fingerprint_id.toString();
}
1 change: 0 additions & 1 deletion pkg/ui/workspaces/db-console/src/util/appStats.ts
Original file line number Diff line number Diff line change
Expand Up @@ -206,7 +206,6 @@ export function flattenStatementStats(
): ExecutionStatistics[] {
return statementStats.map(stmt => ({
statement: stmt.key.key_data.query,
statement_summary: stmt.key.key_data.query_summary,
aggregated_ts: util.TimestampToNumber(stmt.key.aggregated_ts),
aggregation_interval: util.DurationToNumber(stmt.key.aggregation_interval),
app: stmt.key.key_data.app,
Expand Down

0 comments on commit bc2b9ee

Please sign in to comment.