-
Notifications
You must be signed in to change notification settings - Fork 125
OCPBUGS-43994: UPSTREAM: <carry>: kube-apiserver: Only log each HTTP request once #2451
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -67,15 +67,15 @@ type respLogger struct { | |
addedInfo strings.Builder | ||
addedKeyValuePairs []interface{} | ||
startTime time.Time | ||
isTerminating bool | ||
|
||
captureErrorOutput bool | ||
|
||
req *http.Request | ||
userAgent string | ||
w http.ResponseWriter | ||
|
||
logStacktracePred StacktracePred | ||
logStacktracePred StacktracePred | ||
shouldLogRequestPred func(ctx context.Context) bool | ||
} | ||
|
||
var _ http.ResponseWriter = &respLogger{} | ||
|
@@ -102,19 +102,24 @@ const withLoggingLevel = 3 | |
|
||
// WithLogging wraps the handler with logging. | ||
func WithLogging(handler http.Handler, pred StacktracePred, isTerminatingFn func() bool) http.Handler { | ||
return withLogging(handler, pred, func() bool { | ||
return klog.V(withLoggingLevel).Enabled() | ||
}, isTerminatingFn) | ||
return withLogging(handler, pred, func(ctx context.Context) bool { | ||
isTerminating := false | ||
if isTerminatingFn != nil { | ||
isTerminating = isTerminatingFn() | ||
} | ||
logger := klog.FromContext(ctx) | ||
return logger.V(withLoggingLevel).Enabled() || (isTerminating && logger.V(1).Enabled()) | ||
}) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @p0lyn0mial I ended up refactoring the logic and private interfaces a bit, but the overall approach is not exactly bullet-proof. There is now a single predicate function that merges previous I added tests and use contextual logging internally that is handy for testing. The issue really is that when you check There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Another approach would be to keep the There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I need to check but if
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. yeah, I think that the patch was introduced in b052cde But given that shouldLogRequest is always true when the loglevel is 3 (hardcoded value) and the fact that rl.isTerminating is unused beyond httplog what is the point of the original patch/pr ? If we were to drop it, I think there would be no change in the behavior. am I right? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
I think the patch is very old. I think that the purpose was to find requests during server termination - not a feature users were using. I think that we could simply drop the patch and test manually that when loglevel is 3 there are no duplicates during server shutdown. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I did push one last commit, but I guess the plan is to close this and also remove the original carry this is fixing then? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think so, given that the behaviour will not change after removing the PR, right?. Unless there are some other parts that depend on the original PR. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I don't think anything depends on it, I've reverted the commit just to test it. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. could you also test manually that httplog logs requests when appropriate loglevel is set and there are no duplicates ? you can also open a new PR so that we get a signal from the CI. |
||
} | ||
|
||
func withLogging(handler http.Handler, stackTracePred StacktracePred, shouldLogRequest ShouldLogRequestPred, isTerminatingFn func() bool) http.Handler { | ||
func withLogging(handler http.Handler, stackTracePred StacktracePred, shouldLogRequest func(context.Context) bool) http.Handler { | ||
return http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) { | ||
if !shouldLogRequest() { | ||
ctx := req.Context() | ||
if !shouldLogRequest(ctx) { | ||
handler.ServeHTTP(w, req) | ||
return | ||
} | ||
|
||
ctx := req.Context() | ||
if old := respLoggerFromRequest(req); old != nil { | ||
panic("multiple WithLogging calls!") | ||
} | ||
|
@@ -123,24 +128,19 @@ func withLogging(handler http.Handler, stackTracePred StacktracePred, shouldLogR | |
startTime = receivedTimestamp | ||
} | ||
|
||
isTerminating := false | ||
if isTerminatingFn != nil { | ||
isTerminating = isTerminatingFn() | ||
} | ||
rl := newLoggedWithStartTime(req, w, startTime).StacktraceWhen(stackTracePred).IsTerminating(isTerminating) | ||
rl := newLoggedWithStartTime(req, w, startTime).StacktraceWhen(stackTracePred).ShouldLogRequest(shouldLogRequest) | ||
req = req.WithContext(context.WithValue(ctx, respLoggerContextKey, rl)) | ||
|
||
var logFunc func() | ||
logFunc = rl.Log | ||
logFunc = func() { | ||
rl.Log(ctx) | ||
} | ||
defer func() { | ||
if logFunc != nil { | ||
logFunc() | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. so, previously, the request was first logged here |
||
} | ||
}() | ||
|
||
if klog.V(3).Enabled() || (rl.isTerminating && klog.V(1).Enabled()) { | ||
tchap marked this conversation as resolved.
Show resolved
Hide resolved
|
||
defer rl.Log() | ||
tchap marked this conversation as resolved.
Show resolved
Hide resolved
|
||
} | ||
w = responsewriter.WrapForHTTP1Or2(rl) | ||
handler.ServeHTTP(w, req) | ||
|
||
|
@@ -149,7 +149,7 @@ func withLogging(handler http.Handler, stackTracePred StacktracePred, shouldLogR | |
// WithRoutine handler in the handler chain (i.e. above handler.ServeHTTP() | ||
// would return request is completely responsed), we want the logging to | ||
// happen in that goroutine too, so we append it to the task. | ||
if routine.AppendTask(ctx, &routine.Task{Func: rl.Log}) { | ||
if routine.AppendTask(ctx, &routine.Task{Func: logFunc}) { | ||
logFunc = nil | ||
} | ||
}) | ||
|
@@ -211,9 +211,9 @@ func (rl *respLogger) StacktraceWhen(pred StacktracePred) *respLogger { | |
return rl | ||
} | ||
|
||
// IsTerminating informs the logger that the server is terminating. | ||
func (rl *respLogger) IsTerminating(is bool) *respLogger { | ||
rl.isTerminating = is | ||
// ShouldLogRequest can be used to set a custom logging condition for Log. | ||
func (rl *respLogger) ShouldLogRequest(shouldLogRequestPred func(context.Context) bool) *respLogger { | ||
rl.shouldLogRequestPred = shouldLogRequestPred | ||
return rl | ||
} | ||
|
||
|
@@ -268,7 +268,7 @@ func SetStacktracePredicate(ctx context.Context, pred StacktracePred) { | |
} | ||
|
||
// Log is intended to be called once at the end of your request handler, via defer | ||
func (rl *respLogger) Log() { | ||
func (rl *respLogger) Log(ctx context.Context) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. There is a change of interface, but it doesn't seem to be really used publicly as this is an unexported object. |
||
latency := time.Since(rl.startTime) | ||
auditID := audit.GetAuditIDTruncated(rl.req.Context()) | ||
verb := metrics.NormalizedVerb(rl.req) | ||
|
@@ -304,7 +304,14 @@ func (rl *respLogger) Log() { | |
} | ||
} | ||
|
||
klog.V(withLoggingLevel).InfoSDepth(1, "HTTP", keysAndValues...) | ||
logger := klog.FromContext(ctx) | ||
shouldLogRequest := logger.V(withLoggingLevel).Enabled() | ||
if rl.shouldLogRequestPred != nil { | ||
shouldLogRequest = rl.shouldLogRequestPred(ctx) | ||
} | ||
if shouldLogRequest { | ||
logger.WithCallDepth(1).Info("HTTP", keysAndValues...) | ||
} | ||
} | ||
|
||
// Header implements http.ResponseWriter. | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
wait, why so many changes in this file ? should we simply remove the code we discussed previously ?