github.com/cockroachdb/cockroach@v20.2.0-alpha.1+incompatible/pkg/ui/src/views/reports/containers/range/logTable.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 _ from "lodash";
    12  import React from "react";
    13  
    14  import * as protos from "src/js/protos";
    15  import { CachedDataReducerState } from "src/redux/cachedDataReducer";
    16  import { FixLong } from "src/util/fixLong";
    17  import Print from "src/views/reports/containers/range/print";
    18  import Loading from "src/views/shared/components/loading";
    19  import { TimestampToMoment } from "src/util/convert";
    20  
    21  interface LogTableProps {
    22    rangeID: Long;
    23    log: CachedDataReducerState<protos.cockroach.server.serverpb.RangeLogResponse>;
    24  }
    25  
    26  function printLogEventType(
    27    eventType: protos.cockroach.kv.kvserver.storagepb.RangeLogEventType,
    28  ) {
    29    switch (eventType) {
    30      case protos.cockroach.kv.kvserver.storagepb.RangeLogEventType.add:
    31        return "Add";
    32      case protos.cockroach.kv.kvserver.storagepb.RangeLogEventType.remove:
    33        return "Remove";
    34      case protos.cockroach.kv.kvserver.storagepb.RangeLogEventType.split:
    35        return "Split";
    36      case protos.cockroach.kv.kvserver.storagepb.RangeLogEventType.merge:
    37        return "Merge";
    38      default:
    39        return "Unknown";
    40    }
    41  }
    42  
    43  export default class LogTable extends React.Component<LogTableProps, {}> {
    44    // If there is no otherRangeID, it comes back as the number 0.
    45    renderRangeID(otherRangeID: Long | number) {
    46      const fixedOtherRangeID = FixLong(otherRangeID);
    47      const fixedCurrentRangeID = FixLong(this.props.rangeID);
    48      if (fixedOtherRangeID.eq(0)) {
    49        return null;
    50      }
    51  
    52      if (fixedCurrentRangeID.eq(fixedOtherRangeID)) {
    53        return `r${fixedOtherRangeID.toString()}`;
    54      }
    55  
    56      return (
    57        <a href={`#/reports/range/${fixedOtherRangeID.toString()}`}>
    58          r{fixedOtherRangeID.toString()}
    59        </a>
    60      );
    61    }
    62  
    63    renderLogInfoDescriptor(title: string, desc: string) {
    64      if (_.isEmpty(desc)) {
    65        return null;
    66      }
    67      return (
    68        <li>
    69          {title}: {desc}
    70        </li>
    71      );
    72    }
    73  
    74    renderLogInfo(
    75      info: protos.cockroach.server.serverpb.RangeLogResponse.IPrettyInfo,
    76    ) {
    77      return (
    78        <ul className="log-entries-list">
    79          {this.renderLogInfoDescriptor("Updated Range Descriptor", info.updated_desc)}
    80          {this.renderLogInfoDescriptor("New Range Descriptor", info.new_desc)}
    81          {this.renderLogInfoDescriptor("Added Replica", info.added_replica)}
    82          {this.renderLogInfoDescriptor("Removed Replica", info.removed_replica)}
    83          {this.renderLogInfoDescriptor("Reason", info.reason)}
    84          {this.renderLogInfoDescriptor("Details", info.details)}
    85        </ul>
    86      );
    87    }
    88  
    89    renderContent = () => {
    90      const { log } = this.props;
    91  
    92      // Sort by descending timestamp.
    93      const events = _.orderBy(
    94        log && log.data && log.data.events,
    95        event => TimestampToMoment(event.event.timestamp).valueOf(),
    96        "desc",
    97      );
    98  
    99      return (
   100        <table className="log-table">
   101          <tbody>
   102            <tr className="log-table__row log-table__row--header">
   103              <th className="log-table__cell log-table__cell--header">Timestamp</th>
   104              <th className="log-table__cell log-table__cell--header">Store</th>
   105              <th className="log-table__cell log-table__cell--header">Event Type</th>
   106              <th className="log-table__cell log-table__cell--header">Range</th>
   107              <th className="log-table__cell log-table__cell--header">Other Range</th>
   108              <th className="log-table__cell log-table__cell--header">Info</th>
   109            </tr>
   110            {_.map(events, (event, key) => (
   111              <tr key={key} className="log-table__row">
   112                <td className="log-table__cell log-table__cell--date">
   113                  {Print.Timestamp(event.event.timestamp)}
   114                </td>
   115                <td className="log-table__cell">s{event.event.store_id}</td>
   116                <td className="log-table__cell">{printLogEventType(event.event.event_type)}</td>
   117                <td className="log-table__cell">{this.renderRangeID(event.event.range_id)}</td>
   118                <td className="log-table__cell">{this.renderRangeID(event.event.other_range_id)}</td>
   119                <td className="log-table__cell">{this.renderLogInfo(event.pretty_info)}</td>
   120              </tr>
   121            ))}
   122          </tbody>
   123        </table>
   124      );
   125    }
   126  
   127    render() {
   128      const { log } = this.props;
   129  
   130      return (
   131        <div>
   132          <h2 className="base-heading">Range Log</h2>
   133          <Loading
   134            loading={!log || log.inFlight}
   135            error={log && log.lastError}
   136            render={this.renderContent}
   137          />
   138        </div>
   139      );
   140    }
   141  }