diff --git a/capture/capture.go b/capture/capture.go index dcdc30e3..53ff59da 100644 --- a/capture/capture.go +++ b/capture/capture.go @@ -3,6 +3,7 @@ package capture import ( "context" "errors" + "expvar" "fmt" "io" "log" @@ -22,9 +23,20 @@ import ( "github.com/google/gopacket/pcap" ) +var stats *expvar.Map + +func init() { + stats = expvar.NewMap("raw") + stats.Init() +} + // PacketHandler is a function that is used to handle packets type PacketHandler func(*tcp.Packet) +type PcapStatProvider interface { + Stats() (*pcap.Stats, error) +} + // PcapOptions options that can be set on a pcap capture handle, // these options take effect on inactive pcap handles type PcapOptions struct { @@ -339,10 +351,19 @@ func (l *Listener) read(handler PacketHandler) { } } + timer := time.NewTicker(1 * time.Second) + for { select { case <-l.quit: return + case <-timer.C: + if h, ok := hndl.handler.(PcapStatProvider); ok { + s, _ := h.Stats() + stats.Add("packets_received", int64(s.PacketsReceived)) + stats.Add("packets_dropped", int64(s.PacketsDropped)) + stats.Add("packets_if_dropped", int64(s.PacketsIfDropped)) + } default: data, ci, err := hndl.handler.ReadPacketData() if err == nil { diff --git a/gor.go b/gor.go index d7134e11..0598b709 100644 --- a/gor.go +++ b/gor.go @@ -3,12 +3,13 @@ package main import ( - _ "expvar" + "expvar" "flag" + "fmt" "log" "net/http" "net/http/httputil" - _ "net/http/pprof" + httppptof "net/http/pprof" "os" "os/signal" "runtime" @@ -22,6 +23,35 @@ var ( memprofile = flag.String("memprofile", "", "write memory profile to this file") ) +func init() { + var defaultServeMux http.ServeMux + http.DefaultServeMux = &defaultServeMux + + http.HandleFunc("/debug/vars", func(w http.ResponseWriter, r *http.Request) { + w.Header().Set("Content-Type", "application/json; charset=utf-8") + fmt.Fprintf(w, "{\n") + first := true + expvar.Do(func(kv expvar.KeyValue) { + if kv.Key == "memstats" || kv.Key == "cmdline" { + return + } + + if !first { + fmt.Fprintf(w, ",\n") + } + first = false + fmt.Fprintf(w, "%q: %s", kv.Key, kv.Value) + }) + fmt.Fprintf(w, "\n}\n") + }) + + http.HandleFunc("/debug/pprof/", httppptof.Index) + http.HandleFunc("/debug/pprof/cmdline", httppptof.Cmdline) + http.HandleFunc("/debug/pprof/profile", httppptof.Profile) + http.HandleFunc("/debug/pprof/symbol", httppptof.Symbol) + http.HandleFunc("/debug/pprof/trace", httppptof.Trace) +} + func loggingMiddleware(addr string, next http.Handler) http.Handler { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { if r.URL.Path == "/loop" {