Add logging of filters to api calls logs

Kubernetes-commit: 7e01b7260ac5cc20c1fc236cae220857726dc330
This commit is contained in:
Marcel Zięba 2021-05-17 11:52:33 +00:00 committed by Kubernetes Publisher
parent 9eb1679911
commit 489e43cad9
2 changed files with 30 additions and 10 deletions

View File

@ -24,6 +24,8 @@ import (
utilclock "k8s.io/apimachinery/pkg/util/clock"
"k8s.io/apiserver/pkg/endpoints/metrics"
apirequest "k8s.io/apiserver/pkg/endpoints/request"
"k8s.io/apiserver/pkg/server/httplog"
"k8s.io/klog/v2"
)
type requestFilterRecordKeyType int
@ -31,6 +33,8 @@ type requestFilterRecordKeyType int
// requestFilterRecordKey is the context key for a request filter record struct.
const requestFilterRecordKey requestFilterRecordKeyType = iota
const minFilterLatencyToLog = 100 * time.Millisecond
type requestFilterRecord struct {
name string
startedTimestamp time.Time
@ -57,7 +61,11 @@ func TrackStarted(handler http.Handler, name string) http.Handler {
// it updates the corresponding metric with the filter latency duration.
func TrackCompleted(handler http.Handler) http.Handler {
return trackCompleted(handler, utilclock.RealClock{}, func(ctx context.Context, fr *requestFilterRecord, completedAt time.Time) {
metrics.RecordFilterLatency(ctx, fr.name, completedAt.Sub(fr.startedTimestamp))
latency := completedAt.Sub(fr.startedTimestamp)
metrics.RecordFilterLatency(ctx, fr.name, latency)
if klog.V(3).Enabled() && latency > minFilterLatencyToLog {
httplog.AddInfof(ctx, "%s=%s", fr.name, latency.String())
}
})
}

View File

@ -23,6 +23,7 @@ import (
"net"
"net/http"
"runtime"
"strings"
"time"
"k8s.io/apiserver/pkg/endpoints/request"
@ -52,7 +53,7 @@ type respLogger struct {
statusRecorded bool
status int
statusStack string
addedInfo string
addedInfo strings.Builder
startTime time.Time
captureErrorOutput bool
@ -83,7 +84,7 @@ func DefaultStacktracePred(status int) bool {
func WithLogging(handler http.Handler, pred StacktracePred) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) {
ctx := req.Context()
if old := respLoggerFromContext(req); old != nil {
if old := respLoggerFromRequest(req); old != nil {
panic("multiple WithLogging calls!")
}
@ -103,8 +104,7 @@ func WithLogging(handler http.Handler, pred StacktracePred) http.Handler {
}
// respLoggerFromContext returns the respLogger or nil.
func respLoggerFromContext(req *http.Request) *respLogger {
ctx := req.Context()
func respLoggerFromContext(ctx context.Context) *respLogger {
val := ctx.Value(respLoggerContextKey)
if rl, ok := val.(*respLogger); ok {
return rl
@ -112,6 +112,10 @@ func respLoggerFromContext(req *http.Request) *respLogger {
return nil
}
func respLoggerFromRequest(req *http.Request) *respLogger {
return respLoggerFromContext(req.Context())
}
func newLoggedWithStartTime(req *http.Request, w http.ResponseWriter, startTime time.Time) *respLogger {
return &respLogger{
startTime: startTime,
@ -130,7 +134,7 @@ func newLogged(req *http.Request, w http.ResponseWriter) *respLogger {
// then a passthroughLogger will be created which will log to stdout immediately
// when Addf is called.
func LogOf(req *http.Request, w http.ResponseWriter) logger {
if rl := respLoggerFromContext(req); rl != nil {
if rl := respLoggerFromRequest(req); rl != nil {
return rl
}
return &passthroughLogger{}
@ -138,7 +142,7 @@ func LogOf(req *http.Request, w http.ResponseWriter) logger {
// Unlogged returns the original ResponseWriter, or w if it is not our inserted logger.
func Unlogged(req *http.Request, w http.ResponseWriter) http.ResponseWriter {
if rl := respLoggerFromContext(req); rl != nil {
if rl := respLoggerFromRequest(req); rl != nil {
return rl.w
}
return w
@ -166,7 +170,14 @@ func StatusIsNot(statuses ...int) StacktracePred {
// Addf adds additional data to be logged with this request.
func (rl *respLogger) Addf(format string, data ...interface{}) {
rl.addedInfo += "\n" + fmt.Sprintf(format, data...)
rl.addedInfo.WriteString("\n")
rl.addedInfo.WriteString(fmt.Sprintf(format, data...))
}
func AddInfof(ctx context.Context, format string, data ...interface{}) {
if rl := respLoggerFromContext(ctx); rl != nil {
rl.Addf(format, data...)
}
}
func (rl *respLogger) LogArgs() []interface{} {
@ -196,8 +207,9 @@ func (rl *respLogger) LogArgs() []interface{} {
args = append(args, "statusStack", rl.statusStack)
}
if len(rl.addedInfo) > 0 {
args = append(args, "addedInfo", rl.addedInfo)
info := rl.addedInfo.String()
if len(info) > 0 {
args = append(args, "addedInfo", info)
}
return args
}