github.com/cockroachdb/cockroach@v20.2.0-alpha.1+incompatible/pkg/ui/src/views/cluster/containers/nodeGraphs/summaryBar.tsx (about) 1 // Copyright 2018 The Cockroach Authors. 2 // 3 // Use of this software is governed by the Business Source License 4 // included in the file licenses/BSL.txt. 5 // 6 // As of the Change Date specified in that file, in accordance with 7 // the Business Source License, use of this software will be governed 8 // by the Apache License, Version 2.0, included in the file 9 // licenses/APL.txt. 10 11 import React from "react"; 12 import { Link } from "react-router-dom"; 13 import * as d3 from "d3"; 14 15 import { NodesSummary } from "src/redux/nodes"; 16 import { Bytes } from "src/util/format"; 17 import { NanoToMilli } from "src/util/convert"; 18 19 import { EventBox } from "src/views/cluster/containers/events"; 20 import { Metric } from "src/views/shared/components/metricQuery"; 21 import { 22 SummaryBar, 23 SummaryLabel, 24 SummaryMetricStat, 25 SummaryStat, 26 SummaryStatBreakdown, 27 SummaryStatMessage, 28 SummaryMetricsAggregator, 29 } from "src/views/shared/components/summaryBar"; 30 31 interface ClusterSummaryProps { 32 nodeSources: string[]; 33 nodesSummary: NodesSummary; 34 } 35 36 /** 37 * ClusterNodeTotals displays a high-level breakdown of the nodes on the cluster 38 * and their current liveness status. 39 */ 40 function ClusterNodeTotals (props: ClusterSummaryProps) { 41 if (!props.nodesSummary || !props.nodesSummary.nodeSums) { 42 return; 43 } 44 const { nodeCounts } = props.nodesSummary.nodeSums; 45 let children: React.ReactNode; 46 if (nodeCounts.dead > 0 || nodeCounts.suspect > 0) { 47 children = ( 48 <div> 49 <SummaryStatBreakdown title="Healthy" value={nodeCounts.healthy} modifier="healthy" /> 50 <SummaryStatBreakdown title="Suspect" value={nodeCounts.suspect} modifier="suspect" /> 51 <SummaryStatBreakdown title="Dead" value={nodeCounts.dead} modifier="dead" /> 52 </div> 53 ); 54 } 55 return ( 56 <SummaryStat 57 title={ 58 <span>Total Nodes <Link to="/overview/list">View nodes list</Link></span> 59 } 60 value={nodeCounts.total} 61 > 62 { children } 63 </SummaryStat> 64 ); 65 } 66 67 const formatOnePlace = d3.format(".1f"); 68 const formatPercentage = d3.format(".2%"); 69 function formatNanosAsMillis (n: number) { 70 return formatOnePlace(NanoToMilli(n)) + " ms"; 71 } 72 73 /** 74 * Component which displays the cluster summary bar on the graphs page. 75 */ 76 export default function(props: ClusterSummaryProps) { 77 // Capacity math used in the summary status section. 78 const { capacityUsed, capacityUsable } = props.nodesSummary.nodeSums; 79 const capacityPercent = capacityUsable !== 0 ? (capacityUsed / capacityUsable) : null; 80 81 return ( 82 <div> 83 <SummaryBar> 84 <SummaryLabel>Summary</SummaryLabel> 85 <ClusterNodeTotals {...props}/> 86 <SummaryStat title="Capacity Used" value={capacityPercent} format={formatPercentage}> 87 <SummaryStatMessage message={`You are using ${Bytes(capacityUsed)} of ${Bytes(capacityUsable)} 88 usable storage capacity across all nodes.`} /> 89 </SummaryStat> 90 <SummaryStat title="Unavailable ranges" value={props.nodesSummary.nodeSums.unavailableRanges} /> 91 <SummaryMetricStat 92 id="qps" 93 title="Queries per second" 94 format={formatOnePlace} 95 aggregator={SummaryMetricsAggregator.SUM} 96 summaryStatMessage="Sum of Selects, Updates, Inserts, and Deletes across your entire cluster." 97 > 98 <Metric sources={props.nodeSources} name="cr.node.sql.select.count" title="Queries/Sec" nonNegativeRate /> 99 <Metric sources={props.nodeSources} name="cr.node.sql.insert.count" title="Queries/Sec" nonNegativeRate /> 100 <Metric sources={props.nodeSources} name="cr.node.sql.update.count" title="Queries/Sec" nonNegativeRate /> 101 <Metric sources={props.nodeSources} name="cr.node.sql.delete.count" title="Queries/Sec" nonNegativeRate /> 102 </SummaryMetricStat> 103 <SummaryMetricStat id="p99" title="P99 latency" format={formatNanosAsMillis} > 104 <Metric sources={props.nodeSources} name="cr.node.sql.service.latency-p99" aggregateMax downsampleMax /> 105 </SummaryMetricStat> 106 </SummaryBar> 107 <SummaryBar> 108 <SummaryLabel>Events</SummaryLabel> 109 <EventBox /> 110 </SummaryBar> 111 </div> 112 ); 113 }