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

[WIP] server, ui: return replica-level QPS and leaseholder info; render in replica matrix #26906

Open
wants to merge 12 commits into
base: master
Choose a base branch
from
Prev Previous commit
Next Next commit
ui: show all ranges in tree
Release note: None
  • Loading branch information
Pete Vilter committed Nov 2, 2018
commit 6ba3a767c5b20f98c6e0c97b1dacd0823e96ca86
103 changes: 57 additions & 46 deletions pkg/ui/src/views/cluster/containers/dataDistribution/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -27,10 +27,12 @@ import ReplicaMatrix, {
import { TreeNode, TreePath } from "./tree";
import "./index.styl";

import IReplicaInfo = cockroach.server.serverpb.LeaseholdersAndQPSResponse.IReplicaInfo;
type DataDistributionResponse = cockroach.server.serverpb.DataDistributionResponse;
type LeaseholdersAndQPSResponse = cockroach.server.serverpb.LeaseholdersAndQPSResponse;
type NodeDescriptor = cockroach.roachpb.INodeDescriptor;
type ZoneConfig$Properties = cockroach.server.serverpb.DataDistributionResponse.IZoneConfig;
type INodeDescriptor = cockroach.roachpb.INodeDescriptor;
type IZoneConfig = cockroach.server.serverpb.DataDistributionResponse.IZoneConfig;
type IRangeInfo = cockroach.server.serverpb.LeaseholdersAndQPSResponse.IRangeInfo;

const ZONE_CONFIG_TEXT = (
<span>
Expand All @@ -44,7 +46,7 @@ interface DataDistributionProps {
dataDistribution: DataDistributionResponse;
leaseholdersAndQPS: LeaseholdersAndQPSResponse;
localityTree: LocalityTree;
sortedZoneConfigs: ZoneConfig$Properties[];
sortedZoneConfigs: IZoneConfig[];
}

class DataDistribution extends React.Component<DataDistributionProps> {
Expand Down Expand Up @@ -82,57 +84,27 @@ class DataDistribution extends React.Component<DataDistributionProps> {
}

getLeaseholderCount(dbPath: TreePath, nodePath: TreePath): number {
const tableName = dbPath[1];
const nodeID = nodePath[nodePath.length - 1];
const range = this.getRangeAtPath(dbPath);

const tableID = this.tableIDForName(tableName);

// gah this is stupid. use int32s
// TODO(vilterp): remove this keyBy...
const tableInfo = this.props.leaseholdersAndQPS.table_infos[tableID];

if (tableInfo) {
return _.sumBy(tableInfo.range_infos, (rangeInfo) => {
return rangeInfo.leaseholder_node_id.toString() === nodeID ? 1 : 0;
});
} else {
if (!range) {
return 0;
}

const isLeaseholder = range.leaseholder_node_id.toString() === nodeID;
return isLeaseholder ? 1 : 0;
}

getQPS(dbPath: TreePath, nodePath: TreePath): number {
const tableName = dbPath[1];
const nodeID = nodePath[nodePath.length - 1];
const replica = this.getReplicaAtPaths(dbPath, nodePath);

const tableID = this.tableIDForName(tableName);

// gah this is stupid. use int32s
// TODO(vilterp): remove this keyBy...
const tableInfo = this.props.leaseholdersAndQPS.table_infos[tableID];

if (tableInfo) {
return _.sumBy(tableInfo.range_infos, (rangeInfo) => {
const replicaOnThisNode = rangeInfo.replica_info[nodeID];
if (replicaOnThisNode) {
return Math.round(replicaOnThisNode.stats.queries_per_second);
}
return 0;
});
} else {
return 0;
}
return replica ? Math.round(replica.stats.queries_per_second) : 0;
}

getReplicaCount(dbPath: TreePath, nodePath: TreePath): number {
const [dbName, tableName] = dbPath;
const nodeID = nodePath[nodePath.length - 1];
const databaseInfo = this.props.dataDistribution.database_info;
const replica = this.getReplicaAtPaths(dbPath, nodePath);

const res = databaseInfo[dbName].table_info[tableName].replica_count_by_node_id[nodeID];
if (!res) {
return 0;
}
return FixLong(res).toInt();
return replica ? 1 : 0;
}

tableIDForName(name: string) {
Expand All @@ -141,13 +113,42 @@ class DataDistribution extends React.Component<DataDistributionProps> {
_.forEach(dbInfo.table_info, (tableInfo, tableName) => {
if (tableName === name) {
id = tableInfo.id.toInt();
// TODO(vilterp): how do you bail out of this early?
// TODO(vilterp): just do a normal for loop and bail out early
// or build a map of this in a selector
// or change the return type of the endpoint...
}
});
});
return id;
}

getRangeAtPath(dbPath: TreePath): IRangeInfo {
const tableName = dbPath[1];
const rangeID = dbPath[2];
const tableID = this.tableIDForName(tableName);
const ranges = this.getRangesForTableID(tableID);
return ranges[rangeID];
}

getReplicaAtPaths(dbPath: TreePath, nodePath: TreePath): IReplicaInfo {
const nodeID = nodePath[nodePath.length - 1];

const range = this.getRangeAtPath(dbPath);
if (!range) {
return null; // TODO(vilterp) under what circumstances does this happen?
}

return range.replica_info[nodeID];
}

getRangesForTableID(tableID: number): { [K: string]: IRangeInfo } {
const maybeTableInfo = this.props.leaseholdersAndQPS.table_infos[tableID.toString()];
if (maybeTableInfo) {
return maybeTableInfo.range_infos;
}
return {};
}

render() {
const nodeTree = nodeTreeFromLocalityTree("Cluster", this.props.localityTree);

Expand All @@ -165,6 +166,10 @@ class DataDistribution extends React.Component<DataDistributionProps> {
tableName,
tableID: tableInfo.id.toInt(),
},
children: _.map(this.getRangesForTableID(tableInfo.id.toNumber()), (rangeInfo) => ({
name: rangeInfo.id.toString(),
data: { dbName, tableName, rangeID: rangeInfo.id.toString() },
})),
})),
})),
};
Expand Down Expand Up @@ -200,7 +205,7 @@ interface DataDistributionPageProps {
dataDistribution: DataDistributionResponse;
leaseholdersAndQPS: LeaseholdersAndQPSResponse;
localityTree: LocalityTree;
sortedZoneConfigs: ZoneConfig$Properties[];
sortedZoneConfigs: IZoneConfig[];
refreshDataDistribution: typeof refreshDataDistribution;
refreshLeaseholdersAndQPS: typeof refreshLeaseholdersAndQPS;
refreshNodes: typeof refreshNodes;
Expand All @@ -224,6 +229,12 @@ class DataDistributionPage extends React.Component<DataDistributionPageProps> {
}

render() {
const isLoading = (
!this.props.dataDistribution ||
!this.props.localityTree ||
!this.props.leaseholdersAndQPS
);

return (
<div>
<Helmet>
Expand All @@ -235,7 +246,7 @@ class DataDistributionPage extends React.Component<DataDistributionPageProps> {
<section style={{ paddingTop: 10, paddingLeft: 30, display: "block" }}>
<Loading
className="loading-image loading-image__spinner-left"
loading={!this.props.dataDistribution || !this.props.localityTree}
loading={isLoading}
image={spinner}
render={() => (
<DataDistribution
Expand Down Expand Up @@ -285,7 +296,7 @@ export default DataDistributionPageConnected;
function nodeTreeFromLocalityTree(
rootName: string,
localityTree: LocalityTree,
): TreeNode<NodeDescriptor> {
): TreeNode<INodeDescriptor> {
const children: TreeNode<any>[] = [];

// Add child localities.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,10 @@ import {
flatten,
sumValuesUnderPaths,
LayoutCell,
FlattenedNode,
FlattenedNode, visitNodes,
} from "./tree";
import { cockroach } from "src/js/protos";
import NodeDescriptor$Properties = cockroach.roachpb.INodeDescriptor;
import INodeDescriptor = cockroach.roachpb.INodeDescriptor;
import "./replicaMatrix.styl";

const DOWN_ARROW = "▼";
Expand All @@ -25,7 +25,7 @@ interface ReplicaMatrixState {
}

interface ReplicaMatrixProps {
cols: TreeNode<NodeDescriptor$Properties>;
cols: TreeNode<INodeDescriptor>;
rows: TreeNode<SchemaObject>;
getValue: (metric: string) => (rowPath: TreePath, colPath: TreePath) => number;
}
Expand All @@ -44,9 +44,23 @@ class ReplicaMatrix extends Component<ReplicaMatrixProps, ReplicaMatrixState> {

constructor(props: ReplicaMatrixProps) {
super(props);

const collapsedPaths = [
["system"],
["defaultdb"],
["postgres"],
];
visitNodes(props.rows, (node, path) => {
if (node.data.tableName) { // [db, table]
collapsedPaths.push(path);
return false;
}
return true;
});

// TODO(vilterp): put all this state in the URL
this.state = {
collapsedRows: [["system"], ["defaultdb"], ["postgres"]],
collapsedRows: collapsedPaths,
collapsedCols: [],
selectedMetric: METRIC_REPLICAS,
};
Expand Down Expand Up @@ -76,7 +90,7 @@ class ReplicaMatrix extends Component<ReplicaMatrixProps, ReplicaMatrixState> {
});
}

colLabel(col: LayoutCell<NodeDescriptor$Properties>): string {
colLabel(col: LayoutCell<INodeDescriptor>): string {
if (col.isPlaceholder) {
return null;
}
Expand All @@ -91,14 +105,26 @@ class ReplicaMatrix extends Component<ReplicaMatrixProps, ReplicaMatrixState> {
}

rowLabel(row: FlattenedNode<SchemaObject>): string {
if (row.isLeaf) {
if (row.data.rangeID) {
return `r${row.data.rangeID}`;
}

if (row.data.tableName) {
return row.data.tableName;
}

return row.data.dbName ? `DB: ${row.data.dbName}` : "Cluster";
}

rowLabelAndArrow(row: FlattenedNode<SchemaObject>): string {
const label = this.rowLabel(row);
const arrow = row.isCollapsed ? SIDE_ARROW : DOWN_ARROW;
const label = row.data.dbName ? `DB: ${row.data.dbName}` : "Cluster";

return `${arrow} ${label}`;
if (row.isLeaf) {
return label;
} else {
return `${arrow} ${label}`;
}
}

handleChangeMetric = (evt: React.FormEvent<HTMLSelectElement>) => {
Expand Down Expand Up @@ -183,7 +209,7 @@ class ReplicaMatrix extends Component<ReplicaMatrixProps, ReplicaMatrixState> {
)}
style={{ paddingLeft: row.depth * ROW_TREE_INDENT_PX + ROW_LEFT_MARGIN_PX }}
>
{this.rowLabel(row)}
{this.rowLabelAndArrow(row)}
</th>
{flattenedCols.map((col) => {
return (
Expand Down Expand Up @@ -220,4 +246,5 @@ export interface SchemaObject {
dbName?: string;
tableName?: string;
tableID?: number;
rangeID?: string;
}
Original file line number Diff line number Diff line change
Expand Up @@ -347,7 +347,7 @@ function nodeAtPath<T>(root: TreeNode<T>, path: TreePath): TreeNode<T> {
* If `f` returns false, the traversal stops. Otherwise, the traversal
* continues.
*/
function visitNodes<T>(root: TreeNode<T>, f: (node: TreeNode<T>, path: TreePath) => boolean) {
export function visitNodes<T>(root: TreeNode<T>, f: (node: TreeNode<T>, path: TreePath) => boolean) {
function recur(node: TreeNode<T>, path: TreePath) {
const continueTraversal = f(node, path);
if (!continueTraversal) {
Expand Down