Compare commits

..

5 Commits

Author SHA1 Message Date
Jan-Otto Kröpke
d451acbd63 [0.30] fix: Avoid COINIT_MULTITHREADED in CoInitializeEx (#2066) (#2091) 2025-06-21 11:29:06 +02:00
Jan-Otto Kröpke
7c14a79ef2 [0.30] service: report invalid parameter errors as debug (#2051) (#2092) 2025-06-21 11:28:48 +02:00
Jan-Otto Kröpke
3d7b16d61d [0.30] fix: added count checks (#2083) (#2089) 2025-06-21 11:28:30 +02:00
Jan-Otto Kröpke
a3131dc087 [0.30] logical_disk: skip unmounted volumes (#2084) (#2090)
Co-authored-by: Nic Jansma <nic@nicj.net>
2025-06-21 11:28:16 +02:00
Karl Persson
93940569fa update: export properties so that they can be read from yaml file (#2054) 2025-05-22 16:33:56 +02:00
12 changed files with 39 additions and 18 deletions

View File

@@ -520,6 +520,8 @@ func (c *Collector) Collect(ch chan<- prometheus.Metric) error {
err := c.perfDataCollector.Collect(&c.perfDataObject)
if err != nil {
return fmt.Errorf("failed to collect DirectoryServices (AD) metrics: %w", err)
} else if len(c.perfDataObject) == 0 {
return fmt.Errorf("failed to collect DirectoryServices (AD) metrics: %w", types.ErrNoDataUnexpected)
}
ch <- prometheus.MustNewConstMetric(

View File

@@ -385,6 +385,8 @@ func (c *Collector) Collect(ch chan<- prometheus.Metric) error {
err := c.perfDataCollector.Collect(&c.perfDataObject)
if err != nil {
return fmt.Errorf("failed to collect ADFS metrics: %w", err)
} else if len(c.perfDataObject) == 0 {
return fmt.Errorf("failed to collect ADFS metrics: %w", types.ErrNoDataUnexpected)
}
ch <- prometheus.MustNewConstMetric(

View File

@@ -288,6 +288,8 @@ func (c *Collector) Collect(ch chan<- prometheus.Metric) error {
err := c.perfDataCollector.Collect(&c.perfDataObject)
if err != nil {
return fmt.Errorf("failed to collect Cache metrics: %w", err)
} else if len(c.perfDataObject) == 0 {
return fmt.Errorf("failed to collect Cache metrics: %w", types.ErrNoDataUnexpected)
}
ch <- prometheus.MustNewConstMetric(

View File

@@ -403,6 +403,8 @@ func (c *Collector) collectServerMetrics(ch chan<- prometheus.Metric) error {
err := c.perfDataCollector.Collect(&c.perfDataObject)
if err != nil {
return fmt.Errorf("failed to collect DHCP Server metrics: %w", err)
} else if len(c.perfDataObject) == 0 {
return fmt.Errorf("failed to collect DHCP Server metrics: %w", types.ErrNoDataUnexpected)
}
ch <- prometheus.MustNewConstMetric(

View File

@@ -345,6 +345,8 @@ func (c *Collector) collectMetrics(ch chan<- prometheus.Metric) error {
err := c.perfDataCollector.Collect(&c.perfDataObject)
if err != nil {
return fmt.Errorf("failed to collect DNS metrics: %w", err)
} else if len(c.perfDataObject) == 0 {
return fmt.Errorf("failed to collect DNS metrics: %w", types.ErrNoDataUnexpected)
}
ch <- prometheus.MustNewConstMetric(

View File

@@ -588,6 +588,11 @@ func getAllMountedVolumes() (map[string]string, error) {
break
}
if errors.Is(err, windows.ERROR_FILE_NOT_FOUND) {
// the volume is not mounted
break
}
if errors.Is(err, windows.ERROR_NO_MORE_FILES) {
rootPathBuf = make([]uint16, (rootPathLen+1)/2)

View File

@@ -248,7 +248,7 @@ func getScheduledTasks() (ScheduledTasks, error) {
runtime.LockOSThread()
defer runtime.UnlockOSThread()
if err := ole.CoInitializeEx(0, ole.COINIT_MULTITHREADED); err != nil {
if err := ole.CoInitializeEx(0, ole.COINIT_APARTMENTTHREADED|ole.COINIT_DISABLE_OLE1DDE); err != nil {
var oleCode *ole.OleError
if errors.As(err, &oleCode) && oleCode.Code() != ole.S_OK && oleCode.Code() != S_FALSE {
return nil, err

View File

@@ -350,7 +350,9 @@ func (c *Collector) collectService(ch chan<- prometheus.Metric, serviceName stri
logLevel := slog.LevelWarn
if errors.Is(err, windows.ERROR_ACCESS_DENIED) {
// ERROR_INVALID_PARAMETER returns when the process is not running. This can be happened
// if the service terminated after query the service API.
if errors.Is(err, windows.ERROR_ACCESS_DENIED) || errors.Is(err, windows.ERROR_INVALID_PARAMETER) {
logLevel = slog.LevelDebug
}

View File

@@ -157,6 +157,8 @@ func (c *Collector) Collect(ch chan<- prometheus.Metric) error {
err := c.perfDataCollector.Collect(&c.perfDataObject)
if err != nil {
return fmt.Errorf("failed to collect System metrics: %w", err)
} else if len(c.perfDataObject) == 0 {
return fmt.Errorf("failed to collect System metrics: %w", types.ErrNoDataUnexpected)
}
ch <- prometheus.MustNewConstMetric(

View File

@@ -245,7 +245,9 @@ func (c *Collector) collectTime(ch chan<- prometheus.Metric) error {
func (c *Collector) collectNTP(ch chan<- prometheus.Metric) error {
err := c.perfDataCollector.Collect(&c.perfDataObject)
if err != nil {
return fmt.Errorf("failed to collect time metrics: %w", err)
return fmt.Errorf("failed to collect Windows Time Service metrics: %w", err)
} else if len(c.perfDataObject) == 0 {
return fmt.Errorf("failed to collect Windows Time Service metrics: %w", types.ErrNoDataUnexpected)
}
ch <- prometheus.MustNewConstMetric(

View File

@@ -37,14 +37,14 @@ import (
const Name = "update"
type Config struct {
online bool `yaml:"online"`
scrapeInterval time.Duration `yaml:"scrape_interval"`
Online bool `yaml:"online"`
ScrapeInterval time.Duration `yaml:"scrape_interval"`
}
//nolint:gochecknoglobals
var ConfigDefaults = Config{
online: false,
scrapeInterval: 6 * time.Hour,
Online: false,
ScrapeInterval: 6 * time.Hour,
}
var (
@@ -85,12 +85,12 @@ func NewWithFlags(app *kingpin.Application) *Collector {
app.Flag(
"collector.updates.online",
"Whether to search for updates online.",
).Default(strconv.FormatBool(ConfigDefaults.online)).BoolVar(&c.config.online)
).Default(strconv.FormatBool(ConfigDefaults.Online)).BoolVar(&c.config.Online)
app.Flag(
"collector.updates.scrape-interval",
"Define the interval of scraping Windows Update information.",
).Default(ConfigDefaults.scrapeInterval.String()).DurationVar(&c.config.scrapeInterval)
).Default(ConfigDefaults.ScrapeInterval.String()).DurationVar(&c.config.ScrapeInterval)
return c
}
@@ -109,7 +109,7 @@ func (c *Collector) Build(logger *slog.Logger, _ *mi.Session) error {
ctx, cancel := context.WithCancel(context.Background())
initErrCh := make(chan error, 1)
go c.scheduleUpdateStatus(ctx, logger, initErrCh, c.config.online)
go c.scheduleUpdateStatus(ctx, logger, initErrCh, c.config.Online)
c.ctxCancelFn = cancel
@@ -166,7 +166,7 @@ func (c *Collector) scheduleUpdateStatus(ctx context.Context, logger *slog.Logge
runtime.LockOSThread()
defer runtime.UnlockOSThread()
if err := ole.CoInitializeEx(0, ole.COINIT_MULTITHREADED); err != nil {
if err := ole.CoInitializeEx(0, ole.COINIT_APARTMENTTHREADED|ole.COINIT_DISABLE_OLE1DDE); err != nil {
var oleCode *ole.OleError
if errors.As(err, &oleCode) && oleCode.Code() != ole.S_OK && oleCode.Code() != 0x00000001 {
initErrCh <- fmt.Errorf("CoInitializeEx: %w", err)
@@ -178,17 +178,17 @@ func (c *Collector) scheduleUpdateStatus(ctx context.Context, logger *slog.Logge
defer ole.CoUninitialize()
// Create a new instance of the WMI object
mus, err := oleutil.CreateObject("Microsoft.Update.Session")
sessionObj, err := oleutil.CreateObject("Microsoft.Update.Session")
if err != nil {
initErrCh <- fmt.Errorf("create Microsoft.Update.Session: %w", err)
return
}
defer mus.Release()
defer sessionObj.Release()
// Query the IDispatch interface of the object
musQueryInterface, err := mus.QueryInterface(ole.IID_IDispatch)
musQueryInterface, err := sessionObj.QueryInterface(ole.IID_IDispatch)
if err != nil {
initErrCh <- fmt.Errorf("IID_IDispatch: %w", err)
@@ -206,9 +206,9 @@ func (c *Collector) scheduleUpdateStatus(ctx context.Context, logger *slog.Logge
// https://learn.microsoft.com/en-us/windows/win32/api/wuapi/nf-wuapi-iupdatesession-createupdatesearcher
us, err := oleutil.CallMethod(musQueryInterface, "CreateUpdateSearcher")
defer func(hc *ole.VARIANT) {
defer func(us *ole.VARIANT) {
if us != nil {
_ = hc.Clear()
_ = us.Clear()
}
}(us)
@@ -268,7 +268,7 @@ func (c *Collector) scheduleUpdateStatus(ctx context.Context, logger *slog.Logge
c.mu.Unlock()
select {
case <-time.After(c.config.scrapeInterval):
case <-time.After(c.config.ScrapeInterval):
case <-ctx.Done():
return
}

View File

@@ -40,7 +40,7 @@ func (s *ScheduleService) Connect() error {
runtime.LockOSThread()
defer runtime.UnlockOSThread()
if err := ole.CoInitializeEx(0, ole.COINIT_MULTITHREADED|ole.COINIT_DISABLE_OLE1DDE); err != nil {
if err := ole.CoInitializeEx(0, ole.COINIT_APARTMENTTHREADED|ole.COINIT_DISABLE_OLE1DDE); err != nil {
var oleCode *ole.OleError
if errors.As(err, &oleCode) && oleCode.Code() != ole.S_OK && oleCode.Code() != 0x00000001 {
return err