vitess.io/vitess@v0.16.2/go/vt/vtgate/debugenv.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 vtgate 18 19 import ( 20 "encoding/json" 21 "fmt" 22 "html" 23 "net/http" 24 "strconv" 25 "text/template" 26 "time" 27 28 "vitess.io/vitess/go/acl" 29 "vitess.io/vitess/go/vt/discovery" 30 "vitess.io/vitess/go/vt/log" 31 ) 32 33 var ( 34 debugEnvHeader = []byte(` 35 <thead><tr> 36 <th>Variable Name</th> 37 <th>Value</th> 38 <th>Action</th> 39 </tr></thead> 40 `) 41 debugEnvRow = template.Must(template.New("debugenv").Parse(` 42 <tr><form method="POST"> 43 <td>{{.VarName}}</td> 44 <td> 45 <input type="hidden" name="varname" value="{{.VarName}}"></input> 46 <input type="text" name="value" value="{{.Value}}"></input> 47 </td> 48 <td><input type="submit" name="Action" value="Modify"></input></td> 49 </form></tr> 50 `)) 51 gridTable = []byte(`<!DOCTYPE html> 52 <style type="text/css"> 53 table.gridtable { 54 font-family: verdana,arial,sans-serif; 55 font-size: 11px; 56 border-width: 1px; 57 border-collapse: collapse; table-layout:fixed; overflow: hidden; 58 } 59 table.gridtable th { 60 border-width: 1px; 61 padding: 8px; 62 border-style: solid; 63 background-color: #dedede; 64 white-space: nowrap; 65 } 66 table.gridtable td { 67 border-width: 1px; 68 padding: 5px; 69 border-style: solid; 70 } 71 table.gridtable th { 72 padding-left: 2em; 73 padding-right: 2em; 74 } 75 </style> 76 `) 77 startTable = []byte(` 78 <table class="gridtable"> 79 `) 80 endTable = []byte(` 81 </table> 82 `) 83 ) 84 85 type envValue struct { 86 VarName string 87 Value string 88 } 89 90 func debugEnvHandler(vtg *VTGate, w http.ResponseWriter, r *http.Request) { 91 if err := acl.CheckAccessHTTP(r, acl.ADMIN); err != nil { 92 acl.SendError(w, err) 93 return 94 } 95 96 var msg string 97 if r.Method == "POST" { 98 varname := r.FormValue("varname") 99 value := r.FormValue("value") 100 setIntVal := func(f func(int)) { 101 ival, err := strconv.Atoi(value) 102 if err != nil { 103 msg = fmt.Sprintf("Failed setting value for %v: %v", varname, err) 104 return 105 } 106 f(ival) 107 msg = fmt.Sprintf("Setting %v to: %v", varname, value) 108 } 109 setDurationVal := func(f func(time.Duration)) { 110 durationVal, err := time.ParseDuration(value) 111 if err != nil { 112 msg = fmt.Sprintf("Failed setting value for %v: %v", varname, err) 113 return 114 } 115 f(durationVal) 116 msg = fmt.Sprintf("Setting %v to: %v", varname, value) 117 } 118 switch varname { 119 case "discovery_low_replication_lag": 120 setDurationVal(discovery.SetLowReplicationLag) 121 case "discovery_high_replication_lag_minimum_serving": 122 setDurationVal(discovery.SetHighReplicationLagMinServing) 123 case "min_num_tablets": 124 setIntVal(discovery.SetMinNumTablets) 125 } 126 } 127 128 var vars []envValue 129 addIntVar := func(varname string, f func() int) { 130 vars = append(vars, envValue{ 131 VarName: varname, 132 Value: fmt.Sprintf("%v", f()), 133 }) 134 } 135 addDurationVar := func(varname string, f func() time.Duration) { 136 vars = append(vars, envValue{ 137 VarName: varname, 138 Value: fmt.Sprintf("%v", f()), 139 }) 140 } 141 addDurationVar("discovery_low_replication_lag", discovery.GetLowReplicationLag) 142 addDurationVar("discovery_high_replication_lag_minimum_serving", discovery.GetHighReplicationLagMinServing) 143 addIntVar("min_num_tablets", discovery.GetMinNumTablets) 144 145 format := r.FormValue("format") 146 if format == "json" { 147 mvars := make(map[string]string) 148 for _, v := range vars { 149 mvars[v.VarName] = v.Value 150 } 151 w.Header().Set("Content-Type", "application/json") 152 _ = json.NewEncoder(w).Encode(mvars) 153 return 154 } 155 156 w.Write(gridTable) 157 w.Write([]byte("<h3>Internal Variables</h3>\n")) 158 if msg != "" { 159 fmt.Fprintf(w, "<b>%s</b><br /><br />\n", html.EscapeString(msg)) 160 } 161 w.Write(startTable) 162 w.Write(debugEnvHeader) 163 for _, v := range vars { 164 if err := debugEnvRow.Execute(w, v); err != nil { 165 log.Errorf("debugenv: couldn't execute template: %v", err) 166 } 167 } 168 w.Write(endTable) 169 }