github.com/cockroachdb/cockroach@v20.2.0-alpha.1+incompatible/pkg/ui/src/views/reports/containers/range/leaseTable.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 Lease from "src/views/reports/containers/range/lease"; 16 import Print from "src/views/reports/containers/range/print"; 17 import RangeInfo from "src/views/reports/containers/range/rangeInfo"; 18 19 interface LeaseTableProps { 20 info: protos.cockroach.server.serverpb.IRangeInfo; 21 } 22 23 export default class LeaseTable extends React.Component<LeaseTableProps, {}> { 24 renderLeaseCell(value: string, title: string = "") { 25 if (_.isEmpty(title)) { 26 return <td className="lease-table__cell" title={value}>{value}</td>; 27 } 28 return <td className="lease-table__cell" title={title}>{value}</td>; 29 } 30 31 renderLeaseTimestampCell(timestamp: protos.cockroach.util.hlc.ITimestamp) { 32 if (_.isNil(timestamp)) { 33 return this.renderLeaseCell("<no value>"); 34 } 35 36 const value = Print.Timestamp(timestamp); 37 return this.renderLeaseCell(value, `${value}\n${timestamp.wall_time.toString()}`); 38 } 39 40 render() { 41 const { info } = this.props; 42 // TODO(bram): Maybe search for the latest lease record instead of just trusting the 43 // leader? 44 const rangeID = info.state.state.desc.range_id; 45 const header = ( 46 <h2 className="base-heading"> 47 Lease History (from {Print.ReplicaID(rangeID, RangeInfo.GetLocalReplica(info))}) 48 </h2> 49 ); 50 if (_.isEmpty(info.lease_history)) { 51 return ( 52 <div> 53 {header} 54 <h3>There is no lease history for this range</h3> 55 </div> 56 ); 57 } 58 59 const isEpoch = Lease.IsEpoch(_.head(info.lease_history)); 60 const leaseHistory = _.reverse(info.lease_history); 61 return ( 62 <div> 63 {header} 64 <table className="lease-table"> 65 <tbody> 66 <tr className="lease-table__row lease-table__row--header"> 67 <th className="lease-table__cell lease-table__cell--header">Replica</th> 68 { 69 isEpoch ? <th className="lease-table__cell lease-table__cell--header">Epoch</th> : null 70 } 71 <th className="lease-table__cell lease-table__cell--header">Proposed</th> 72 <th className="lease-table__cell lease-table__cell--header">Proposed Delta</th> 73 { 74 !isEpoch ? <th className="lease-table__cell lease-table__cell--header">Expiration</th> : null 75 } 76 <th className="lease-table__cell lease-table__cell--header">Start</th> 77 <th className="lease-table__cell lease-table__cell--header">Start Delta</th> 78 </tr> 79 { 80 _.map(leaseHistory, (lease, key) => { 81 let prevProposedTimestamp: protos.cockroach.util.hlc.ITimestamp = null; 82 let prevStart: protos.cockroach.util.hlc.ITimestamp = null; 83 if (key < leaseHistory.length - 1) { 84 prevProposedTimestamp = leaseHistory[key + 1].proposed_ts; 85 prevStart = leaseHistory[key + 1].start; 86 } 87 return ( 88 <tr key={key} className="lease-table__row"> 89 {this.renderLeaseCell(Print.ReplicaID(rangeID, lease.replica))} 90 {isEpoch ? this.renderLeaseCell(`n${lease.replica.node_id}, ${lease.epoch.toString()}`) : null} 91 {this.renderLeaseTimestampCell(lease.proposed_ts)} 92 {this.renderLeaseCell(Print.TimestampDelta(lease.proposed_ts, prevProposedTimestamp))} 93 {!isEpoch ? this.renderLeaseTimestampCell(lease.expiration) : null} 94 {this.renderLeaseTimestampCell(lease.start)} 95 {this.renderLeaseCell(Print.TimestampDelta(lease.start, prevStart))} 96 </tr> 97 ); 98 }) 99 } 100 </tbody> 101 </table> 102 </div> 103 ); 104 } 105 }