From d7100fd9bcb9bfb22da36cb34b6464e7cae8ee70 Mon Sep 17 00:00:00 2001 From: Jakob Borg Date: Tue, 7 Apr 2015 21:45:22 +0200 Subject: [PATCH] Add HTTP request tracing --- cmd/syncthing/debug.go | 3 ++- cmd/syncthing/gui.go | 29 +++++++++++++++++++++++++++++ cmd/syncthing/main.go | 1 + 3 files changed, 32 insertions(+), 1 deletion(-) diff --git a/cmd/syncthing/debug.go b/cmd/syncthing/debug.go index ea8cac3b..36e297aa 100644 --- a/cmd/syncthing/debug.go +++ b/cmd/syncthing/debug.go @@ -12,5 +12,6 @@ import ( ) var ( - debugNet = strings.Contains(os.Getenv("STTRACE"), "net") || os.Getenv("STTRACE") == "all" + debugNet = strings.Contains(os.Getenv("STTRACE"), "net") || os.Getenv("STTRACE") == "all" + debugHTTP = strings.Contains(os.Getenv("STTRACE"), "http") || os.Getenv("STTRACE") == "all" ) diff --git a/cmd/syncthing/gui.go b/cmd/syncthing/gui.go index 0e6691bb..25cac92d 100644 --- a/cmd/syncthing/gui.go +++ b/cmd/syncthing/gui.go @@ -18,6 +18,7 @@ import ( "net/http" "os" "path/filepath" + "reflect" "runtime" "strconv" "strings" @@ -180,6 +181,10 @@ func startGUI(cfg config.GUIConfiguration, assetDir string, m *model.Model) erro handler = redirectToHTTPSMiddleware(handler) } + if debugHTTP { + handler = debugMiddleware(handler) + } + srv := http.Server{ Handler: handler, ReadTimeout: 10 * time.Second, @@ -210,6 +215,30 @@ func getPostHandler(get, post http.Handler) http.Handler { }) } +func debugMiddleware(h http.Handler) http.Handler { + return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + t0 := time.Now() + h.ServeHTTP(w, r) + ms := 1000 * time.Since(t0).Seconds() + + // The variable `w` is most likely a *http.response, which we can't do + // much with since it's a non exported type. We can however peek into + // it with reflection to get at the status code and number of bytes + // written. + var status, written int64 + if rw := reflect.Indirect(reflect.ValueOf(w)); rw.IsValid() && rw.Kind() == reflect.Struct { + if rf := rw.FieldByName("status"); rf.IsValid() && rf.Kind() == reflect.Int { + status = rf.Int() + } + if rf := rw.FieldByName("written"); rf.IsValid() && rf.Kind() == reflect.Int64 { + written = rf.Int() + } + } + + l.Debugf("http: %s %q: status %d, %d bytes in %.02f ms", r.Method, r.URL.String(), status, written, ms) + }) +} + func redirectToHTTPSMiddleware(h http.Handler) http.Handler { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { // Add a generous access-control-allow-origin header since we may be diff --git a/cmd/syncthing/main.go b/cmd/syncthing/main.go index a7e885f0..a069dd5a 100644 --- a/cmd/syncthing/main.go +++ b/cmd/syncthing/main.go @@ -143,6 +143,7 @@ are mostly useful for developers. Use with care. - "discover" (the discover package) - "events" (the events package) - "files" (the files package) + - "http" (the main package; HTTP requests) - "net" (the main package; connections & network messages) - "model" (the model package) - "scanner" (the scanner package)