Skip to content

Commit

Permalink
chore: refactor http handler (#1616)
Browse files Browse the repository at this point in the history
  • Loading branch information
jkroepke authored Sep 9, 2024
1 parent 3187002 commit 6c5b4ba
Show file tree
Hide file tree
Showing 11 changed files with 381 additions and 244 deletions.
30 changes: 9 additions & 21 deletions exporter.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ import (
"github.com/go-kit/log/level"
"github.com/prometheus-community/windows_exporter/pkg/collector"
"github.com/prometheus-community/windows_exporter/pkg/config"
"github.com/prometheus-community/windows_exporter/pkg/httphandler"
winlog "github.com/prometheus-community/windows_exporter/pkg/log"
"github.com/prometheus-community/windows_exporter/pkg/log/flag"
"github.com/prometheus-community/windows_exporter/pkg/types"
Expand Down Expand Up @@ -223,14 +224,20 @@ func main() {
_ = level.Info(logger).Log("msg", fmt.Sprintf("Enabled collectors: %v", strings.Join(enabledCollectorList, ", ")))

mux := http.NewServeMux()
mux.HandleFunc("GET "+*metricsPath, withConcurrencyLimit(*maxRequests, collectors.BuildServeHTTP(logger, *disableExporterMetrics, *timeoutMargin)))
mux.Handle("GET "+*metricsPath, httphandler.New(logger, collectors, &httphandler.Options{
DisableExporterMetrics: *disableExporterMetrics,
TimeoutMargin: *timeoutMargin,
MaxRequests: *maxRequests,
}))

mux.HandleFunc("GET /health", func(w http.ResponseWriter, _ *http.Request) {
w.Header().Set("Content-Type", "application/json")
_, err := fmt.Fprintln(w, `{"status":"ok"}`)
if err != nil {
_ = level.Debug(logger).Log("msg", "Failed to write to stream", "err", err)
}
})

mux.HandleFunc("GET /version", func(w http.ResponseWriter, _ *http.Request) {
// we can't use "version" directly as it is a package, and not an object that
// can be serialized.
Expand Down Expand Up @@ -263,7 +270,7 @@ func main() {
ReadHeaderTimeout: 5 * time.Second,
IdleTimeout: 60 * time.Second,
ReadTimeout: 5 * time.Second,
WriteTimeout: 10 * time.Minute,
WriteTimeout: 5 * time.Minute,
Handler: mux,
}

Expand Down Expand Up @@ -291,22 +298,3 @@ func main() {

_ = level.Info(logger).Log("msg", "windows_exporter has shut down")
}

func withConcurrencyLimit(n int, next http.HandlerFunc) http.HandlerFunc {
if n <= 0 {
return next
}

sem := make(chan struct{}, n)
return func(w http.ResponseWriter, r *http.Request) {
select {
case sem <- struct{}{}:
defer func() { <-sem }()
default:
w.WriteHeader(http.StatusServiceUnavailable)
_, _ = w.Write([]byte("Too many concurrent requests"))
return
}
next(w, r)
}
}
1 change: 1 addition & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ require (
github.com/prometheus/exporter-toolkit v0.12.0
github.com/stretchr/testify v1.9.0
github.com/yusufpapurcu/wmi v1.2.4
golang.org/x/exp v0.0.0-20231006140011-7918f672742d
golang.org/x/sys v0.25.0
gopkg.in/yaml.v3 v3.0.1
)
Expand Down
2 changes: 2 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,8 @@ golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPh
golang.org/x/crypto v0.27.0 h1:GXm2NjJrPaiv/h1tb2UH8QfgC/hOf/+z0p6PT8o1w7A=
golang.org/x/crypto v0.27.0/go.mod h1:1Xngt8kV6Dvbssa53Ziq6Eqn0HqbZi5Z6R0ZpwQzt70=
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
golang.org/x/exp v0.0.0-20231006140011-7918f672742d h1:jtJma62tbqLibJ5sFQz8bKtEM8rJBtfilJ2qTU199MI=
golang.org/x/exp v0.0.0-20231006140011-7918f672742d/go.mod h1:ldy0pHrwJyGW56pPQzzkH36rKxoZW1tw7ZJpeKx+hdo=
golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU=
golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
Expand Down
52 changes: 26 additions & 26 deletions pkg/collector/collector.go
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ import (
)

// NewWithFlags To be called by the exporter for collector initialization before running kingpin.Parse.
func NewWithFlags(app *kingpin.Application) *Collectors {
func NewWithFlags(app *kingpin.Application) *MetricCollectors {
collectors := map[string]Collector{}

for name, builder := range BuildersWithFlags {
Expand All @@ -82,8 +82,8 @@ func NewWithFlags(app *kingpin.Application) *Collectors {
// NewWithConfig To be called by the external libraries for collector initialization without running kingpin.Parse
//
//goland:noinspection GoUnusedExportedFunction
func NewWithConfig(config Config) *Collectors {
collectors := map[string]Collector{}
func NewWithConfig(config Config) *MetricCollectors {
collectors := Map{}
collectors[ad.Name] = ad.New(&config.AD)
collectors[adcs.Name] = adcs.New(&config.ADCS)
collectors[adfs.Name] = adfs.New(&config.ADFS)
Expand Down Expand Up @@ -142,26 +142,26 @@ func NewWithConfig(config Config) *Collectors {
}

// New To be called by the external libraries for collector initialization.
func New(collectors Map) *Collectors {
return &Collectors{
collectors: collectors,
wmiClient: &wmi.Client{
func New(collectors Map) *MetricCollectors {
return &MetricCollectors{
Collectors: collectors,
WMIClient: &wmi.Client{
AllowMissingFields: true,
},
}
}

func (c *Collectors) SetPerfCounterQuery(logger log.Logger) error {
func (c *MetricCollectors) SetPerfCounterQuery(logger log.Logger) error {
var (
err error

perfCounterNames []string
perfIndicies []string
)

perfCounterDependencies := make([]string, 0, len(c.collectors))
perfCounterDependencies := make([]string, 0, len(c.Collectors))

for _, collector := range c.collectors {
for _, collector := range c.Collectors {
perfCounterNames, err = collector.GetPerfCounter(logger)
if err != nil {
return err
Expand All @@ -175,31 +175,31 @@ func (c *Collectors) SetPerfCounterQuery(logger log.Logger) error {
perfCounterDependencies = append(perfCounterDependencies, strings.Join(perfIndicies, " "))
}

c.perfCounterQuery = strings.Join(perfCounterDependencies, " ")
c.PerfCounterQuery = strings.Join(perfCounterDependencies, " ")

return nil
}

// Enable removes all collectors that not enabledCollectors.
func (c *Collectors) Enable(enabledCollectors []string) {
for name := range c.collectors {
func (c *MetricCollectors) Enable(enabledCollectors []string) {
for name := range c.Collectors {
if !slices.Contains(enabledCollectors, name) {
delete(c.collectors, name)
delete(c.Collectors, name)
}
}
}

// Build To be called by the exporter for collector initialization.
func (c *Collectors) Build(logger log.Logger) error {
func (c *MetricCollectors) Build(logger log.Logger) error {
var err error

c.wmiClient.SWbemServicesClient, err = wmi.InitializeSWbemServices(c.wmiClient)
c.WMIClient.SWbemServicesClient, err = wmi.InitializeSWbemServices(c.WMIClient)
if err != nil {
return fmt.Errorf("initialize SWbemServices: %w", err)
}

for _, collector := range c.collectors {
if err = collector.Build(logger, c.wmiClient); err != nil {
for _, collector := range c.Collectors {
if err = collector.Build(logger, c.WMIClient); err != nil {
return fmt.Errorf("error build collector %s: %w", collector.GetName(), err)
}
}
Expand All @@ -208,12 +208,12 @@ func (c *Collectors) Build(logger log.Logger) error {
}

// PrepareScrapeContext creates a ScrapeContext to be used during a single scrape.
func (c *Collectors) PrepareScrapeContext() (*types.ScrapeContext, error) {
if c.perfCounterQuery == "" { // if perfCounterQuery is empty, no perf counters are needed.
func (c *MetricCollectors) PrepareScrapeContext() (*types.ScrapeContext, error) {
if c.PerfCounterQuery == "" { // if perfCounterQuery is empty, no perf counters are needed.
return &types.ScrapeContext{}, nil
}

objs, err := perflib.GetPerflibSnapshot(c.perfCounterQuery)
objs, err := perflib.GetPerflibSnapshot(c.PerfCounterQuery)
if err != nil {
return nil, err
}
Expand All @@ -222,17 +222,17 @@ func (c *Collectors) PrepareScrapeContext() (*types.ScrapeContext, error) {
}

// Close To be called by the exporter for collector cleanup.
func (c *Collectors) Close() error {
errs := make([]error, 0, len(c.collectors))
func (c *MetricCollectors) Close() error {
errs := make([]error, 0, len(c.Collectors))

for _, collector := range c.collectors {
for _, collector := range c.Collectors {
if err := collector.Close(nil); err != nil {
errs = append(errs, err)
}
}

if c.wmiClient != nil && c.wmiClient.SWbemServicesClient != nil {
if err := c.wmiClient.SWbemServicesClient.Close(); err != nil {
if c.WMIClient != nil && c.WMIClient.SWbemServicesClient != nil {
if err := c.WMIClient.SWbemServicesClient.Close(); err != nil {
errs = append(errs, err)
}
}
Expand Down
85 changes: 0 additions & 85 deletions pkg/collector/handler.go

This file was deleted.

Loading

0 comments on commit 6c5b4ba

Please sign in to comment.