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 }