Skip to content

Commit 0f388cf

Browse files
committed
PMM-9973 resolutions filtering fix
1 parent 7124736 commit 0f388cf

File tree

1 file changed

+97
-3
lines changed

1 file changed

+97
-3
lines changed

cmd/postgres_exporter/main.go

+97-3
Original file line numberDiff line numberDiff line change
@@ -14,13 +14,15 @@
1414
package main
1515

1616
import (
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

Comments
 (0)