mirror of
https://github.com/prometheus-community/windows_exporter.git
synced 2026-02-08 05:56:37 +00:00
update: expose publish date of updates (#2050)
This commit is contained in:
@@ -60,11 +60,14 @@ type Collector struct {
|
||||
mu sync.RWMutex
|
||||
ctxCancelFn context.CancelFunc
|
||||
|
||||
logger *slog.Logger
|
||||
|
||||
metricsBuf []prometheus.Metric
|
||||
|
||||
pendingUpdate *prometheus.Desc
|
||||
queryDurationSeconds *prometheus.Desc
|
||||
lastScrapeMetric *prometheus.Desc
|
||||
pendingUpdate *prometheus.Desc
|
||||
pendingUpdateLastPublished *prometheus.Desc
|
||||
queryDurationSeconds *prometheus.Desc
|
||||
lastScrapeMetric *prometheus.Desc
|
||||
}
|
||||
|
||||
func New(config *Config) *Collector {
|
||||
@@ -146,9 +149,9 @@ func (c *Collector) Close() error {
|
||||
}
|
||||
|
||||
func (c *Collector) Build(logger *slog.Logger, _ *mi.Session) error {
|
||||
logger = logger.With(slog.String("collector", Name))
|
||||
c.logger = logger.With(slog.String("collector", Name))
|
||||
|
||||
logger.Info("update collector is in an experimental state! The configuration and metrics may change in future. Please report any issues.")
|
||||
c.logger.Info("update collector is in an experimental state! The configuration and metrics may change in future. Please report any issues.")
|
||||
|
||||
ctx, cancel := context.WithCancel(context.Background())
|
||||
|
||||
@@ -164,7 +167,14 @@ func (c *Collector) Build(logger *slog.Logger, _ *mi.Session) error {
|
||||
c.pendingUpdate = prometheus.NewDesc(
|
||||
prometheus.BuildFQName(types.Namespace, Name, "pending_info"),
|
||||
"Expose information for a single pending update item",
|
||||
[]string{"category", "severity", "title"},
|
||||
[]string{"id", "revision", "category", "severity", "title"},
|
||||
nil,
|
||||
)
|
||||
|
||||
c.pendingUpdateLastPublished = prometheus.NewDesc(
|
||||
prometheus.BuildFQName(types.Namespace, Name, "pending_published_timestamp"),
|
||||
"Expose last published timestamp for a single pending update item",
|
||||
[]string{"id", "revision"},
|
||||
nil,
|
||||
)
|
||||
|
||||
@@ -241,9 +251,16 @@ func (c *Collector) scheduleUpdateStatus(ctx context.Context, logger *slog.Logge
|
||||
|
||||
defer musQueryInterface.Release()
|
||||
|
||||
_, err = oleutil.PutProperty(musQueryInterface, "UserLocale", 1033)
|
||||
if err != nil {
|
||||
initErrCh <- fmt.Errorf("failed to set ClientApplicationID: %w", err)
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
_, err = oleutil.PutProperty(musQueryInterface, "ClientApplicationID", "windows_exporter")
|
||||
if err != nil {
|
||||
initErrCh <- fmt.Errorf("put ClientApplicationID: %w", err)
|
||||
initErrCh <- fmt.Errorf("failed to set ClientApplicationID: %w", err)
|
||||
|
||||
return
|
||||
}
|
||||
@@ -320,7 +337,7 @@ func (c *Collector) scheduleUpdateStatus(ctx context.Context, logger *slog.Logge
|
||||
}
|
||||
|
||||
func (c *Collector) fetchUpdates(logger *slog.Logger, usd *ole.IDispatch) ([]prometheus.Metric, error) {
|
||||
metricsBuf := make([]prometheus.Metric, 0, len(c.metricsBuf))
|
||||
metricsBuf := make([]prometheus.Metric, 0, len(c.metricsBuf)*2+1)
|
||||
|
||||
timeStart := time.Now()
|
||||
|
||||
@@ -367,10 +384,22 @@ func (c *Collector) fetchUpdates(logger *slog.Logger, usd *ole.IDispatch) ([]pro
|
||||
c.pendingUpdate,
|
||||
prometheus.GaugeValue,
|
||||
1,
|
||||
update.identity,
|
||||
update.revision,
|
||||
update.category,
|
||||
update.severity,
|
||||
update.title,
|
||||
))
|
||||
|
||||
if update.lastPublished != (time.Time{}) {
|
||||
metricsBuf = append(metricsBuf, prometheus.MustNewConstMetric(
|
||||
c.pendingUpdateLastPublished,
|
||||
prometheus.GaugeValue,
|
||||
float64(update.lastPublished.Unix()),
|
||||
update.identity,
|
||||
update.revision,
|
||||
))
|
||||
}
|
||||
}
|
||||
|
||||
metricsBuf = append(metricsBuf, prometheus.MustNewConstMetric(
|
||||
@@ -383,9 +412,12 @@ func (c *Collector) fetchUpdates(logger *slog.Logger, usd *ole.IDispatch) ([]pro
|
||||
}
|
||||
|
||||
type windowsUpdate struct {
|
||||
category string
|
||||
severity string
|
||||
title string
|
||||
identity string
|
||||
revision string
|
||||
category string
|
||||
severity string
|
||||
title string
|
||||
lastPublished time.Time
|
||||
}
|
||||
|
||||
// getUpdateStatus retrieves the update status of the given item.
|
||||
@@ -423,10 +455,48 @@ func (c *Collector) getUpdateStatus(updd *ole.IDispatch, item int) (windowsUpdat
|
||||
return windowsUpdate{}, fmt.Errorf("get Title: %w", err)
|
||||
}
|
||||
|
||||
// Get the Identity object
|
||||
identityVariant, err := oleutil.GetProperty(updateItem, "Identity")
|
||||
if err != nil {
|
||||
return windowsUpdate{}, fmt.Errorf("get Identity: %w", err)
|
||||
}
|
||||
|
||||
identity := identityVariant.ToIDispatch()
|
||||
defer identity.Release()
|
||||
|
||||
// Read the UpdateID
|
||||
updateIDVariant, err := oleutil.GetProperty(identity, "UpdateID")
|
||||
if err != nil {
|
||||
return windowsUpdate{}, fmt.Errorf("get UpdateID: %w", err)
|
||||
}
|
||||
|
||||
revisionVariant, err := oleutil.GetProperty(identity, "RevisionNumber")
|
||||
if err != nil {
|
||||
return windowsUpdate{}, fmt.Errorf("get RevisionNumber: %w", err)
|
||||
}
|
||||
|
||||
lastPublished, err := oleutil.GetProperty(updateItem, "LastDeploymentChangeTime")
|
||||
if err != nil {
|
||||
return windowsUpdate{}, fmt.Errorf("get LastDeploymentChangeTime: %w", err)
|
||||
}
|
||||
|
||||
lastPublishedDate, err := ole.GetVariantDate(uint64(lastPublished.Val))
|
||||
if err != nil {
|
||||
c.logger.Debug("failed to convert LastDeploymentChangeTime",
|
||||
slog.String("title", title.ToString()),
|
||||
slog.Any("err", err),
|
||||
)
|
||||
|
||||
lastPublishedDate = time.Time{}
|
||||
}
|
||||
|
||||
return windowsUpdate{
|
||||
category: categoryName,
|
||||
severity: severity.ToString(),
|
||||
title: title.ToString(),
|
||||
identity: updateIDVariant.ToString(),
|
||||
revision: strconv.FormatInt(revisionVariant.Val, 10),
|
||||
category: categoryName,
|
||||
severity: severity.ToString(),
|
||||
title: title.ToString(),
|
||||
lastPublished: lastPublishedDate,
|
||||
}, nil
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user