mirror of
https://github.com/k3s-io/kubernetes.git
synced 2025-07-21 19:01:49 +00:00
track latency for http.ResponseWriter.Write
This commit is contained in:
parent
eca9085694
commit
1d1a44cf12
@ -17,11 +17,14 @@ limitations under the License.
|
|||||||
package filters
|
package filters
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
"time"
|
||||||
|
|
||||||
"k8s.io/apimachinery/pkg/util/sets"
|
"k8s.io/apimachinery/pkg/util/sets"
|
||||||
"k8s.io/apiserver/pkg/endpoints/request"
|
"k8s.io/apiserver/pkg/endpoints/request"
|
||||||
|
"k8s.io/apiserver/pkg/endpoints/responsewriter"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
@ -46,6 +49,32 @@ func WithLatencyTrackers(handler http.Handler) http.Handler {
|
|||||||
}
|
}
|
||||||
|
|
||||||
req = req.WithContext(request.WithLatencyTrackers(ctx))
|
req = req.WithContext(request.WithLatencyTrackers(ctx))
|
||||||
|
w = responsewriter.WrapForHTTP1Or2(&writeLatencyTracker{
|
||||||
|
ResponseWriter: w,
|
||||||
|
ctx: req.Context(),
|
||||||
|
})
|
||||||
|
|
||||||
handler.ServeHTTP(w, req)
|
handler.ServeHTTP(w, req)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var _ http.ResponseWriter = &writeLatencyTracker{}
|
||||||
|
var _ responsewriter.UserProvidedDecorator = &writeLatencyTracker{}
|
||||||
|
|
||||||
|
type writeLatencyTracker struct {
|
||||||
|
http.ResponseWriter
|
||||||
|
ctx context.Context
|
||||||
|
}
|
||||||
|
|
||||||
|
func (wt *writeLatencyTracker) Unwrap() http.ResponseWriter {
|
||||||
|
return wt.ResponseWriter
|
||||||
|
}
|
||||||
|
|
||||||
|
func (wt *writeLatencyTracker) Write(bs []byte) (int, error) {
|
||||||
|
startedAt := time.Now()
|
||||||
|
defer func() {
|
||||||
|
request.TrackResponseWriteLatency(wt.ctx, time.Since(startedAt))
|
||||||
|
}()
|
||||||
|
|
||||||
|
return wt.ResponseWriter.Write(bs)
|
||||||
|
}
|
||||||
|
@ -141,6 +141,13 @@ type LatencyTrackers struct {
|
|||||||
// the latency measured here will include the time spent writing the
|
// the latency measured here will include the time spent writing the
|
||||||
// serialized raw bytes to the http ResponseWriter object.
|
// serialized raw bytes to the http ResponseWriter object.
|
||||||
SerializationTracker DurationTracker
|
SerializationTracker DurationTracker
|
||||||
|
|
||||||
|
// ResponseWriteTracker tracks the latency incurred in writing the
|
||||||
|
// serialized raw bytes to the http ResponseWriter object (via the
|
||||||
|
// Write method) associated with the request.
|
||||||
|
// The Write method can be invoked multiple times, so we use a
|
||||||
|
// latency tracker that sums up the duration from each call.
|
||||||
|
ResponseWriteTracker DurationTracker
|
||||||
}
|
}
|
||||||
|
|
||||||
type latencyTrackersKeyType int
|
type latencyTrackersKeyType int
|
||||||
@ -164,6 +171,7 @@ func WithLatencyTrackersAndCustomClock(parent context.Context, c clock.Clock) co
|
|||||||
StorageTracker: newSumLatencyTracker(c),
|
StorageTracker: newSumLatencyTracker(c),
|
||||||
TransformTracker: newSumLatencyTracker(c),
|
TransformTracker: newSumLatencyTracker(c),
|
||||||
SerializationTracker: newSumLatencyTracker(c),
|
SerializationTracker: newSumLatencyTracker(c),
|
||||||
|
ResponseWriteTracker: newSumLatencyTracker(c),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -212,6 +220,16 @@ func TrackSerializeResponseObjectLatency(ctx context.Context, f func()) {
|
|||||||
f()
|
f()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TrackResponseWriteLatency is used to track latency incurred in writing
|
||||||
|
// the serialized raw bytes to the http ResponseWriter object (via the
|
||||||
|
// Write method) associated with the request.
|
||||||
|
// When called multiple times, the latency provided will be summed up.
|
||||||
|
func TrackResponseWriteLatency(ctx context.Context, d time.Duration) {
|
||||||
|
if tracker, ok := LatencyTrackersFrom(ctx); ok {
|
||||||
|
tracker.ResponseWriteTracker.TrackDuration(d)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// AuditAnnotationsFromLatencyTrackers will inspect each latency tracker
|
// AuditAnnotationsFromLatencyTrackers will inspect each latency tracker
|
||||||
// associated with the request context and return a set of audit
|
// associated with the request context and return a set of audit
|
||||||
// annotations that can be added to the API audit entry.
|
// annotations that can be added to the API audit entry.
|
||||||
@ -220,6 +238,7 @@ func AuditAnnotationsFromLatencyTrackers(ctx context.Context) map[string]string
|
|||||||
transformLatencyKey = "apiserver.latency.k8s.io/transform-response-object"
|
transformLatencyKey = "apiserver.latency.k8s.io/transform-response-object"
|
||||||
storageLatencyKey = "apiserver.latency.k8s.io/etcd"
|
storageLatencyKey = "apiserver.latency.k8s.io/etcd"
|
||||||
serializationLatencyKey = "apiserver.latency.k8s.io/serialize-response-object"
|
serializationLatencyKey = "apiserver.latency.k8s.io/serialize-response-object"
|
||||||
|
responseWriteLatencyKey = "apiserver.latency.k8s.io/response-write"
|
||||||
mutatingWebhookLatencyKey = "apiserver.latency.k8s.io/mutating-webhook"
|
mutatingWebhookLatencyKey = "apiserver.latency.k8s.io/mutating-webhook"
|
||||||
validatingWebhookLatencyKey = "apiserver.latency.k8s.io/validating-webhook"
|
validatingWebhookLatencyKey = "apiserver.latency.k8s.io/validating-webhook"
|
||||||
)
|
)
|
||||||
@ -239,6 +258,9 @@ func AuditAnnotationsFromLatencyTrackers(ctx context.Context) map[string]string
|
|||||||
if latency := tracker.SerializationTracker.GetLatency(); latency != 0 {
|
if latency := tracker.SerializationTracker.GetLatency(); latency != 0 {
|
||||||
annotations[serializationLatencyKey] = latency.String()
|
annotations[serializationLatencyKey] = latency.String()
|
||||||
}
|
}
|
||||||
|
if latency := tracker.ResponseWriteTracker.GetLatency(); latency != 0 {
|
||||||
|
annotations[responseWriteLatencyKey] = latency.String()
|
||||||
|
}
|
||||||
if latency := tracker.MutatingWebhookTracker.GetLatency(); latency != 0 {
|
if latency := tracker.MutatingWebhookTracker.GetLatency(); latency != 0 {
|
||||||
annotations[mutatingWebhookLatencyKey] = latency.String()
|
annotations[mutatingWebhookLatencyKey] = latency.String()
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user