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  }