diff --git a/pkg/ui/workspaces/db-console/src/views/reports/containers/customChart/customMetric.tsx b/pkg/ui/workspaces/db-console/src/views/reports/containers/customChart/customMetric.tsx index 0f7549dd241a..61e813b500e1 100644 --- a/pkg/ui/workspaces/db-console/src/views/reports/containers/customChart/customMetric.tsx +++ b/pkg/ui/workspaces/db-console/src/views/reports/containers/customChart/customMetric.tsx @@ -54,9 +54,9 @@ export class CustomMetricState { downsampler = TimeSeriesQueryAggregator.AVG; aggregator = TimeSeriesQueryAggregator.SUM; derivative = TimeSeriesQueryDerivative.NONE; - perNode = false; + perSource = false; perTenant = false; - source = ""; + nodeSource = ""; tenantSource = ""; } @@ -112,9 +112,9 @@ export class CustomMetricRow extends React.Component { }); }; - changeSource = (selectedOption: DropdownOption) => { + changeNodeSource = (selectedOption: DropdownOption) => { this.changeState({ - source: selectedOption.value, + nodeSource: selectedOption.value, }); }; @@ -124,9 +124,9 @@ export class CustomMetricRow extends React.Component { }); }; - changePerNode = (selection: React.FormEvent) => { + changePerSource = (selection: React.FormEvent) => { this.changeState({ - perNode: selection.currentTarget.checked, + perSource: selection.currentTarget.checked, }); }; @@ -151,8 +151,8 @@ export class CustomMetricRow extends React.Component { downsampler, aggregator, derivative, - source, - perNode, + nodeSource, + perSource, tenantSource, perTenant, }, @@ -217,17 +217,17 @@ export class CustomMetricRow extends React.Component { className="metric-table-dropdown__select" clearable={false} searchable={false} - value={source} + value={nodeSource} options={nodeOptions} - onChange={this.changeSource} + onChange={this.changeNodeSource} /> {canViewTenantOptions && ( @@ -340,7 +340,7 @@ export class CustomChartTable extends React.Component { Aggregator Rate Source - Per Node + Per Node/Store {canViewTenantOptions && ( Virtual Cluster )} diff --git a/pkg/ui/workspaces/db-console/src/views/reports/containers/customChart/index.tsx b/pkg/ui/workspaces/db-console/src/views/reports/containers/customChart/index.tsx index fcdccb77b5a3..c01662b6d16a 100644 --- a/pkg/ui/workspaces/db-console/src/views/reports/containers/customChart/index.tsx +++ b/pkg/ui/workspaces/db-console/src/views/reports/containers/customChart/index.tsx @@ -208,56 +208,79 @@ export class CustomChart extends React.Component< ); }; + getSources = ( + nodesSummary: NodesSummary, + metricState: CustomMetricState, + ): string[] => { + if (!(nodesSummary?.nodeStatuses?.length > 0)) { + return []; + } + // If we have no nodeSource, and we're not asking for perSource metrics, + // then the user is asking for cluster-wide metrics. We can return an empty + // source list. + if (metricState.nodeSource === "" && !metricState.perSource) { + return []; + } + if (isStoreMetric(nodesSummary.nodeStatuses[0], metricState.metric)) { + // If a specific node is selected, return the storeIDs associated with that node. + // Otherwise, we're at the cluster level, so we grab each store ID. + return metricState.nodeSource + ? nodesSummary.storeIDsByNodeID[metricState.nodeSource] + : Object.values(nodesSummary.storeIDsByNodeID).flatMap(s => s); + } else { + // If it's not a store metric, and a specific nodeSource is chosen, just return that. + // Otherwise, return all known node IDs. + return metricState.nodeSource + ? [metricState.nodeSource] + : nodesSummary.nodeIDs; + } + }; + // This function handles the logic related to creating Metric components // based on perNode and perTenant flags. renderMetricComponents = (metrics: CustomMetricState[], index: number) => { const { nodesSummary, tenantOptions } = this.props; + // We require nodes information to determine sources (storeIDs/nodeIDs) down below. + if (!(nodesSummary?.nodeStatuses?.length > 0)) { + return; + } const tenants = tenantOptions.length > 1 ? tenantOptions.slice(1) : []; return metrics.map((m, i) => { if (m.metric === "") { return ""; } - if (m.perNode && m.perTenant) { - return _.flatMap(nodesSummary.nodeIDs, nodeID => { + if (m.perSource && m.perTenant) { + const sources = this.getSources(nodesSummary, m); + return _.flatMap(sources, source => { return tenants.map(tenant => ( - n.toString(), - ) - : [nodeID] - } + sources={[source]} tenantSource={tenant.value} /> )); }); - } else if (m.perNode) { - return _.map(nodesSummary.nodeIDs, nodeID => ( + } else if (m.perSource) { + const sources = this.getSources(nodesSummary, m); + return _.map(sources, source => ( - n.toString(), - ) - : [nodeID] - } + sources={[source]} tenantSource={m.tenantSource} /> )); } else if (m.perTenant) { + const sources = this.getSources(nodesSummary, m); return tenants.map(tenant => ( )); @@ -279,7 +302,7 @@ export class CustomChart extends React.Component< aggregator={m.aggregator} downsampler={m.downsampler} derivative={m.derivative} - sources={m.source === "" ? [] : [m.source]} + sources={this.getSources(nodesSummary, m)} tenantSource={m.tenantSource} /> ); @@ -402,5 +425,8 @@ export default withRouter( ); function isStoreMetric(nodeStatus: INodeStatus, metricName: string) { + if (metricName?.startsWith("cr.store")) { + return true; + } return _.has(nodeStatus.store_statuses[0].metrics, metricName); }