diff --git a/internal/collector/service/service.go b/internal/collector/service/service.go index d60894fc..8fdc1595 100644 --- a/internal/collector/service/service.go +++ b/internal/collector/service/service.go @@ -141,7 +141,7 @@ func (c *Collector) Build(logger *slog.Logger, _ *mi.Session) error { }, } - c.queryAllServicesBuffer = make([]byte, 1024*100) + c.queryAllServicesBuffer = make([]byte, 1024*200) c.info = prometheus.NewDesc( prometheus.BuildFQName(types.Namespace, Name, "info"), @@ -240,6 +240,15 @@ func (c *Collector) Collect(ch chan<- prometheus.Metric) error { } func (c *Collector) collectWorker(ch chan<- prometheus.Metric, service windows.ENUM_SERVICE_STATUS_PROCESS) { + if uintptr(unsafe.Pointer(service.ServiceName)) == uintptr(windows.InvalidHandle) { + c.logger.Log(context.Background(), slog.LevelWarn, "failed collecting service info", + slog.String("err", "ServiceName is 0xffffffffffffffff"), + slog.String("service", fmt.Sprintf("%+v", service)), + ) + + return + } + serviceName := windows.UTF16PtrToString(service.ServiceName) if c.config.ServiceExclude.MatchString(serviceName) || !c.config.ServiceInclude.MatchString(serviceName) { @@ -373,6 +382,8 @@ func (c *Collector) queryAllServices() ([]windows.ENUM_SERVICE_STATUS_PROCESS, e err error ) + clear(c.queryAllServicesBuffer) + for { currentBufferSize := uint32(cap(c.queryAllServicesBuffer)) diff --git a/internal/httphandler/httphandler.go b/internal/httphandler/httphandler.go index 0dc830ec..7a1be7c3 100644 --- a/internal/httphandler/httphandler.go +++ b/internal/httphandler/httphandler.go @@ -40,9 +40,8 @@ type MetricsHTTPHandler struct { // the exporter itself. exporterMetricsRegistry *prometheus.Registry - logger *slog.Logger - options Options - concurrencyCh chan struct{} + logger *slog.Logger + options Options } type Options struct { @@ -62,9 +61,6 @@ func New(logger *slog.Logger, metricCollectors *collector.Collection, options *O metricCollectors: metricCollectors, logger: logger, options: *options, - - // We are expose metrics directly from the memory region of the Win32 API. We should not allow more than one request at a time. - concurrencyCh: make(chan struct{}, 1), } if !options.DisableExporterMetrics { diff --git a/pkg/collector/handler.go b/pkg/collector/handler.go index 5c34c286..65d89e1e 100644 --- a/pkg/collector/handler.go +++ b/pkg/collector/handler.go @@ -18,6 +18,7 @@ package collector import ( "fmt" "log/slog" + "sync" "time" "github.com/prometheus/client_golang/prometheus" @@ -26,6 +27,12 @@ import ( // Interface guard. var _ prometheus.Collector = (*Handler)(nil) +// We are expose metrics directly from the memory region of the Win32 API. +// We should not allow more than one request at a time. +// +//nolint:gochecknoglobals +var concurrencyMu sync.Mutex + // Handler implements [prometheus.Collector] for a set of Windows Collection. type Handler struct { maxScrapeDuration time.Duration @@ -58,5 +65,7 @@ func (p *Handler) Describe(_ chan<- *prometheus.Desc) {} // Collect sends the collected metrics from each of the Collection to // prometheus. func (p *Handler) Collect(ch chan<- prometheus.Metric) { + concurrencyMu.Lock() p.collection.collectAll(ch, p.logger, p.maxScrapeDuration) + concurrencyMu.Unlock() }