mirror of
https://github.com/prometheus-community/windows_exporter.git
synced 2026-10-17 10:09:05 +02:00
collector: preserve fatal causes in joined build errors (#2599)
Signed-off-by: Jan-Otto Kröpke <mail@jkroepke.de>
This commit is contained in:
@@ -280,14 +280,7 @@ func (c *Collection) Build(ctx context.Context, logger *slog.Logger) error {
|
||||
|
||||
// errors.ErrUnsupported marks a collector whose subsystem is not
|
||||
// available on this host, e.g. a Windows feature that is not installed.
|
||||
if errors.Is(err, errors.ErrUnsupported) ||
|
||||
errors.Is(err, pdh.ErrNoData) ||
|
||||
errors.Is(err, winregistry.ErrNotExist) ||
|
||||
errors.Is(err, pdh.NewPdhError(pdh.CstatusNoObject)) ||
|
||||
errors.Is(err, pdh.NewPdhError(pdh.CstatusNoCounter)) ||
|
||||
errors.Is(err, mi.MI_RESULT_INVALID_OPERATION_TIMEOUT) ||
|
||||
errors.Is(err, mi.MI_RESULT_INVALID_NAMESPACE) ||
|
||||
errors.Is(err, mi.MI_RESULT_INVALID_CLASS) {
|
||||
if expectedBuildError(err) {
|
||||
logger.LogAttrs(ctx, slog.LevelWarn, "couldn't initialize collector",
|
||||
slog.Any("err", err),
|
||||
)
|
||||
@@ -421,3 +414,31 @@ func (c *Collection) WithCollectors(collectors []string) (*Collection, error) {
|
||||
func (c *Collection) GetStartTime() gotime.Time {
|
||||
return c.startTime
|
||||
}
|
||||
|
||||
// expectedBuildError tolerates an error tree only if every independent cause is
|
||||
// an expected initialization failure for an optional Windows subsystem.
|
||||
func expectedBuildError(err error) bool {
|
||||
if joined, ok := err.(interface{ Unwrap() []error }); ok {
|
||||
causes := joined.Unwrap()
|
||||
for _, cause := range causes {
|
||||
if !expectedBuildError(cause) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
return len(causes) != 0
|
||||
}
|
||||
|
||||
if wrapped, ok := err.(interface{ Unwrap() error }); ok {
|
||||
return expectedBuildError(wrapped.Unwrap())
|
||||
}
|
||||
|
||||
return errors.Is(err, errors.ErrUnsupported) ||
|
||||
errors.Is(err, pdh.ErrNoData) ||
|
||||
errors.Is(err, winregistry.ErrNotExist) ||
|
||||
errors.Is(err, pdh.NewPdhError(pdh.CstatusNoObject)) ||
|
||||
errors.Is(err, pdh.NewPdhError(pdh.CstatusNoCounter)) ||
|
||||
errors.Is(err, mi.MI_RESULT_INVALID_OPERATION_TIMEOUT) ||
|
||||
errors.Is(err, mi.MI_RESULT_INVALID_NAMESPACE) ||
|
||||
errors.Is(err, mi.MI_RESULT_INVALID_CLASS)
|
||||
}
|
||||
|
||||
@@ -72,6 +72,10 @@ func TestCollectionBuildAndClose(t *testing.T) {
|
||||
{name: "optional counter missing", buildErr: pdh.ErrNoData},
|
||||
{name: "unsupported on this host", buildErr: fmt.Errorf("feature missing: %w", errors.ErrUnsupported)},
|
||||
{name: "close failure", closeErr: closeFailure},
|
||||
{name: "all expected joined errors", buildErr: errors.Join(errors.ErrUnsupported, pdh.ErrNoData)},
|
||||
{name: "joined fatal error", buildErr: errors.Join(errors.ErrUnsupported, buildFailure), wantBuildErr: buildFailure},
|
||||
{name: "nested fatal error", buildErr: errors.Join(pdh.ErrNoData, fmt.Errorf("nested: %w", errors.Join(errors.ErrUnsupported, buildFailure))), wantBuildErr: buildFailure},
|
||||
{name: "multiple wrapped fatal error", buildErr: fmt.Errorf("%w and %w", errors.ErrUnsupported, buildFailure), wantBuildErr: buildFailure},
|
||||
} {
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
Reference in New Issue
Block a user