@@ -65,6 +65,7 @@ type respLogger struct {
65
65
addedInfo strings.Builder
66
66
addedKeyValuePairs []interface {}
67
67
startTime time.Time
68
+ isTerminating bool
68
69
69
70
captureErrorOutput bool
70
71
@@ -98,13 +99,13 @@ func DefaultStacktracePred(status int) bool {
98
99
const withLoggingLevel = 3
99
100
100
101
// WithLogging wraps the handler with logging.
101
- func WithLogging (handler http.Handler , pred StacktracePred ) http.Handler {
102
+ func WithLogging (handler http.Handler , pred StacktracePred , isTerminatingFn func () bool ) http.Handler {
102
103
return withLogging (handler , pred , func () bool {
103
104
return klog .V (withLoggingLevel ).Enabled ()
104
- })
105
+ }, isTerminatingFn )
105
106
}
106
107
107
- func withLogging (handler http.Handler , stackTracePred StacktracePred , shouldLogRequest ShouldLogRequestPred ) http.Handler {
108
+ func withLogging (handler http.Handler , stackTracePred StacktracePred , shouldLogRequest ShouldLogRequestPred , isTerminatingFn func () bool ) http.Handler {
108
109
return http .HandlerFunc (func (w http.ResponseWriter , req * http.Request ) {
109
110
if ! shouldLogRequest () {
110
111
handler .ServeHTTP (w , req )
@@ -115,17 +116,22 @@ func withLogging(handler http.Handler, stackTracePred StacktracePred, shouldLogR
115
116
if old := respLoggerFromRequest (req ); old != nil {
116
117
panic ("multiple WithLogging calls!" )
117
118
}
118
-
119
119
startTime := time .Now ()
120
120
if receivedTimestamp , ok := request .ReceivedTimestampFrom (ctx ); ok {
121
121
startTime = receivedTimestamp
122
122
}
123
123
124
- rl := newLoggedWithStartTime (req , w , startTime )
125
- rl .StacktraceWhen (stackTracePred )
124
+ isTerminating := false
125
+ if isTerminatingFn != nil {
126
+ isTerminating = isTerminatingFn ()
127
+ }
128
+ rl := newLoggedWithStartTime (req , w , startTime ).StacktraceWhen (stackTracePred ).IsTerminating (isTerminating )
126
129
req = req .WithContext (context .WithValue (ctx , respLoggerContextKey , rl ))
127
130
defer rl .Log ()
128
131
132
+ if klog .V (3 ).Enabled () || (rl .isTerminating && klog .V (1 ).Enabled ()) {
133
+ defer rl .Log ()
134
+ }
129
135
w = responsewriter .WrapForHTTP1Or2 (rl )
130
136
handler .ServeHTTP (w , req )
131
137
})
@@ -185,6 +191,12 @@ func (rl *respLogger) StacktraceWhen(pred StacktracePred) *respLogger {
185
191
return rl
186
192
}
187
193
194
+ // IsTerminating informs the logger that the server is terminating.
195
+ func (rl * respLogger ) IsTerminating (is bool ) * respLogger {
196
+ rl .isTerminating = is
197
+ return rl
198
+ }
199
+
188
200
// StatusIsNot returns a StacktracePred which will cause stacktraces to be logged
189
201
// for any status *not* in the given list.
190
202
func StatusIsNot (statuses ... int ) StacktracePred {
0 commit comments