github.com/matrixorigin/matrixone@v1.2.0/pkg/perfcounter/http.go (about) 1 // Copyright 2023 Matrix Origin 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 package perfcounter 16 17 import ( 18 "fmt" 19 "github.com/matrixorigin/matrixone/pkg/util/metric/stats" 20 "io" 21 "net/http" 22 "reflect" 23 "sort" 24 "sync/atomic" 25 ) 26 27 func (c *CounterSet) ServeHTTP(w http.ResponseWriter, req *http.Request) { 28 fmt.Fprintf(w, ` 29 <style> 30 table, th, td { 31 border: 1px solid; 32 border-collapse: collapse; 33 font-family: monospace, monospace; 34 } 35 </style> 36 `) 37 38 v := reflect.ValueOf(c) 39 format(w, v, v.Type()) 40 } 41 42 func format(w io.Writer, v reflect.Value, t reflect.Type) { 43 switch val := v.Interface().(type) { 44 case atomic.Int64: 45 fmt.Fprintf(w, "%v", val.Load()) 46 case stats.Counter: 47 fmt.Fprintf(w, "%v", val.Load()) 48 49 default: 50 switch t.Kind() { 51 case reflect.Struct: 52 formatStruct(w, v, t) 53 case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: 54 fmt.Fprintf(w, "%v", v.Int()) 55 case reflect.Ptr, reflect.Interface: 56 format(w, v.Elem(), t.Elem()) 57 case reflect.Map: 58 formatMap(w, v, t) 59 case reflect.String: 60 fmt.Fprint(w, v.String()) 61 default: 62 panic(fmt.Sprintf("unknown kind: %v", t.Kind())) 63 } 64 } 65 } 66 67 func formatStruct(w io.Writer, v reflect.Value, t reflect.Type) { 68 fmt.Fprintf(w, "<table>") 69 defer fmt.Fprintf(w, "</table>") 70 for i, l := 0, t.NumField(); i < l; i++ { 71 fieldValue := v.Field(i) 72 if fieldValue.IsZero() { 73 continue 74 } 75 field := t.Field(i) 76 fmt.Fprintf(w, "<tr>") 77 fmt.Fprintf(w, "<td>%s</td>", field.Name) 78 fmt.Fprintf(w, "<td>") 79 format(w, fieldValue, fieldValue.Type()) 80 fmt.Fprintf(w, "</td>") 81 fmt.Fprintf(w, "</tr>") 82 } 83 } 84 85 func formatMap(w io.Writer, v reflect.Value, t reflect.Type) { 86 fmt.Fprintf(w, "<table>") 87 defer fmt.Fprintf(w, "</table>") 88 89 if t.Key().Kind() == reflect.String { 90 keyValues := v.MapKeys() 91 keys := make([]string, 0, v.Len()) 92 for _, keyValue := range keyValues { 93 keys = append(keys, keyValue.String()) 94 } 95 sort.Strings(keys) 96 for _, key := range keys { 97 fmt.Fprintf(w, "<tr>") 98 fmt.Fprint(w, "<td>") 99 fmt.Fprint(w, key) 100 fmt.Fprint(w, "</td>") 101 value := v.MapIndex(reflect.ValueOf(key)) 102 fmt.Fprint(w, "<td>") 103 format(w, value, value.Type()) 104 fmt.Fprint(w, "</td>") 105 fmt.Fprint(w, "</tr>") 106 } 107 108 } else { 109 iter := v.MapRange() 110 for iter.Next() { 111 value := iter.Value() 112 if value.IsZero() { 113 continue 114 } 115 key := iter.Key() 116 fmt.Fprintf(w, "<tr>") 117 fmt.Fprintf(w, "<td>") 118 format(w, key, key.Type()) 119 fmt.Fprintf(w, "</td>") 120 fmt.Fprintf(w, "<td>") 121 format(w, value, value.Type()) 122 fmt.Fprintf(w, "</td>") 123 fmt.Fprintf(w, "</tr>") 124 } 125 } 126 }