@@ -100,6 +100,11 @@ version for 'cluster', or empty for 'initial'.
100
100
}
101
101
}
102
102
103
+ type asyncResult struct {
104
+ name string
105
+ error error
106
+ }
107
+
103
108
// RunMetrics launches an server bound to listenAddress serving
104
109
// Prometheus metrics at /metrics over HTTP, and, if tlsConfig is
105
110
// non-nil, also over HTTPS. Continues serving until runContext.Done()
@@ -123,50 +128,60 @@ func RunMetrics(runContext context.Context, shutdownContext context.Context, lis
123
128
// HTTP, needed during upgrade, while still allowing TLS certs and end to end metrics protection.
124
129
mux := cmux .New (tcpListener )
125
130
126
- errorChannel := make (chan error , 1 )
127
- errorChannelCount := 1
131
+ resultChannel := make (chan asyncResult , 1 )
132
+ resultChannelCount := 1
128
133
129
134
go func () {
130
135
// match HTTP first
131
136
httpListener := mux .Match (cmux .HTTP1 ())
132
137
klog .Infof ("Metrics port listening for HTTP on %v" , listenAddress )
133
- errorChannel <- server .Serve (httpListener )
138
+ err := server .Serve (httpListener )
139
+ resultChannel <- asyncResult {name : "HTTP server" , error : err }
134
140
}()
135
141
136
142
if tlsConfig != nil {
137
- errorChannelCount ++
143
+ resultChannelCount ++
138
144
go func () {
139
145
tlsListener := tls .NewListener (mux .Match (cmux .Any ()), tlsConfig )
140
146
klog .Infof ("Metrics port listening for HTTPS on %v" , listenAddress )
141
- errorChannel <- server .Serve (tlsListener )
147
+ err := server .Serve (tlsListener )
148
+ resultChannel <- asyncResult {name : "HTTPS server" , error : err }
142
149
}()
143
150
}
144
151
145
- errorChannelCount ++
152
+ resultChannelCount ++
146
153
go func () {
147
- errorChannel <- mux .Serve ()
154
+ err := mux .Serve ()
155
+ resultChannel <- asyncResult {name : "TCP muxer" , error : err }
148
156
}()
149
157
150
158
shutdown := false
151
159
var loopError error
152
- for errorChannelCount > 0 {
160
+ for resultChannelCount > 0 {
153
161
if shutdown {
154
- err := <- errorChannel
155
- errorChannelCount --
156
- if err != nil && err != http .ErrServerClosed && err != cmux .ErrListenerClosed {
157
- if loopError == nil {
158
- loopError = err
159
- } else if err != nil { // log the error we are discarding
160
- klog .Errorf ("Failed to gracefully shut down metrics server: %s" , err )
162
+ select {
163
+ case result := <- resultChannel :
164
+ resultChannelCount --
165
+ if result .error == nil {
166
+ klog .Infof ("Collected metrics %s goroutine." , result .name )
167
+ } else {
168
+ klog .Errorf ("Collected metrics %s goroutine: %v" , result .name , result .error )
169
+ loopError = result .error
161
170
}
171
+ case <- shutdownContext .Done (): // out of time
172
+ klog .Errorf ("Abandoning %d uncollected metrics goroutines" , resultChannelCount )
173
+ return shutdownContext .Err ()
162
174
}
163
175
} else {
164
176
select {
165
177
case <- runContext .Done (): // clean shutdown
166
- case err := <- errorChannel : // crashed before a shutdown was requested
167
- errorChannelCount --
168
- if err != nil && err != http .ErrServerClosed && err != cmux .ErrListenerClosed {
169
- loopError = err
178
+ case result := <- resultChannel : // crashed before a shutdown was requested
179
+ resultChannelCount --
180
+ if result .error == nil {
181
+ klog .Infof ("Collected metrics %s goroutine." , result .name )
182
+ } else {
183
+ klog .Errorf ("Collected metrics %s goroutine: %v" , result .name , result .error )
184
+ loopError = result .error
170
185
}
171
186
}
172
187
shutdown = true
0 commit comments