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,21 @@ 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+ })
149+
150+ http .Handle (* metricPath , promHandler )
151+
135152 http .HandleFunc ("/" , func (w http.ResponseWriter , r * http.Request ) {
136153 w .Header ().Set ("Content-Type" , "text/html; charset=UTF-8" ) // nolint: errcheck
137154 w .Write (landingPage ) // nolint: errcheck
@@ -152,3 +169,80 @@ func main() {
152169 os .Exit (1 )
153170 }
154171}
172+
173+ // handler wraps an unfiltered http.Handler but uses a filtered handler,
174+ // created on the fly, if filtering is requested. Create instances with
175+ // newHandler. It used for collectors filtering.
176+ type handler struct {
177+ unfilteredHandler http.Handler
178+ collectors map [string ]prometheus.Collector
179+ }
180+
181+ func newHandler (collectors map [string ]prometheus.Collector ) * handler {
182+ h := & handler {collectors : collectors }
183+
184+ innerHandler , err := h .innerHandler ()
185+ if err != nil {
186+ level .Error (logger ).Log ("msg" , "Couldn't create metrics handler" , "error" , err )
187+ os .Exit (1 )
188+ }
189+
190+ h .unfilteredHandler = innerHandler
191+ return h
192+ }
193+
194+ // ServeHTTP implements http.Handler.
195+ func (h * handler ) ServeHTTP (w http.ResponseWriter , r * http.Request ) {
196+ filters := r .URL .Query ()["collect[]" ]
197+ level .Debug (logger ).Log ("msg" , "Collect query" , "filters" , filters )
198+
199+ if len (filters ) == 0 {
200+ // No filters, use the prepared unfiltered handler.
201+ h .unfilteredHandler .ServeHTTP (w , r )
202+ return
203+ }
204+
205+ filteredHandler , err := h .innerHandler (filters ... )
206+ if err != nil {
207+ level .Warn (logger ).Log ("msg" , "Couldn't create filtered metrics handler" , "error" , err )
208+ w .WriteHeader (http .StatusBadRequest )
209+ w .Write ([]byte (fmt .Sprintf ("Couldn't create filtered metrics handler: %s" , err )))
210+ return
211+ }
212+
213+ filteredHandler .ServeHTTP (w , r )
214+ }
215+
216+ func (h * handler ) innerHandler (filters ... string ) (http.Handler , error ) {
217+ registry := prometheus .NewRegistry ()
218+
219+ // register all collectors by default.
220+ if len (filters ) == 0 {
221+ for name , c := range h .collectors {
222+ if err := registry .Register (c ); err != nil {
223+ return nil , err
224+ }
225+ level .Debug (logger ).Log ("msg" , "Collector was registered" , "collector" , name )
226+ }
227+ }
228+
229+ // register only filtered collectors.
230+ for _ , name := range filters {
231+ if c , ok := h .collectors [name ]; ok {
232+ if err := registry .Register (c ); err != nil {
233+ return nil , err
234+ }
235+ level .Debug (logger ).Log ("msg" , "Collector was registered" , "collector" , name )
236+ }
237+ }
238+
239+ handler := promhttp .HandlerFor (
240+ registry ,
241+ promhttp.HandlerOpts {
242+ //ErrorLog: log.NewNopLogger() .NewErrorLogger(),
243+ ErrorHandling : promhttp .ContinueOnError ,
244+ },
245+ )
246+
247+ return handler , nil
248+ }
0 commit comments