github.com/geph-official/geph2@v0.22.6-0.20210211030601-f527cb59b0df/cmd/geph-client/stats.go (about) 1 package main 2 3 import ( 4 "archive/zip" 5 "encoding/json" 6 "fmt" 7 "net/http" 8 "os" 9 "runtime" 10 "runtime/pprof" 11 "strings" 12 "sync" 13 "sync/atomic" 14 "time" 15 16 "github.com/geph-official/geph2/libs/bdclient" 17 log "github.com/sirupsen/logrus" 18 ) 19 20 type stats struct { 21 Connected bool 22 PublicIP string 23 UpBytes uint64 24 DownBytes uint64 25 MinPing uint64 26 PingTime time.Time 27 Username string 28 Tier string 29 PayTxes []bdclient.PaymentTx 30 Expiry time.Time 31 LogLines []string 32 Bridges map[string]int 33 //bridgeThunk func() []niaucchi4.LinkInfo 34 35 lock sync.Mutex 36 } 37 38 var statsCollector = &stats{} 39 40 func useStats(f func(sc *stats)) { 41 statsCollector.lock.Lock() 42 defer statsCollector.lock.Unlock() 43 f(statsCollector) 44 } 45 46 func handleKill(w http.ResponseWriter, r *http.Request) { 47 log.Println("dying on command") 48 go func() { 49 time.Sleep(time.Millisecond * 100) 50 os.Exit(0) 51 }() 52 } 53 54 func handleStats(w http.ResponseWriter, r *http.Request) { 55 w.Header().Add("Access-Control-Allow-Origin", "*") 56 var bts []byte 57 useStats(func(sc *stats) { 58 sc.Bridges = make(map[string]int) 59 // bridges 60 if !direct { 61 trackerMap.Range(func(key, value interface{}) bool { 62 v := int(atomic.LoadInt64(value.(*int64))) 63 if v > 0 { 64 sc.Bridges[key.(string)] = v 65 } 66 return true 67 }) 68 } 69 ll := sc.LogLines 70 sc.LogLines = nil 71 var err error 72 bts, err = json.Marshal(sc) 73 if err != nil { 74 panic(err) 75 } 76 sc.LogLines = ll 77 }) 78 w.Header().Add("content-type", "application/json") 79 w.Write(bts) 80 } 81 82 func handleDebugPack(w http.ResponseWriter, r *http.Request) { 83 w.Header().Add("Content-Disposition", fmt.Sprintf("attachment; filename=\"geph-logs-%v-%v.zip\"", username, time.Now().Format(time.RFC3339))) 84 w.Header().Add("content-type", "application/zip") 85 zwriter := zip.NewWriter(w) 86 defer zwriter.Close() 87 logFile, err := zwriter.Create("logs.txt") 88 if err != nil { 89 return 90 } 91 useStats(func(sc *stats) { 92 for _, line := range sc.LogLines { 93 fmt.Fprintln(logFile, line) 94 } 95 }) 96 straceFile, err := zwriter.Create("stacktrace.txt") 97 if err != nil { 98 return 99 } 100 buf := make([]byte, 8192) 101 for { 102 n := runtime.Stack(buf, true) 103 if n < len(buf) { 104 buf = buf[:n] 105 break 106 } 107 buf = append(buf, buf...) 108 } 109 straceFile.Write(buf) 110 heapprofFile, err := zwriter.Create("heap.pprof") 111 pprof.WriteHeapProfile(heapprofFile) 112 } 113 114 func handleLogs(w http.ResponseWriter, r *http.Request) { 115 w.Header().Add("Access-Control-Allow-Origin", "*") 116 var bts []byte 117 useStats(func(sc *stats) { 118 for _, line := range sc.LogLines { 119 fmt.Fprintln(w, line) 120 } 121 }) 122 w.Header().Add("content-type", "text/plain") 123 w.Write(bts) 124 } 125 126 func handleProxyPac(w http.ResponseWriter, r *http.Request) { 127 w.Write([]byte(fmt.Sprintf(`function FindProxyForURL(url, host) 128 { 129 return "PROXY %v"; 130 } 131 `, strings.Replace(httpAddr, strings.Split(httpAddr, ":")[0], "localhost", -1)))) 132 } 133 134 func handleStacktrace(w http.ResponseWriter, r *http.Request) { 135 buf := make([]byte, 8192) 136 for { 137 n := runtime.Stack(buf, true) 138 if n < len(buf) { 139 buf = buf[:n] 140 break 141 } 142 buf = append(buf, buf...) 143 } 144 w.Write(buf) 145 }