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