diff --git a/pkg/apiserver/proxy.go b/pkg/apiserver/proxy.go index 6a3609ea8bf..1e8bc9c759c 100644 --- a/pkg/apiserver/proxy.go +++ b/pkg/apiserver/proxy.go @@ -82,16 +82,25 @@ type ProxyHandler struct { } func (r *ProxyHandler) ServeHTTP(w http.ResponseWriter, req *http.Request) { + var verb string + var apiResource string + var httpCode int + reqStart := time.Now() + defer func() { monitor("proxy", verb, apiResource, httpCode, reqStart) }() + requestInfo, err := r.apiRequestInfoResolver.GetAPIRequestInfo(req) if err != nil { notFound(w, req) + httpCode = http.StatusNotFound return } + verb = requestInfo.Verb namespace, resource, parts := requestInfo.Namespace, requestInfo.Resource, requestInfo.Parts ctx := api.WithNamespace(api.NewContext(), namespace) if len(parts) < 2 { notFound(w, req) + httpCode = http.StatusNotFound return } id := parts[1] @@ -110,13 +119,15 @@ func (r *ProxyHandler) ServeHTTP(w http.ResponseWriter, req *http.Request) { if !ok { httplog.LogOf(req, w).Addf("'%v' has no storage object", resource) notFound(w, req) + httpCode = http.StatusNotFound return } + apiResource = resource redirector, ok := storage.(Redirector) if !ok { httplog.LogOf(req, w).Addf("'%v' is not a redirector", resource) - errorJSON(errors.NewMethodNotSupported(resource, "proxy"), r.codec, w) + httpCode = errorJSON(errors.NewMethodNotSupported(resource, "proxy"), r.codec, w) return } @@ -125,11 +136,13 @@ func (r *ProxyHandler) ServeHTTP(w http.ResponseWriter, req *http.Request) { httplog.LogOf(req, w).Addf("Error getting ResourceLocation: %v", err) status := errToAPIStatus(err) writeJSON(status.Code, r.codec, status, w) + httpCode = status.Code return } if location == "" { httplog.LogOf(req, w).Addf("ResourceLocation for %v returned ''", id) notFound(w, req) + httpCode = http.StatusNotFound return } @@ -137,6 +150,7 @@ func (r *ProxyHandler) ServeHTTP(w http.ResponseWriter, req *http.Request) { if err != nil { status := errToAPIStatus(err) writeJSON(status.Code, r.codec, status, w) + httpCode = status.Code return } if destURL.Scheme == "" { @@ -151,8 +165,10 @@ func (r *ProxyHandler) ServeHTTP(w http.ResponseWriter, req *http.Request) { status := errToAPIStatus(err) writeJSON(status.Code, r.codec, status, w) notFound(w, req) + httpCode = status.Code return } + httpCode = http.StatusOK newReq.Header = req.Header proxy := httputil.NewSingleHostReverseProxy(&url.URL{Scheme: "http", Host: destURL.Host}) diff --git a/pkg/apiserver/validator.go b/pkg/apiserver/validator.go index d73a418c530..76b25a069ec 100644 --- a/pkg/apiserver/validator.go +++ b/pkg/apiserver/validator.go @@ -23,6 +23,7 @@ import ( "net" "net/http" "strconv" + "time" "github.com/GoogleCloudPlatform/kubernetes/pkg/probe" ) @@ -72,6 +73,10 @@ type ServerStatus struct { } func (v *validator) ServeHTTP(w http.ResponseWriter, r *http.Request) { + var httpCode int + reqStart := time.Now() + defer func() { monitor("validate", "get", "", httpCode, reqStart) }() + reply := []ServerStatus{} for name, server := range v.servers() { status, msg, err := server.check(v.client) @@ -85,11 +90,13 @@ func (v *validator) ServeHTTP(w http.ResponseWriter, r *http.Request) { } data, err := json.MarshalIndent(reply, "", " ") if err != nil { - w.WriteHeader(http.StatusInternalServerError) + httpCode = http.StatusInternalServerError + w.WriteHeader(httpCode) w.Write([]byte(err.Error())) return } - w.WriteHeader(http.StatusOK) + httpCode = http.StatusOK + w.WriteHeader(httpCode) w.Write(data) } diff --git a/pkg/apiserver/watch.go b/pkg/apiserver/watch.go index 4b2b4e17ef9..9f6578be991 100644 --- a/pkg/apiserver/watch.go +++ b/pkg/apiserver/watch.go @@ -22,6 +22,7 @@ import ( "path" "regexp" "strings" + "time" "github.com/GoogleCloudPlatform/kubernetes/pkg/api" "github.com/GoogleCloudPlatform/kubernetes/pkg/api/errors" @@ -83,39 +84,51 @@ func isWebsocketRequest(req *http.Request) bool { // ServeHTTP processes watch requests. func (h *WatchHandler) ServeHTTP(w http.ResponseWriter, req *http.Request) { + var verb string + var apiResource string + var httpCode int + reqStart := time.Now() + defer func() { monitor("watch", verb, apiResource, httpCode, reqStart) }() + if req.Method != "GET" { notFound(w, req) + httpCode = http.StatusNotFound return } requestInfo, err := h.apiRequestInfoResolver.GetAPIRequestInfo(req) if err != nil { notFound(w, req) + httpCode = http.StatusNotFound return } + verb = requestInfo.Verb ctx := api.WithNamespace(api.NewContext(), requestInfo.Namespace) storage := h.storage[requestInfo.Resource] if storage == nil { notFound(w, req) + httpCode = http.StatusNotFound return } + apiResource = requestInfo.Resource watcher, ok := storage.(ResourceWatcher) if !ok { - errorJSON(errors.NewMethodNotSupported(requestInfo.Resource, "watch"), h.codec, w) + httpCode = errorJSON(errors.NewMethodNotSupported(requestInfo.Resource, "watch"), h.codec, w) return } label, field, resourceVersion, err := getWatchParams(req.URL.Query()) if err != nil { - errorJSON(err, h.codec, w) + httpCode = errorJSON(err, h.codec, w) return } watching, err := watcher.Watch(ctx, label, field, resourceVersion) if err != nil { - errorJSON(err, h.codec, w) + httpCode = errorJSON(err, h.codec, w) return } + httpCode = http.StatusOK // TODO: This is one watch per connection. We want to multiplex, so that // multiple watches of the same thing don't create two watches downstream.