vitess.io/vitess@v0.16.2/go/vt/srvtopo/status.go (about) 1 /* 2 Copyright 2021 The Vitess Authors. 3 4 Licensed under the Apache License, Version 2.0 (the "License"); 5 you may not use this file except in compliance with the License. 6 You may obtain a copy of the License at 7 8 http://www.apache.org/licenses/LICENSE-2.0 9 10 Unless required by applicable law or agreed to in writing, software 11 distributed under the License is distributed on an "AS IS" BASIS, 12 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 See the License for the specific language governing permissions and 14 limitations under the License. 15 */ 16 17 package srvtopo 18 19 import ( 20 "context" 21 "html/template" 22 "sort" 23 "time" 24 25 topodatapb "vitess.io/vitess/go/vt/proto/topodata" 26 ) 27 28 // TopoTemplate is the HTML to use to display the 29 // ResilientServerCacheStatus object 30 const TopoTemplate = ` 31 <style> 32 table { 33 border-collapse: collapse; 34 } 35 td, th { 36 border: 1px solid #999; 37 padding: 0.2rem; 38 } 39 </style> 40 <table> 41 <tr> 42 <th colspan="4">SrvKeyspace Names Cache</th> 43 </tr> 44 <tr> 45 <th>Cell</th> 46 <th>SrvKeyspace Names</th> 47 <th>TTL</th> 48 <th>Error</th> 49 </tr> 50 {{range $i, $skn := .SrvKeyspaceNames}} 51 <tr> 52 <td>{{github_com_vitessio_vitess_vtctld_srv_cell $skn.Cell}}</td> 53 <td>{{range $j, $value := $skn.Value}}{{github_com_vitessio_vitess_vtctld_srv_keyspace $skn.Cell $value}} {{end}}</td> 54 <td>{{github_com_vitessio_vitess_srvtopo_ttl_time $skn.ExpirationTime}}</td> 55 <td>{{if $skn.LastError}}({{github_com_vitessio_vitess_srvtopo_time_since $skn.LastQueryTime}}Ago) {{$skn.LastError}}{{end}}</td> 56 </tr> 57 {{end}} 58 </table> 59 <br> 60 <table> 61 <tr> 62 <th colspan="5">SrvKeyspace Cache</th> 63 </tr> 64 <tr> 65 <th>Cell</th> 66 <th>Keyspace</th> 67 <th>SrvKeyspace</th> 68 <th>TTL</th> 69 <th>Error</th> 70 </tr> 71 {{range $i, $sk := .SrvKeyspaces}} 72 <tr> 73 <td>{{github_com_vitessio_vitess_vtctld_srv_cell $sk.Cell}}</td> 74 <td>{{github_com_vitessio_vitess_vtctld_srv_keyspace $sk.Cell $sk.Keyspace}}</td> 75 <td>{{$sk.StatusAsHTML}}</td> 76 <td>{{github_com_vitessio_vitess_srvtopo_ttl_time $sk.ExpirationTime}}</td> 77 <td>{{if $sk.LastError}}({{github_com_vitessio_vitess_srvtopo_time_since $sk.LastErrorTime}} Ago) {{$sk.LastError}}{{end}}</td> 78 </tr> 79 {{end}} 80 </table> 81 ` 82 83 // The next few structures and methods are used to get a displayable 84 // version of the cache in a status page. 85 86 // SrvKeyspaceNamesCacheStatus is the current value for SrvKeyspaceNames 87 type SrvKeyspaceNamesCacheStatus struct { 88 Cell string 89 Value []string 90 ExpirationTime time.Time 91 LastQueryTime time.Time 92 LastError error 93 LastErrorCtx context.Context 94 } 95 96 // SrvKeyspaceNamesCacheStatusList is used for sorting 97 type SrvKeyspaceNamesCacheStatusList []*SrvKeyspaceNamesCacheStatus 98 99 // Len is part of sort.Interface 100 func (skncsl SrvKeyspaceNamesCacheStatusList) Len() int { 101 return len(skncsl) 102 } 103 104 // Less is part of sort.Interface 105 func (skncsl SrvKeyspaceNamesCacheStatusList) Less(i, j int) bool { 106 return skncsl[i].Cell < skncsl[j].Cell 107 } 108 109 // Swap is part of sort.Interface 110 func (skncsl SrvKeyspaceNamesCacheStatusList) Swap(i, j int) { 111 skncsl[i], skncsl[j] = skncsl[j], skncsl[i] 112 } 113 114 // SrvKeyspaceCacheStatus is the current value for a SrvKeyspace object 115 type SrvKeyspaceCacheStatus struct { 116 Cell string 117 Keyspace string 118 Value *topodatapb.SrvKeyspace 119 ExpirationTime time.Time 120 LastErrorTime time.Time 121 LastError error 122 } 123 124 // StatusAsHTML returns an HTML version of our status. 125 // It works best if there is data in the cache. 126 func (st *SrvKeyspaceCacheStatus) StatusAsHTML() template.HTML { 127 if st.Value == nil { 128 return template.HTML("No Data") 129 } 130 131 result := "<b>Partitions:</b><br>" 132 for _, keyspacePartition := range st.Value.Partitions { 133 result += " <b>" + keyspacePartition.ServedType.String() + ":</b>" 134 for _, shard := range keyspacePartition.ShardReferences { 135 result += " " + shard.Name 136 } 137 result += "<br>" 138 } 139 140 if len(st.Value.ServedFrom) > 0 { 141 result += "<b>ServedFrom:</b><br>" 142 for _, sf := range st.Value.ServedFrom { 143 result += " <b>" + sf.TabletType.String() + ":</b> " + sf.Keyspace + "<br>" 144 } 145 } 146 147 return template.HTML(result) 148 } 149 150 // SrvKeyspaceCacheStatusList is used for sorting 151 type SrvKeyspaceCacheStatusList []*SrvKeyspaceCacheStatus 152 153 // Len is part of sort.Interface 154 func (skcsl SrvKeyspaceCacheStatusList) Len() int { 155 return len(skcsl) 156 } 157 158 // Less is part of sort.Interface 159 func (skcsl SrvKeyspaceCacheStatusList) Less(i, j int) bool { 160 return skcsl[i].Cell+"."+skcsl[i].Keyspace < 161 skcsl[j].Cell+"."+skcsl[j].Keyspace 162 } 163 164 // Swap is part of sort.Interface 165 func (skcsl SrvKeyspaceCacheStatusList) Swap(i, j int) { 166 skcsl[i], skcsl[j] = skcsl[j], skcsl[i] 167 } 168 169 // ResilientServerCacheStatus has the full status of the cache 170 type ResilientServerCacheStatus struct { 171 SrvKeyspaceNames SrvKeyspaceNamesCacheStatusList 172 SrvKeyspaces SrvKeyspaceCacheStatusList 173 } 174 175 // CacheStatus returns a displayable version of the cache 176 func (server *ResilientServer) CacheStatus() *ResilientServerCacheStatus { 177 result := &ResilientServerCacheStatus{ 178 SrvKeyspaceNames: server.srvKeyspaceNamesCacheStatus(), 179 SrvKeyspaces: server.srvKeyspaceCacheStatus(), 180 } 181 sort.Sort(result.SrvKeyspaceNames) 182 sort.Sort(result.SrvKeyspaces) 183 return result 184 } 185 186 // Returns the ttl for the cached entry or "Expired" if it is in the past 187 func ttlTime(expirationTime time.Time) template.HTML { 188 ttl := time.Until(expirationTime).Round(time.Second) 189 if ttl < 0 { 190 return template.HTML("<b>Expired</b>") 191 } 192 return template.HTML(ttl.String()) 193 } 194 195 func timeSince(t time.Time) template.HTML { 196 return template.HTML(time.Since(t).Round(time.Second).String()) 197 } 198 199 // StatusFuncs is required for CacheStatus) to work properly. 200 // We don't register them inside servenv directly so we don't introduce 201 // a dependency here. 202 var StatusFuncs = template.FuncMap{ 203 "github_com_vitessio_vitess_srvtopo_ttl_time": ttlTime, 204 "github_com_vitessio_vitess_srvtopo_time_since": timeSince, 205 }