Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

cluster-ui: update transactions page with execution stats #193

Merged
merged 3 commits into from
Feb 9, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion packages/cluster-ui/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@
"keywords": [],
"license": "MIT",
"dependencies": {
"@cockroachlabs/crdb-protobuf-client": "^0.0.5",
"@cockroachlabs/crdb-protobuf-client": "^0.0.6",
"@cockroachlabs/icons": "0.3.0",
"@cockroachlabs/ui-components": "0.2.14-alpha.0",
"@popperjs/core": "^2.4.0",
Expand Down
4 changes: 2 additions & 2 deletions packages/cluster-ui/src/barCharts/barCharts.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -54,10 +54,10 @@ const retryBars = [
];

const rowsReadStdDev = bar(cx("rows-read-dev"), (d: StatementStatistics) =>
stdDevLong(d.stats.rows_read, d.stats.exec_stat_collection_count),
stdDevLong(d.stats.rows_read, d.stats.count),
);
const bytesReadStdDev = bar(cx("rows-read-dev"), (d: StatementStatistics) =>
stdDevLong(d.stats.bytes_read, d.stats.exec_stat_collection_count),
stdDevLong(d.stats.bytes_read, d.stats.count),
);
const latencyStdDev = bar(
cx("bar-chart__overall-dev"),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -111,30 +111,6 @@ export const StatementTableTitle = {
Execution Count
</Tooltip>
),
rowsAffected: (
<Tooltip
placement="bottom"
title={
<div className={cx("tooltip__table--title")}>
<p>
{
"Average number of rows returned while executing statements with this fingerprint within the last hour or specified "
}
<Anchor href={statementsTimeInterval} target="_blank">
time interval
</Anchor>
.
</p>
<p>
The gray bar indicates the mean number of rows returned. The blue
bar indicates one standard deviation from the mean.
</p>
</div>
}
>
Rows Affected
</Tooltip>
),
rowsRead: (
<Tooltip
placement="bottom"
Expand Down
51 changes: 50 additions & 1 deletion packages/cluster-ui/src/transactionsPage/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import { aggregateNumericStats, FixLong } from "../util";
type Statement = protos.cockroach.server.serverpb.StatementsResponse.ICollectedStatementStatistics;
type TransactionStats = protos.cockroach.sql.ITransactionStatistics;
type Transaction = protos.cockroach.server.serverpb.StatementsResponse.IExtendedCollectedTransactionStatistics;
type ExecStats = protos.cockroach.sql.IExecStats;

export const getTrxAppFilterOptions = (
transactions: Transaction[],
Expand Down Expand Up @@ -124,12 +125,52 @@ const withFingerprint = function(
};
};

function addExecStats(a: ExecStats, b: ExecStats): Required<ExecStats> {
let execStatCountA = FixLong(a.count).toInt();
const execStatCountB = FixLong(b.count).toInt();
if (execStatCountA === 0 && execStatCountB === 0) {
// If both counts are zero, artificially set the one count to one to avoid
// division by zero when calculating the mean in addNumericStats.
execStatCountA = 1;
}
return {
count: a.count.add(b.count),
network_bytes:
a.network_bytes && b.network_bytes
? aggregateNumericStats(
a.network_bytes,
b.network_bytes,
execStatCountA,
execStatCountB,
)
: null,
max_mem_usage:
a.max_mem_usage && b.max_mem_usage
? aggregateNumericStats(
a.max_mem_usage,
b.max_mem_usage,
execStatCountA,
execStatCountB,
)
: null,
contention_time:
a.contention_time && b.contention_time
? aggregateNumericStats(
a.contention_time,
b.contention_time,
execStatCountA,
execStatCountB,
)
: null,
};
}

// addTransactionStats adds together two stat objects into one using their counts to compute a new
// average for the numeric statistics. It's modeled after the similar `addStatementStats` function
function addTransactionStats(
a: TransactionStats,
b: TransactionStats,
): TransactionStats {
): Required<TransactionStats> {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I added this in because I thought that incorrect addition of transaction stats was causing some null property accesses, but it was in fact due to something else. However, I kept it in because I thought it's hygienic. When is this used? I didn't update my statements page PR to update the similar addStatementStats (however, something similar exists in the main cockroach repo, which is not the case for transactions). What's the consequence of this? Should I update addStatementStats?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes I like making changes like this. I think making the same change to addStatementStats is worth it.

Because the Statements Page has been integrated into CC, it has its own redux layer in cluster-ui that was built to work nicely with CC's redux store. That redux layer is not used with DB Console so there is some code duplication there. I think what we'll end up doing in the near term is moving the redux layer directly into CC to clarify that the two redux configurations are separate and make peace with some code duplication.

So making that change to addStatementStats will protect CC's version of the Statements Page from null lookups.

const countA = FixLong(a.count).toInt();
const countB = FixLong(b.count).toInt();
return {
Expand All @@ -151,6 +192,14 @@ function addTransactionStats(
countA,
countB,
),
rows_read: aggregateNumericStats(a.rows_read, b.rows_read, countA, countB),
bytes_read: aggregateNumericStats(
a.bytes_read,
b.bytes_read,
countA,
countB,
),
exec_stats: addExecStats(a.exec_stats, b.exec_stats),
};
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import * as protos from "@cockroachlabs/crdb-protobuf-client";
import { stdDevLong } from "src/util/appStats";
import { Duration } from "src/util/format";
import { Duration, Bytes } from "src/util/format";
import classNames from "classnames/bind";
import styles from "../barCharts/barCharts.module.scss";
import { barChartFactory } from "src/barCharts/barChartFactory";
Expand All @@ -14,16 +14,27 @@ import {
type Transaction = protos.cockroach.server.serverpb.StatementsResponse.IExtendedCollectedTransactionStatistics;
const cx = classNames.bind(styles);

const retryBar = [
bar("count-retry", (d: Transaction) =>
longToInt(d.stats_data.stats.max_retries),
),
];
const countBar = [
bar("count-first-try", (d: Transaction) =>
longToInt(d.stats_data.stats.count),
),
];
const rowsReadBar = [
bar("rows-read", (d: Transaction) =>
longToInt(d.stats_data.stats.rows_read.mean),
),
];
const rowsReadStdDev = bar(cx("rows-read-dev"), (d: Transaction) =>
stdDevLong(d.stats_data.stats.rows_read, d.stats_data.stats.count),
);
const bytesReadBar = [
bar("bytes-read", (d: Transaction) =>
longToInt(d.stats_data.stats.bytes_read.mean),
),
];
const bytesReadStdDev = bar(cx("bytes-read-dev"), (d: Transaction) =>
stdDevLong(d.stats_data.stats.bytes_read, d.stats_data.stats.count),
);
const latencyBar = [
bar(
"bar-chart__service-lat",
Expand All @@ -33,33 +44,71 @@ const latencyBar = [
const latencyStdDev = bar(cx("bar-chart__overall-dev"), (d: Transaction) =>
stdDevLong(d.stats_data.stats.service_lat, d.stats_data.stats.count),
);
const rowsBar = [
bar("rows", (d: Transaction) => d.stats_data.stats.num_rows.mean),
const maxMemUsageBar = [
bar("max-mem-usage", (d: Transaction) =>
longToInt(d.stats_data.stats.exec_stats.max_mem_usage?.mean),
),
];
const rowsStdDev = bar(cx("rows-dev"), (d: Transaction) =>
stdDevLong(d.stats_data.stats.num_rows, d.stats_data.stats.count),
const maxMemUsageStdDev = bar(cx("max-mem-usage-dev"), (d: Transaction) =>
stdDevLong(
d.stats_data.stats.exec_stats.max_mem_usage,
d.stats_data.stats.exec_stats.count,
),
);
const networkBytesBar = [
bar("network-bytes", (d: Transaction) =>
longToInt(d.stats_data.stats.exec_stats.network_bytes?.mean),
),
];
const networkBytesStdDev = bar(cx("network-bytes-dev"), (d: Transaction) =>
stdDevLong(
d.stats_data.stats.exec_stats.network_bytes,
d.stats_data.stats.exec_stats.count,
),
);
const retryBar = [
bar("count-retry", (d: Transaction) =>
longToInt(d.stats_data.stats.max_retries),
),
];

export const transactionsCountBarChart = barChartFactory(
"grey",
countBar,
approximify,
);
export const transactionsRetryBarChart = barChartFactory(
"red",
retryBar,
export const transactionsRowsReadBarChart = barChartFactory(
"grey",
rowsReadBar,
approximify,
rowsReadStdDev,
);
export const transactionsRowsBarChart = barChartFactory(
export const transactionsBytesReadBarChart = barChartFactory(
"grey",
rowsBar,
approximify,
rowsStdDev,
formatTwoPlaces,
bytesReadBar,
Bytes,
bytesReadStdDev,
);
export const transactionsLatencyBarChart = barChartFactory(
"grey",
latencyBar,
v => Duration(v * 1e9),
latencyStdDev,
);
export const transactionsMaxMemUsageBarChart = barChartFactory(
"grey",
maxMemUsageBar,
Bytes,
maxMemUsageStdDev,
);
export const transactionsNetworkBytesBarChart = barChartFactory(
"grey",
networkBytesBar,
Bytes,
networkBytesStdDev,
);
export const transactionsRetryBarChart = barChartFactory(
"red",
retryBar,
approximify,
);
Loading