1414package main
1515
1616import (
17+ "fmt"
1718 "net/http"
1819 "os"
1920
2021 "github.com/go-kit/log"
2122 "github.com/go-kit/log/level"
2223 "github.com/prometheus-community/postgres_exporter/collector"
2324 "github.com/prometheus/client_golang/prometheus"
25+ "github.com/prometheus/client_golang/prometheus/collectors"
2426 "github.com/prometheus/client_golang/prometheus/promhttp"
2527 "github.com/prometheus/common/promlog"
2628 "github.com/prometheus/common/promlog/flag"
@@ -113,11 +115,12 @@ func main() {
113115 exporter .servers .Close ()
114116 }()
115117
116- prometheus .MustRegister (version .NewCollector (exporterName ))
118+ versionCollector := version .NewCollector (exporterName )
119+ prometheus .MustRegister (versionCollector )
117120
118121 prometheus .MustRegister (exporter )
119122
120- cleanup := initializePerconaExporters (dsn , opts )
123+ cleanup , hr , mr , lr := initializePerconaExporters (dsn , opts )
121124 defer cleanup ()
122125
123126 pe , err := collector .NewPostgresCollector (
@@ -131,7 +134,22 @@ func main() {
131134 }
132135 prometheus .MustRegister (pe )
133136
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+
135153 http .HandleFunc ("/" , func (w http.ResponseWriter , r * http.Request ) {
136154 w .Header ().Set ("Content-Type" , "text/html; charset=UTF-8" ) // nolint: errcheck
137155 w .Write (landingPage ) // nolint: errcheck
@@ -152,3 +170,80 @@ func main() {
152170 os .Exit (1 )
153171 }
154172}
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