Change:
Currently we do not measure latency for REST operations. This is important for any component that performs non-watch operations (scheduler, controllers, kubelet). This is also prerequisite to actually make sure that all API calls take less than 1 sec ( ).
The apiserver is already , including for REST operations. You can scrape the metrics by hitting the /metrics HTTP endpoint.
Sorry, I was not clear in the description. I'm more interested on the client side and with more details so that I can measure things like: how long it takes to write bindings in scheduler how long it takes to update status in kubelet I'd think about it as a counterpart for apiserver stats.

Discussion:
<ins> /* Copyright 2015 Google Inc. All rights reserved. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ package metrics import ( "sync" "time" "github.com/prometheus/client_golang/prometheus" ) const restClientSubsystem = "rest_client" var ( RequestLatency = prometheus.NewSummaryVec( prometheus.SummaryOpts{ Subsystem: restClientSubsystem, Name:      "request_latency_microseconds", Help:      "Request latency in microseconds. Broken down by verb and URL", }, []string{"verb", "url"}, ) ) var registerMetrics sync.Once // Register all metrics. func Register() { // Register the metrics. registerMetrics.Do(func() { prometheus.MustRegister(RequestLatency) }) } // Gets the time since the specified start in microseconds. func SinceInMicroseconds(start time.Time) float64 { return float64(time.Since(start).Nanoseconds() / time.Microsecond.Nanoseconds()) } </ins>

"github.com/GoogleCloudPlatform/kubernetes/pkg/api" "github.com/GoogleCloudPlatform/kubernetes/pkg/api/errors" <ins> "github.com/GoogleCloudPlatform/kubernetes/pkg/client/metrics" </ins> "github.com/GoogleCloudPlatform/kubernetes/pkg/fields" "github.com/GoogleCloudPlatform/kubernetes/pkg/labels" "github.com/GoogleCloudPlatform/kubernetes/pkg/runtime"

// NewRequest creates a new request helper object for accessing runtime.Objects on a server. func NewRequest(client HTTPClient, verb string, baseURL *url.URL, apiVersion string, codec runtime.Codec, namespaceInQuery bool, preserveResourceCase bool) *Request { <ins> metrics.Register() </ins> return &Request{ client:  client, verb:    verb,

p = path.Join(p, r.resourceName, r.subresource, r.subpath) } <del> finalURL := *r.baseURL </del> <ins> finalURL := url.URL{} if r.baseURL != nil { finalURL = *r.baseURL } </ins> finalURL.Path = p query := url.Values{}

return finalURL.String() } <ins> // Similar to finalURL(), but if the request contains name of an object // (e.g. GET for a specific Pod) it will be substited with "<name>". func (r Request) finalURLTemplate() string { if len(r.resourceName) != 0 { r.resourceName = "<name>" } return r.finalURL() } </ins> // Watch attempts to begin watching the requested location. // Returns a watch.Interface, or an error. func (r *Request) Watch() (watch.Interface, error) {

//  * If the status code and body don't make sense together: *UnexpectedStatusError //  * http.Client.Do errors are returned directly. func (r *Request) Do() Result { <ins> start := time.Now() defer func() { metrics.RequestLatency.WithLabelValues(r.verb, r.finalURLTemplate()).Observe(metrics.SinceInMicroseconds(start)) }() </ins> body, err := r.DoRaw() if err != nil { return Result{err: err}