vitess.io/vitess@v0.16.2/go/vt/discovery/tablets_cache_status.go (about) 1 package discovery 2 3 import ( 4 "fmt" 5 "html/template" 6 "sort" 7 "strings" 8 9 "google.golang.org/protobuf/proto" 10 11 querypb "vitess.io/vitess/go/vt/proto/query" 12 topodatapb "vitess.io/vitess/go/vt/proto/topodata" 13 "vitess.io/vitess/go/vt/topo/topoproto" 14 ) 15 16 // TabletsCacheStatus is the current tablets for a cell/target. 17 type TabletsCacheStatus struct { 18 Cell string 19 Target *querypb.Target 20 TabletsStats TabletStatsList 21 } 22 23 // TabletStatsList is used for sorting. 24 type TabletStatsList []*TabletHealth 25 26 // Len is part of sort.Interface. 27 func (tsl TabletStatsList) Len() int { 28 return len(tsl) 29 } 30 31 // Less is part of sort.Interface 32 func (tsl TabletStatsList) Less(i, j int) bool { 33 name1 := topoproto.TabletAliasString(tsl[i].Tablet.Alias) 34 name2 := topoproto.TabletAliasString(tsl[j].Tablet.Alias) 35 return name1 < name2 36 } 37 38 // Swap is part of sort.Interface 39 func (tsl TabletStatsList) Swap(i, j int) { 40 tsl[i], tsl[j] = tsl[j], tsl[i] 41 } 42 43 func (tsl TabletStatsList) deepEqual(other TabletStatsList) bool { 44 if len(tsl) != len(other) { 45 return false 46 } 47 for i, th := range tsl { 48 o := other[i] 49 if !th.DeepEqual(o) { 50 return false 51 } 52 } 53 return true 54 } 55 56 // StatusAsHTML returns an HTML version of the status. 57 func (tcs *TabletsCacheStatus) StatusAsHTML() template.HTML { 58 tLinks := make([]string, 0, 1) 59 if tcs.TabletsStats != nil { 60 sort.Sort(tcs.TabletsStats) 61 } 62 for _, ts := range tcs.TabletsStats { 63 color := "green" 64 extra := "" 65 if ts.LastError != nil { 66 color = "red" 67 extra = fmt.Sprintf(" (%v)", ts.LastError) 68 } else if !ts.Serving { 69 color = "red" 70 extra = " (Not Serving)" 71 } else if ts.Target.TabletType == topodatapb.TabletType_PRIMARY { 72 extra = fmt.Sprintf(" (PrimaryTermStartTime: %v)", ts.PrimaryTermStartTime) 73 } else { 74 extra = fmt.Sprintf(" (RepLag: %v)", ts.Stats.ReplicationLagSeconds) 75 } 76 name := topoproto.TabletAliasString(ts.Tablet.Alias) 77 tLinks = append(tLinks, fmt.Sprintf(`<a href="%s" style="color:%v">%v</a>%v`, ts.getTabletDebugURL(), color, name, extra)) 78 } 79 return template.HTML(strings.Join(tLinks, "<br>")) 80 } 81 82 func (tcs *TabletsCacheStatus) deepEqual(otcs *TabletsCacheStatus) bool { 83 return tcs.Cell == otcs.Cell && 84 proto.Equal(tcs.Target, otcs.Target) && 85 tcs.TabletsStats.deepEqual(otcs.TabletsStats) 86 } 87 88 // TabletsCacheStatusList is used for sorting. 89 type TabletsCacheStatusList []*TabletsCacheStatus 90 91 // Len is part of sort.Interface. 92 func (tcsl TabletsCacheStatusList) Len() int { 93 return len(tcsl) 94 } 95 96 // Less is part of sort.Interface 97 func (tcsl TabletsCacheStatusList) Less(i, j int) bool { 98 return tcsl[i].Cell+"."+tcsl[i].Target.Keyspace+"."+tcsl[i].Target.Shard+"."+string(tcsl[i].Target.TabletType) < 99 tcsl[j].Cell+"."+tcsl[j].Target.Keyspace+"."+tcsl[j].Target.Shard+"."+string(tcsl[j].Target.TabletType) 100 } 101 102 // Swap is part of sort.Interface 103 func (tcsl TabletsCacheStatusList) Swap(i, j int) { 104 tcsl[i], tcsl[j] = tcsl[j], tcsl[i] 105 } 106 107 func (tcsl TabletsCacheStatusList) deepEqual(other TabletsCacheStatusList) bool { 108 if len(tcsl) != len(other) { 109 return false 110 } 111 for i, tcs := range tcsl { 112 otcs := other[i] 113 if !tcs.deepEqual(otcs) { 114 return false 115 } 116 } 117 return true 118 }