131 lines
		
	
	
		
			3.2 KiB
		
	
	
	
		
			Go
		
	
	
			
		
		
	
	
			131 lines
		
	
	
		
			3.2 KiB
		
	
	
	
		
			Go
		
	
	
// +build httpstats
 | 
						|
 | 
						|
package go9p
 | 
						|
 | 
						|
import (
 | 
						|
	"fmt"
 | 
						|
	"io"
 | 
						|
	"net/http"
 | 
						|
	"sync"
 | 
						|
)
 | 
						|
 | 
						|
var mux sync.RWMutex
 | 
						|
var stat map[string]http.Handler
 | 
						|
var httponce sync.Once
 | 
						|
 | 
						|
func register(s string, h http.Handler) {
 | 
						|
	mux.Lock()
 | 
						|
	if stat == nil {
 | 
						|
		stat = make(map[string]http.Handler)
 | 
						|
	}
 | 
						|
 | 
						|
	if h == nil {
 | 
						|
		delete(stat, s)
 | 
						|
	} else {
 | 
						|
		stat[s] = h
 | 
						|
	}
 | 
						|
	mux.Unlock()
 | 
						|
}
 | 
						|
func (srv *Srv) statsRegister() {
 | 
						|
	httponce.Do(func() {
 | 
						|
		http.HandleFunc("/go9p/", StatsHandler)
 | 
						|
		go http.ListenAndServe(":6060", nil)
 | 
						|
	})
 | 
						|
 | 
						|
	register("/go9p/srv/"+srv.Id, srv)
 | 
						|
}
 | 
						|
 | 
						|
func (srv *Srv) statsUnregister() {
 | 
						|
	register("/go9p/srv/"+srv.Id, nil)
 | 
						|
}
 | 
						|
 | 
						|
func (srv *Srv) ServeHTTP(c http.ResponseWriter, r *http.Request) {
 | 
						|
	io.WriteString(c, fmt.Sprintf("<html><body><h1>Server %s</h1>", srv.Id))
 | 
						|
	defer io.WriteString(c, "</body></html>")
 | 
						|
 | 
						|
	// connections
 | 
						|
	io.WriteString(c, "<h2>Connections</h2><p>")
 | 
						|
	srv.Lock()
 | 
						|
	defer srv.Unlock()
 | 
						|
	if len(srv.conns) == 0 {
 | 
						|
		io.WriteString(c, "none")
 | 
						|
		return
 | 
						|
	}
 | 
						|
 | 
						|
	for _, conn := range srv.conns {
 | 
						|
		io.WriteString(c, fmt.Sprintf("<a href='/go9p/srv/%s/conn/%s'>%s</a><br>", srv.Id, conn.Id, conn.Id))
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
func (conn *Conn) statsRegister() {
 | 
						|
	register("/go9p/srv/"+conn.Srv.Id+"/conn/"+conn.Id, conn)
 | 
						|
}
 | 
						|
 | 
						|
func (conn *Conn) statsUnregister() {
 | 
						|
	register("/go9p/srv/"+conn.Srv.Id+"/conn/"+conn.Id, nil)
 | 
						|
}
 | 
						|
 | 
						|
func (conn *Conn) ServeHTTP(c http.ResponseWriter, r *http.Request) {
 | 
						|
	io.WriteString(c, fmt.Sprintf("<html><body><h1>Connection %s/%s</h1>", conn.Srv.Id, conn.Id))
 | 
						|
	defer io.WriteString(c, "</body></html>")
 | 
						|
 | 
						|
	// statistics
 | 
						|
	conn.Lock()
 | 
						|
	io.WriteString(c, fmt.Sprintf("<p>Number of processed requests: %d", conn.nreqs))
 | 
						|
	io.WriteString(c, fmt.Sprintf("<br>Sent %v bytes", conn.rsz))
 | 
						|
	io.WriteString(c, fmt.Sprintf("<br>Received %v bytes", conn.tsz))
 | 
						|
	io.WriteString(c, fmt.Sprintf("<br>Pending requests: %d max %d", conn.npend, conn.maxpend))
 | 
						|
	io.WriteString(c, fmt.Sprintf("<br>Number of reads: %d", conn.nreads))
 | 
						|
	io.WriteString(c, fmt.Sprintf("<br>Number of writes: %d", conn.nwrites))
 | 
						|
	conn.Unlock()
 | 
						|
 | 
						|
	// fcalls
 | 
						|
	if conn.Debuglevel&DbgLogFcalls != 0 {
 | 
						|
		fs := conn.Srv.Log.Filter(conn, DbgLogFcalls)
 | 
						|
		io.WriteString(c, fmt.Sprintf("<h2>Last %d 9P messages</h2>", len(fs)))
 | 
						|
		for i, l := range fs {
 | 
						|
			fc := l.Data.(*Fcall)
 | 
						|
			if fc.Type == 0 {
 | 
						|
				continue
 | 
						|
			}
 | 
						|
 | 
						|
			lbl := ""
 | 
						|
			if fc.Type%2 == 0 {
 | 
						|
				// try to find the response for the T message
 | 
						|
				for j := i + 1; j < len(fs); j++ {
 | 
						|
					rc := fs[j].Data.(*Fcall)
 | 
						|
					if rc.Tag == fc.Tag {
 | 
						|
						lbl = fmt.Sprintf("<a href='#fc%d'>➴</a>", j)
 | 
						|
						break
 | 
						|
					}
 | 
						|
				}
 | 
						|
			} else {
 | 
						|
				// try to find the request for the R message
 | 
						|
				for j := i - 1; j >= 0; j-- {
 | 
						|
					tc := fs[j].Data.(*Fcall)
 | 
						|
					if tc.Tag == fc.Tag {
 | 
						|
						lbl = fmt.Sprintf("<a href='#fc%d'>➶</a>", j)
 | 
						|
						break
 | 
						|
					}
 | 
						|
				}
 | 
						|
			}
 | 
						|
 | 
						|
			io.WriteString(c, fmt.Sprintf("<br id='fc%d'>%d: %s%s", i, i, fc, lbl))
 | 
						|
		}
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
func StatsHandler(c http.ResponseWriter, r *http.Request) {
 | 
						|
	mux.RLock()
 | 
						|
	if v, ok := stat[r.URL.Path]; ok {
 | 
						|
		v.ServeHTTP(c, r)
 | 
						|
	} else if r.URL.Path == "/go9p/" {
 | 
						|
		io.WriteString(c, fmt.Sprintf("<html><body><br><h1>On offer: </h1><br>"))
 | 
						|
		for v := range stat {
 | 
						|
			io.WriteString(c, fmt.Sprintf("<a href='%s'>%s</a><br>", v, v))
 | 
						|
		}
 | 
						|
		io.WriteString(c, "</body></html>")
 | 
						|
	}
 | 
						|
	mux.RUnlock()
 | 
						|
}
 |