@@ -65,6 +65,7 @@ type respLogger struct {
6565 addedInfo strings.Builder
6666 addedKeyValuePairs []interface {}
6767 startTime time.Time
68+ isTerminating bool
6869
6970 captureErrorOutput bool
7071
@@ -98,13 +99,13 @@ func DefaultStacktracePred(status int) bool {
9899const withLoggingLevel = 3
99100
100101// 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 {
102103 return withLogging (handler , pred , func () bool {
103104 return klog .V (withLoggingLevel ).Enabled ()
104- })
105+ }, isTerminatingFn )
105106}
106107
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 {
108109 return http .HandlerFunc (func (w http.ResponseWriter , req * http.Request ) {
109110 if ! shouldLogRequest () {
110111 handler .ServeHTTP (w , req )
@@ -115,17 +116,22 @@ func withLogging(handler http.Handler, stackTracePred StacktracePred, shouldLogR
115116 if old := respLoggerFromRequest (req ); old != nil {
116117 panic ("multiple WithLogging calls!" )
117118 }
118-
119119 startTime := time .Now ()
120120 if receivedTimestamp , ok := request .ReceivedTimestampFrom (ctx ); ok {
121121 startTime = receivedTimestamp
122122 }
123123
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 )
126129 req = req .WithContext (context .WithValue (ctx , respLoggerContextKey , rl ))
127130 defer rl .Log ()
128131
132+ if klog .V (3 ).Enabled () || (rl .isTerminating && klog .V (1 ).Enabled ()) {
133+ defer rl .Log ()
134+ }
129135 w = responsewriter .WrapForHTTP1Or2 (rl )
130136 handler .ServeHTTP (w , req )
131137 })
@@ -185,6 +191,12 @@ func (rl *respLogger) StacktraceWhen(pred StacktracePred) *respLogger {
185191 return rl
186192}
187193
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+
188200// StatusIsNot returns a StacktracePred which will cause stacktraces to be logged
189201// for any status *not* in the given list.
190202func StatusIsNot (statuses ... int ) StacktracePred {
0 commit comments