Skip to content

Commit

Permalink
[receiver/hostmetrics] Continue scraping filesystem metric with parti…
Browse files Browse the repository at this point in the history
…tions info available (open-telemetry#14734)

In case an error is returned while gathering partitions information, try to keep going if any subset of partitions was provided.
  • Loading branch information
atoulme authored and shalper2 committed Dec 6, 2022
1 parent 9a66bc6 commit 2d207f0
Show file tree
Hide file tree
Showing 3 changed files with 89 additions and 6 deletions.
16 changes: 16 additions & 0 deletions .chloggen/use_partitions_provided_if_possible.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
# One of 'breaking', 'deprecation', 'new_component', 'enhancement', 'bug_fix'
change_type: bug_fix

# The name of the component, or a single word describing the area of concern, (e.g. filelogreceiver)
component: hostmetricsreceiver

# A brief description of the change. Surround your text with quotes ("") if it needs to start with a backtick (`).
note: Allow to continue collecting partition information even if an error is returned

# One or more tracking issues related to the change
issues: [14315]

# (Optional) One or more lines of additional information to render under the primary note.
# These lines will be padded with 2 spaces and then inserted directly into the document.
# Use pipe (|) for multiline entries.
subtext: Log the error and continue if partition information, however incomplete, was provided.
Original file line number Diff line number Diff line change
Expand Up @@ -78,11 +78,14 @@ func (s *scraper) scrape(_ context.Context) (pmetric.Metrics, error) {

// omit logical (virtual) filesystems (not relevant for windows)
partitions, err := s.partitions( /*all=*/ false)
var errors scrapererror.ScrapeErrors
if err != nil {
return pmetric.NewMetrics(), scrapererror.NewPartialScrapeError(err, metricsLen)
if len(partitions) == 0 {
return pmetric.NewMetrics(), scrapererror.NewPartialScrapeError(err, metricsLen)
}
errors.AddPartial(0, fmt.Errorf("failed collecting partitions information: %w", err))
}

var errors scrapererror.ScrapeErrors
usages := make([]*deviceUsage, 0, len(partitions))
for _, partition := range partitions {
if !s.fsFilter.includePartition(partition) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,8 @@ func TestScrape(t *testing.T) {
newErrRegex string
initializationErr string
expectedErr string
failedMetricsLen *int
continueOnErr bool
}

testCases := []testCase{
Expand Down Expand Up @@ -200,6 +202,62 @@ func TestScrape(t *testing.T) {
partitionsFunc: func(bool) ([]disk.PartitionStat, error) { return nil, errors.New("err1") },
expectedErr: "err1",
},
{
name: "Partitions and error provided",
config: Config{
Metrics: metadata.DefaultMetricsSettings(),
IncludeDevices: DeviceMatchConfig{
Config: filterset.Config{
MatchType: filterset.Strict,
},
Devices: []string{"device_a", "device_b"},
},
ExcludeFSTypes: FSTypeMatchConfig{
Config: filterset.Config{
MatchType: filterset.Strict,
},
FSTypes: []string{"fs_type_b"},
},
},
usageFunc: func(s string) (*disk.UsageStat, error) {
return &disk.UsageStat{
Fstype: "fs_type_a",
}, nil
},
partitionsFunc: func(b bool) ([]disk.PartitionStat, error) {
return []disk.PartitionStat{
{
Device: "device_a",
Mountpoint: "mount_point_a",
Fstype: "fs_type_a",
},
{
Device: "device_b",
Mountpoint: "mount_point_d",
Fstype: "fs_type_c",
},
}, errors.New("invalid partitions collection")
},
expectMetrics: true,
expectedDeviceDataPoints: 2,
expectedDeviceAttributes: []map[string]pcommon.Value{
{
"device": pcommon.NewValueStr("device_a"),
"mountpoint": pcommon.NewValueStr("mount_point_a"),
"type": pcommon.NewValueStr("fs_type_a"),
"mode": pcommon.NewValueStr("unknown"),
},
{
"device": pcommon.NewValueStr("device_b"),
"mountpoint": pcommon.NewValueStr("mount_point_d"),
"type": pcommon.NewValueStr("fs_type_c"),
"mode": pcommon.NewValueStr("unknown"),
},
},
expectedErr: "failed collecting partitions information: invalid partitions collection",
failedMetricsLen: new(int),
continueOnErr: true,
},
{
name: "Usage Error",
usageFunc: func(string) (*disk.UsageStat, error) { return nil, errors.New("err2") },
Expand Down Expand Up @@ -243,12 +301,18 @@ func TestScrape(t *testing.T) {
if isPartial {
var scraperErr scrapererror.PartialScrapeError
require.ErrorAs(t, err, &scraperErr)
assert.Equal(t, metricsLen, scraperErr.Failed)
expectedFailedMetricsLen := metricsLen
if test.failedMetricsLen != nil {
expectedFailedMetricsLen = *test.failedMetricsLen
}
assert.Equal(t, expectedFailedMetricsLen, scraperErr.Failed)
}

return
if !test.continueOnErr {
return
}
} else {
require.NoError(t, err, "Failed to scrape metrics: %v", err)
}
require.NoError(t, err, "Failed to scrape metrics: %v", err)

if !test.expectMetrics {
assert.Equal(t, 0, md.MetricCount())
Expand Down

0 comments on commit 2d207f0

Please sign in to comment.