1// Copyright 2009 The Go Authors. All rights reserved. 2// Use of this source code is governed by a BSD-style 3// license that can be found in the LICENSE file. 4 5package rpc 6 7/* 8 Some HTML presented at http://machine:port/debug/rpc 9 Lists services, their methods, and some statistics, still rudimentary. 10*/ 11 12import ( 13 "fmt" 14 "html/template" 15 "net/http" 16 "slices" 17 "strings" 18) 19 20const debugText = `<html> 21 <body> 22 <title>Services</title> 23 {{range .}} 24 <hr> 25 Service {{.Name}} 26 <hr> 27 <table> 28 <th align=center>Method</th><th align=center>Calls</th> 29 {{range .Method}} 30 <tr> 31 <td align=left font=fixed>{{.Name}}({{.Type.ArgType}}, {{.Type.ReplyType}}) error</td> 32 <td align=center>{{.Type.NumCalls}}</td> 33 </tr> 34 {{end}} 35 </table> 36 {{end}} 37 </body> 38 </html>` 39 40var debug = template.Must(template.New("RPC debug").Parse(debugText)) 41 42// If set, print log statements for internal and I/O errors. 43var debugLog = false 44 45type debugMethod struct { 46 Type *methodType 47 Name string 48} 49 50type methodArray []debugMethod 51 52type debugService struct { 53 Service *service 54 Name string 55 Method []debugMethod 56} 57 58type serviceArray []debugService 59 60func (s serviceArray) Len() int { return len(s) } 61func (s serviceArray) Less(i, j int) bool { return s[i].Name < s[j].Name } 62func (s serviceArray) Swap(i, j int) { s[i], s[j] = s[j], s[i] } 63 64func (m methodArray) Len() int { return len(m) } 65func (m methodArray) Less(i, j int) bool { return m[i].Name < m[j].Name } 66func (m methodArray) Swap(i, j int) { m[i], m[j] = m[j], m[i] } 67 68type debugHTTP struct { 69 *Server 70} 71 72// Runs at /debug/rpc 73func (server debugHTTP) ServeHTTP(w http.ResponseWriter, req *http.Request) { 74 // Build a sorted version of the data. 75 var services serviceArray 76 server.serviceMap.Range(func(snamei, svci any) bool { 77 svc := svci.(*service) 78 ds := debugService{svc, snamei.(string), make([]debugMethod, 0, len(svc.method))} 79 for mname, method := range svc.method { 80 ds.Method = append(ds.Method, debugMethod{method, mname}) 81 } 82 slices.SortFunc(ds.Method, func(a, b debugMethod) int { 83 return strings.Compare(a.Name, b.Name) 84 }) 85 services = append(services, ds) 86 return true 87 }) 88 slices.SortFunc(services, func(a, b debugService) int { 89 return strings.Compare(a.Name, b.Name) 90 }) 91 err := debug.Execute(w, services) 92 if err != nil { 93 fmt.Fprintln(w, "rpc: error executing template:", err.Error()) 94 } 95} 96