Skip to content

Commit eefd04f

Browse files
committed
UPSTREAM: <carry>: add http logging for kubelet metrics endpoint
1 parent 9c2642e commit eefd04f

File tree

2 files changed

+108
-4
lines changed

2 files changed

+108
-4
lines changed

pkg/kubelet/server/server.go

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -474,15 +474,17 @@ func (s *Server) InstallAuthNotRequiredHandlers() {
474474
r.RawMustRegister(metrics.NewPrometheusCollector(prometheusHostAdapter{s.host}, containerPrometheusLabelsFunc(s.host), includedMetrics, clock.RealClock{}, cadvisorOpts))
475475
}
476476
s.restfulCont.Handle(cadvisorMetricsPath,
477-
compbasemetrics.HandlerFor(r, compbasemetrics.HandlerOpts{ErrorHandling: compbasemetrics.ContinueOnError}),
478-
)
477+
WithHTTPLogging(
478+
compbasemetrics.HandlerFor(r, compbasemetrics.HandlerOpts{ErrorHandling: compbasemetrics.ContinueOnError}),
479+
))
479480

480481
s.addMetricsBucketMatcher("metrics/resource")
481482
resourceRegistry := compbasemetrics.NewKubeRegistry()
482483
resourceRegistry.CustomMustRegister(collectors.NewResourceMetricsCollector(s.resourceAnalyzer))
483484
s.restfulCont.Handle(resourceMetricsPath,
484-
compbasemetrics.HandlerFor(resourceRegistry, compbasemetrics.HandlerOpts{ErrorHandling: compbasemetrics.ContinueOnError}),
485-
)
485+
WithHTTPLogging(
486+
compbasemetrics.HandlerFor(resourceRegistry, compbasemetrics.HandlerOpts{ErrorHandling: compbasemetrics.ContinueOnError}),
487+
))
486488

487489
// prober metrics are exposed under a different endpoint
488490

pkg/kubelet/server/server_patch.go

Lines changed: 102 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,102 @@
1+
package server
2+
3+
import (
4+
"net/http"
5+
"time"
6+
7+
"k8s.io/apiserver/pkg/audit"
8+
"k8s.io/apiserver/pkg/endpoints/responsewriter"
9+
"k8s.io/klog/v2"
10+
)
11+
12+
func WithHTTPLogging(handler http.Handler) http.Handler {
13+
return http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) {
14+
logger := newHTTPLogger(w, req)
15+
defer logger.log()
16+
17+
w = responsewriter.WrapForHTTP1Or2(logger)
18+
handler.ServeHTTP(w, req)
19+
})
20+
}
21+
22+
func newHTTPLogger(w http.ResponseWriter, req *http.Request) *httpLogger {
23+
return &httpLogger{
24+
w: w,
25+
startedAt: time.Now(),
26+
method: req.Method,
27+
requestURI: req.RequestURI,
28+
auditID: audit.GetAuditIDTruncated(req.Context()),
29+
userAgent: req.UserAgent(),
30+
srcIP: req.RemoteAddr,
31+
}
32+
}
33+
34+
type httpLogger struct {
35+
w http.ResponseWriter
36+
37+
method string
38+
requestURI string
39+
auditID string
40+
userAgent string
41+
srcIP string
42+
43+
startedAt time.Time
44+
writeLatency time.Duration
45+
writeBytes int
46+
statusRecorded bool
47+
statusCode int
48+
}
49+
50+
var _ http.ResponseWriter = &httpLogger{}
51+
var _ responsewriter.UserProvidedDecorator = &httpLogger{}
52+
53+
func (l *httpLogger) Unwrap() http.ResponseWriter {
54+
return l.w
55+
}
56+
57+
// Header implements http.ResponseWriter.
58+
func (l *httpLogger) Header() http.Header {
59+
return l.w.Header()
60+
}
61+
62+
// Write implements http.ResponseWriter.
63+
func (l *httpLogger) Write(b []byte) (int, error) {
64+
if !l.statusRecorded {
65+
l.record(http.StatusOK) // Default if WriteHeader hasn't been called
66+
}
67+
now := time.Now()
68+
var written int
69+
defer func() {
70+
l.writeLatency += time.Since(now)
71+
l.writeBytes += written
72+
}()
73+
written, err := l.w.Write(b)
74+
return written, err
75+
}
76+
77+
// WriteHeader implements http.ResponseWriter.
78+
func (l *httpLogger) WriteHeader(status int) {
79+
l.record(status)
80+
l.w.WriteHeader(status)
81+
}
82+
83+
func (l *httpLogger) record(status int) {
84+
l.statusCode = status
85+
l.statusRecorded = true
86+
}
87+
88+
func (l *httpLogger) log() {
89+
latency := time.Since(l.startedAt)
90+
kvs := []interface{}{
91+
"method", l.method,
92+
"URI", l.requestURI,
93+
"latency", latency,
94+
"userAgent", l.userAgent,
95+
"audit-ID", l.auditID,
96+
"srcIP", l.srcIP,
97+
"status", l.statusCode,
98+
"writeLatency", l.writeLatency,
99+
"writtenBytes", l.writeBytes / 1024,
100+
}
101+
klog.V(1).InfoSDepth(1, "HTTP", kvs...)
102+
}

0 commit comments

Comments
 (0)