14
14
package main
15
15
16
16
import (
17
+ "fmt"
17
18
"net/http"
18
19
"os"
19
20
20
21
"github.com/go-kit/log"
21
22
"github.com/go-kit/log/level"
22
23
"github.com/prometheus-community/postgres_exporter/collector"
23
24
"github.com/prometheus/client_golang/prometheus"
25
+ "github.com/prometheus/client_golang/prometheus/collectors"
24
26
"github.com/prometheus/client_golang/prometheus/promhttp"
25
27
"github.com/prometheus/common/promlog"
26
28
"github.com/prometheus/common/promlog/flag"
@@ -113,11 +115,12 @@ func main() {
113
115
exporter .servers .Close ()
114
116
}()
115
117
116
- prometheus .MustRegister (version .NewCollector (exporterName ))
118
+ versionCollector := version .NewCollector (exporterName )
119
+ prometheus .MustRegister (versionCollector )
117
120
118
121
prometheus .MustRegister (exporter )
119
122
120
- cleanup := initializePerconaExporters (dsn , opts )
123
+ cleanup , hr , mr , lr := initializePerconaExporters (dsn , opts )
121
124
defer cleanup ()
122
125
123
126
pe , err := collector .NewPostgresCollector (
@@ -131,7 +134,22 @@ func main() {
131
134
}
132
135
prometheus .MustRegister (pe )
133
136
134
- http .Handle (* metricPath , promhttp .Handler ())
137
+ psCollector := collectors .NewProcessCollector (collectors.ProcessCollectorOpts {})
138
+ goCollector := collectors .NewGoCollector ()
139
+
140
+ promHandler := newHandler (map [string ]prometheus.Collector {
141
+ "exporter" : exporter ,
142
+ "custom_query.hr" : hr ,
143
+ "custom_query.mr" : mr ,
144
+ "custom_query.lr" : lr ,
145
+ "standard.process" : psCollector ,
146
+ "standard.go" : goCollector ,
147
+ "version" : versionCollector ,
148
+ "postgres" : pe ,
149
+ })
150
+
151
+ http .Handle (* metricPath , promHandler )
152
+
135
153
http .HandleFunc ("/" , func (w http.ResponseWriter , r * http.Request ) {
136
154
w .Header ().Set ("Content-Type" , "text/html; charset=UTF-8" ) // nolint: errcheck
137
155
w .Write (landingPage ) // nolint: errcheck
@@ -152,3 +170,80 @@ func main() {
152
170
os .Exit (1 )
153
171
}
154
172
}
173
+
174
+ // handler wraps an unfiltered http.Handler but uses a filtered handler,
175
+ // created on the fly, if filtering is requested. Create instances with
176
+ // newHandler. It used for collectors filtering.
177
+ type handler struct {
178
+ unfilteredHandler http.Handler
179
+ collectors map [string ]prometheus.Collector
180
+ }
181
+
182
+ func newHandler (collectors map [string ]prometheus.Collector ) * handler {
183
+ h := & handler {collectors : collectors }
184
+
185
+ innerHandler , err := h .innerHandler ()
186
+ if err != nil {
187
+ level .Error (logger ).Log ("msg" , "Couldn't create metrics handler" , "error" , err )
188
+ os .Exit (1 )
189
+ }
190
+
191
+ h .unfilteredHandler = innerHandler
192
+ return h
193
+ }
194
+
195
+ // ServeHTTP implements http.Handler.
196
+ func (h * handler ) ServeHTTP (w http.ResponseWriter , r * http.Request ) {
197
+ filters := r .URL .Query ()["collect[]" ]
198
+ level .Debug (logger ).Log ("msg" , "Collect query" , "filters" , filters )
199
+
200
+ if len (filters ) == 0 {
201
+ // No filters, use the prepared unfiltered handler.
202
+ h .unfilteredHandler .ServeHTTP (w , r )
203
+ return
204
+ }
205
+
206
+ filteredHandler , err := h .innerHandler (filters ... )
207
+ if err != nil {
208
+ level .Warn (logger ).Log ("msg" , "Couldn't create filtered metrics handler" , "error" , err )
209
+ w .WriteHeader (http .StatusBadRequest )
210
+ w .Write ([]byte (fmt .Sprintf ("Couldn't create filtered metrics handler: %s" , err ))) // nolint: errcheck
211
+ return
212
+ }
213
+
214
+ filteredHandler .ServeHTTP (w , r )
215
+ }
216
+
217
+ func (h * handler ) innerHandler (filters ... string ) (http.Handler , error ) {
218
+ registry := prometheus .NewRegistry ()
219
+
220
+ // register all collectors by default.
221
+ if len (filters ) == 0 {
222
+ for name , c := range h .collectors {
223
+ if err := registry .Register (c ); err != nil {
224
+ return nil , err
225
+ }
226
+ level .Debug (logger ).Log ("msg" , "Collector was registered" , "collector" , name )
227
+ }
228
+ }
229
+
230
+ // register only filtered collectors.
231
+ for _ , name := range filters {
232
+ if c , ok := h .collectors [name ]; ok {
233
+ if err := registry .Register (c ); err != nil {
234
+ return nil , err
235
+ }
236
+ level .Debug (logger ).Log ("msg" , "Collector was registered" , "collector" , name )
237
+ }
238
+ }
239
+
240
+ handler := promhttp .HandlerFor (
241
+ registry ,
242
+ promhttp.HandlerOpts {
243
+ //ErrorLog: log.NewNopLogger() .NewErrorLogger(),
244
+ ErrorHandling : promhttp .ContinueOnError ,
245
+ },
246
+ )
247
+
248
+ return handler , nil
249
+ }
0 commit comments